弗朗西斯·麦格鲁已经给出了正确的答案,但是因为我曾经做过一次关于这个的演讲,所以我想我会添加一些图片。
这里的问题是 Quartz 中的坐标位于像素之间的交叉点。这在填充矩形时很好,因为位于坐标内的每个像素都会被填充。但是线条在技术上(数学上!)是不可见的。要绘制它们,Quartz 必须实际绘制一个具有给定线宽的矩形。这个矩形以坐标为中心:

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

这就是你褪色的图纸的来源。修复现在很明显:不要在像素之间绘制,您可以通过将点移动半个像素来实现这一点,因此您的坐标以所需像素为中心:

现在当然只是抵消可能不是你想要的。因为如果您将填充的变体与描边的变体进行比较,则描边在右下角大一个像素。如果您要剪裁到矩形,这将切断右下角:

由于人们通常希望矩形在指定的矩形内描边,因此您通常所做的就是向center偏移 0.5 ,因此右下角实际上向上移动了一个像素。或者,许多绘图应用程序从中心偏移 0.5 ,以避免边框和填充之间的重叠(当您使用透明度进行绘图时,这看起来很奇怪)。
请注意,这只适用于 1x 屏幕。2x Retina 屏幕实际上表现出这个问题的方式不同,因为下面的每个像素实际上都是由 4 个 Retina 像素绘制的,这意味着它们实际上可以绘制半个像素。但是,如果您想要一条 0.5pt 的尖线,您仍然会遇到同样的问题。此外,由于 Apple 将来可能会推出其他 Retina 屏幕,例如每个像素由 9 个 Retina 像素 (3x) 组成,或者其他什么,你真的不应该依赖这个。相反,现在有 API 调用将矩形转换为“支持对齐”,无论您是运行 1x、2x 还是虚构的 3x,它都会为您执行此操作。
PS - 因为我把这一切都写完了,我把它放在我的网站上:http: //orangejuiceliberationfront.com/are-your-rectangles-blurry-pale-and-have-rounded-corners /我将在此处更新和修改此描述并添加更多图像。