Cocoa 如何使用NSBezierPath获得1像素线?

Cocoa 如何使用NSBezierPath获得1像素线?,cocoa,nsbezierpath,Cocoa,Nsbezierpath,我正在开发一个自定义控件。其中一个要求是画线。虽然这是可行的,但我注意到我的1像素宽的线条看起来不像1像素宽的线条-我知道,它们不是真正的像素,但你知道我的意思。它们看起来更像两三个像素宽。当我用一个1像素的短划线和一个2像素的间隙画一条虚线时,这变得非常明显。1像素的虚线实际上看起来像细小的线条,而不是圆点 我已经阅读了Cocoa绘图文档,尽管Apple提到了setLineWidth方法,但将线宽更改为小于1.0的值只会使线条看起来更模糊,而不是更细 所以,我怀疑还有其他因素影响我的线条 有什

我正在开发一个自定义控件。其中一个要求是画线。虽然这是可行的,但我注意到我的1像素宽的线条看起来不像1像素宽的线条-我知道,它们不是真正的像素,但你知道我的意思。它们看起来更像两三个像素宽。当我用一个1像素的短划线和一个2像素的间隙画一条虚线时,这变得非常明显。1像素的虚线实际上看起来像细小的线条,而不是圆点

我已经阅读了Cocoa绘图文档,尽管Apple提到了setLineWidth方法,但将线宽更改为小于1.0的值只会使线条看起来更模糊,而不是更细

所以,我怀疑还有其他因素影响我的线条


有什么想法吗?

贝塞尔路径是以其路径为中心绘制的,因此,如果沿X坐标绘制一条1像素宽的路径,该线实际上是沿Y坐标{-0.5,0.5}绘制的。解决方案通常是将坐标偏移0.5,这样该线就不会在子像素边界中绘制。您应该能够将边界框移动0.5以获得更清晰的绘图行为。

我发现一些信息表明这是由抗锯齿造成的。暂时关闭抗锯齿很容易:

[[NSGraphicsContext currentContext] setShouldAntialias: NO];
这将产生一条清晰的1像素线。画完后,再打开它

我尝试了Francis McGrew建议的解决方案,将x坐标偏移为0.5,但这对我的线条外观没有任何影响

编辑: 更具体地说,我分别更改了x和y坐标,并将偏移量设置为0.5

编辑2: 我一定是做错了什么,因为用0.5的偏移量改变坐标确实有效。最终结果比通过关闭抗锯齿获得的结果要好,因此我将让Francis Msgrow的答案成为公认的答案。

答案(隐藏)在Apple文档中:

为避免在绘制一点宽的水平线或垂直线时出现抗锯齿,如果该线的宽度为奇数像素,则必须将该位置偏移0.5个点至整编号位置的任一侧

隐藏在中,但在当前的标准(OS X)中找不到任何特定的内容

至于调用
setDefaultLineWidth:

“宽度0被解释为可以在特定设备上渲染的最细线条。根据线相对于像素网格的位置和当前抗锯齿设置,实际渲染线宽可能与指定宽度相差多达2个设备像素。线条的宽度也可能受到活动图形上下文的当前变换矩阵中指定的缩放因子的影响。”

Francis McGrew已经给出了正确的答案,但是因为我曾经做过一次关于这方面的演示,我想我应该添加一些图片

这里的问题是石英中的坐标位于像素之间的交点处。填充矩形时这很好,因为位于坐标内的每个像素都会被填充。但从技术上讲,线条是(数学上!)不可见。要绘制它们,Quartz必须实际绘制一个具有给定线宽的矩形。该矩形位于坐标的中心:

因此,当你让Quartz用整数坐标画一个矩形时,它的问题是它只能画整个像素。但在这里你看到我们有一半像素。所以它所做的是平均颜色。对于50%的黑色(线条颜色)和50%的白色(背景)线条,它只是用灰色绘制每个像素:

这就是你被洗掉的图形的来源。修复方法现在很明显:不要在像素之间绘制,你可以通过将点移动半个像素来实现这一点,因此你的坐标位于所需像素的中心:

当然,偏移可能不是您想要的。因为如果您将填充变量与笔划变量进行比较,笔划会朝右下角大一个像素。例如,如果您剪切到矩形,这将切断右下角:

由于人们通常期望矩形在指定的矩形内进行笔划,因此通常要做的是向中心偏移0.5,因此右下角有效地向上移动一个像素。或者,许多绘图应用程序向中心偏移0.5,以避免边框和填充之间的重叠(在使用透明度绘制时,这可能看起来很奇怪)

请注意,这仅适用于1x屏幕。2x视网膜屏幕实际上表现出不同的问题,因为下面的每个像素实际上是由4个视网膜像素绘制的,这意味着它们实际上可以绘制半像素。但是,如果你想要一条0.5pt的锐线,你仍然会遇到同样的问题。另外,因为苹果可能会在未来引入uce其他视网膜屏幕,例如,每个像素由9个视网膜像素(3x)或其他什么组成,你真的不应该依赖它。相反,现在有API调用将矩形转换为“背向对齐”,无论你运行的是1x、2x还是虚构的3x,它都会为你实现这一点


PS-自从我费劲地写了这篇文章之后,我就把它放在了我的网站上:在那里我将更新和修改这篇描述,并添加更多的图片。

有了一个框,你通常想把它插入或开始它的笔划宽度的一半,而不是移动它。事实上,令人惊讶的是,苹果没有记录这样一个重要的方面。可可和石英绘图指南涵盖了这一点。回答很好!也许是“采用”的最佳解决方案“1x像素,Apple文档中的检测过程:对于0宽度,我已经尝试过了,只得到了最细的线而没有线。@Unome Yay.Retina或plain old display..?非视网膜显示。视网膜显示良好。编辑:视网膜显示不显示模糊线,但是如果设置宽度