老谭笔记

由一个像素引发的"血案"

由于项目中经常需要程序绘制各种奇形怪状的自定义控件,所以NSBezierPath是一个非常不错的选择,偶然的机会发现当设置NSBezierPath的lineWidth为1.0时,绘制出来的效果很不理想,如下图所示:

NSBezierPath1

这当然不是我所想要的效果,线条模糊,宽度似乎也不是我想要的1.0个像素,经过多次尝试,发现当NSBezierPath的x坐标和y坐标均处在0.5的位置时效果就令人满意了:

NSBezierPath2

最初我也不求甚解,知道如何应对便可,但每次代码写到此处时,好奇心便又多了一点儿,虽然根据自己经验已经能猜到大概,但仍然去拜读了一下Apple的文档,结果正如心中所料:当我们用整数定义某路径时,路径的坐标总是在两个像素之间的,而NSBezierPath在绘制线条时,线条宽度刚好平均分配在路径两侧,而当宽度为1或其它奇数时,两侧就会出现半像素的情况,并且在非Retina显示下,每一个需要绘制的像素是与屏幕最终显示的单元是一一对应的,如图:

NSBezierPath3

所以结果就导致原本一个像素的内容最终呈现在了两个像素的显示单元上了,最终造成了显示效果并非我们所想要的.而当宽度为偶数时,就恰好可以避免这样的情况:

NSBezierPath4

而当我们将位置设定在0.5个像素的时候,正好可以在路径两边都占用整数个显示单位,如下图:

NSBezierPath5

问题也就迎刃而解了,所以在平时使用NSBezierPath画边框时,这样的写法可以很容易避开这样问题:

1
2
3
4
5
NSRect rect = xx;
CGFloat lineWidth = xx;
NSBezierPath *path = [NSBezierPath bezierPathWithRect:NSInsetRect(rect, lineWidth/2, lineWidth/2)];
[path setLineWidth:lineWidth];
[path stroke];