Rog*_*ger 14 cocoa nsbezierpath
我正在开发一个自定义控件.其中一个要求是绘制线条.虽然这有效,但我注意到我的1像素宽线看起来并不像1像素宽线 - 我知道,它们不是像素,但你知道我的意思.它们看起来更像是两个或三个像素宽.当我绘制一条带有1像素短划线和2像素间隙的虚线时,这变得非常明显.1像素破折号实际上看起来像小线而不是点.
我已经阅读了Cocoa Drawing文档,虽然Apple提到了setLineWidth方法,但将线宽更改为小于1.0的值只会使线看起来更模糊而不是更薄.
所以,我怀疑还有其他因素会影响我的线条外观.
有任何想法吗?
Fra*_*rew 25
Bezier路径以其路径为中心绘制,因此如果沿X坐标绘制1像素宽的路径,该线实际沿Y坐标绘制{-0.5,0.5}解决方案通常是将坐标偏移0.5,以便该线未在子像素边界中绘制.您应该能够将边界框移动0.5,以获得更清晰的绘图行为.
uli*_*ess 18
弗朗西斯麦格劳已经给出了正确的答案,但自从我做了一次这样的介绍后,我想我会添加一些照片.
这里的问题是Quartz中的坐标位于像素之间的交叉点.填充矩形时这很好,因为坐标内的每个像素都会被填充.但是线条在技术上(数学上)是不可见的.要绘制它们,Quartz必须实际绘制一个具有给定线宽的矩形.此矩形以坐标为中心:
因此,当你要求Quartz描绘一个带有积分坐标的矩形时,它的问题是它只能绘制整个像素.但在这里你看到我们有半像素.所以它的作用是平均颜色.对于50%黑色(线条颜色)和50%白色(背景)线条,它只是以灰色绘制每个像素:
这是您褪色的图纸的来源.修复现在很明显:不要在像素之间绘制,并且通过将点移动半个像素来实现这一点,因此您的坐标位于所需像素的中心:
现在当然只是抵消可能不是你想要的.因为如果将填充的变体与描边的变体进行比较,则笔划向右下方的一个像素变大.如果你是剪裁到矩形,这将切断右下角:
由于人们通常期望矩形在指定的矩形内行程,你通常做的是向中心偏移0.5 ,所以右下角有效地向上移动一个像素.或者,许多绘图应用程序0.5抵消掉从中心,以避免边界和填充(可以看起来很奇怪,当你与透明度图)之间的重叠.
请注意,这仅适用于1x屏幕.2x Retina屏幕实际上表现出不同的问题,因为下面的每个像素实际上是由4个Retina像素绘制的,这意味着它们实际上可以绘制半像素.但是,如果你想要一个尖锐的0.5pt线,你仍然会遇到同样的问题.此外,由于苹果可能在未来推出其他Retina屏幕,例如每个像素由9个Retina像素(3x)或其他任何一个组成,你应该真的不依赖于此.相反,现在有API调用将矩形转换为"支持对齐",无论您运行1x,2x还是虚拟3x,都会为您执行此操作.
PS - 因为我总是把这一切都搞砸了,我把它放在我的网站上:http://orangejuiceliberationfront.com/are-your-rectangles-blurry-pale-and-have-rounded-corners /我将更新和修改此说明并添加更多图像.
答案是(隐藏)在Apple Docs中:
" 为了避免在绘制一个点宽的水平或垂直线时进行抗锯齿处理,如果线条的宽度为奇数个像素,则必须将位置偏移0.5点到整个编号位置的任意一侧 "
隐藏在iOS绘图和打印指南中:iOS绘图概念,但在当前的标准(OS X)可可绘图指南中没有任何特定内容.
至于调用的效果setDefaultLineWidth:
的文档还指出:
" 宽度为0被解释为可以在特定设备上呈现的最细线.实际渲染的线宽可能与指定的宽度相差多达2个设备像素,具体取决于线相对于线的位置.像素网格和当前的抗锯齿设置.线条的宽度也可能受到活动图形上下文的当前变换矩阵中指定的缩放因子的影响. "
我发现一些信息表明这是由抗锯齿引起的.暂时关闭抗锯齿很容易:
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
Run Code Online (Sandbox Code Playgroud)
这给出了清晰的1像素线.绘图后再次打开它.
我尝试了Francis McGrew建议的解决方案,将x坐标偏移0.5,但这对我的线条的外观没有任何影响.
编辑:更具体地说,我单独更改了x和y坐标,并且偏移量为0.5.
编辑2:我一定做错了,因为用0.5的偏移量改变坐标实际上是行得通的.最终结果优于通过关闭抗锯齿获得的结果,因此我将让Francis MsGrew的回答成为可接受的答案.