如何确定线宽均匀的开罗绘图?

how to determine cairo drawing with line width even?

我使用 cr(来自 Gtk 的小部件绘制事件)并且我想使用偶数像素(2、4、6 等)创建一个矩形(或一条线),而不需要任何“上下文转换”。根据this the line will be "around the path". And according to this圆形笔的直径”。

但是在一个矩形中,它是外少内多还是相反?在一条线上,下,左,右?

我理解在奇数线宽中,“围绕路径”意味着 1 在中心,其余的都在周围。 但是在均匀的线宽下,比如当线宽为2时,1个像素在路径里面还是外面?

是否有稳定的方法来确定受影响的像素或它是随机的?

每次笔划都创建两次,首先使用线宽 1,然后使用余数(奇数),这既痛苦又耗时。

But in a rectangle will it be less outside and more inside or the opposite? And in a line will be up,down, left or right?

这条线在路径的两边将具有相同的宽度。如果这不与像素网格对齐,您会得到一些消除锯齿的结果。

I understand that in an odd line width, "around the path" means 1 in the center and the rest are equally around. But in an even line width, as when the line width is 2, will be 1 pixel inside the path or outside?

线宽为 3 时,将在路径的两侧绘制 1.5 个像素。

如果线宽为 4,则在路径的两侧绘制 2 个像素。

也许下面的例子可以更清楚地说明这一点。这是用 Lua 编写的,并使用 LGI 作为 Lua 的 cairo 绑定,但这直接映射到 C API:

local cairo = require("lgi").cairo
s = cairo.ImageSurface(cairo.Format.RGB24, 100, 30)
cr = cairo.Context(s)

cr:set_source_rgb(1, 1, 1)
cr:paint()

cr:set_source_rgb(0, 0, 0)

cr:set_line_width(2)
cr:rectangle(5, 10, 5, 5)
cr:stroke()

cr:set_line_width(6)
cr:rectangle(15, 10, 14, 14)
cr:stroke()

cr:set_line_width(7)
cr:rectangle(40.5, 10.5, 14, 14)
cr:stroke()

cr:set_line_width(7)
cr:rectangle(70, 10, 14, 14)
cr:stroke()

s:write_to_png("out.png")

生成的图像是:

第一个矩形的线宽为2,它是用整数坐标绘制的,所以有例如从 (5, 10) 到 (10, 10) 的一行(顶行)。线的两边画了一半的线宽,所以这条线对应一个"filled rectangle" 从(4, 9) 到(6, 11).

最后一个矩形的线宽为7,也是用整数坐标绘制的。它的顶行从 (70, 10) 到 (70, 24)。由于一半的线宽位于线的两侧,因此 "filled rectangle" 从 (66.5, 6.5) 变为 (73.5, 27.5)。这些数字不是整数,您可以在结果中看到应用了一些抗锯齿。

相比之下,倒数第二个矩形的位置偏移了 0.5。这会导致其 "top line" 的 "filled rectangle" 再次出现在像素网格上。

另请参阅此常见问题条目:https://www.cairographics.org/FAQ/#sharp_lines