[cairo] Patch to allow Cairo-based software to print to laser cutters on Windows

Rick Yorgason rick at firefang.com
Thu Oct 18 02:12:23 UTC 2018

Hi there,

The current version of Cairo has problems with laser cutters (and maybe 
some other CNC machines) on Windows because it prints all strokes with 
PS_GEOMETRIC, and these devices expect hairline-width strokes (anything 
<= the device's minimum unit size) to be drawn with a PS_COSMETIC pen. 
Otherwise, it etches the material instead of cutting it.

With this patch, I can use Inkscape to set my stroke width to 0.001" and 
it will cut through the material as expected.

This approach is standard across other Windows programs, like Corel or 
Acrobat. Up until now, the workaround in Inkscape has been to export as 
a PDF and then print it with Acrobat, which correctly uses PS_COSMETIC 
for hairline strokes.

This patch should produce prints that look nearly identical to the old 
approach. Any stroke which is larger than 1 unit will be printed with 
the PS_GEOMETRIC pen, as always, and any stroke with a unit size of 0 
will also be "printed" with a PS_GEOMETRIC pen, as always. (I don't know 
if there's any value to printing zero-width strokes at all, but I didn't 
want to assume that no applications exist which rely on that behaviour.) 
Previously, anything between 0 and 1 would get rounded to one of those 
values, and either get printed at the minimum size, or not at all. This 
codifies that anything between the two will get drawn as a PS_COSMETIC 
pen, which is only valid when printing 1 device unit thick.

Tested on an Epilog Fusion and an Epilog Zing.

Let me know if you have any questions!


-------------- next part --------------
--- D:/scratch/Cairo/cairo-1.15.14.orig/src/win32/cairo-win32-printing-surface.c	Wed Sep 19 13:02:10 2018
+++ D:/scratch/Cairo/cairo-1.15.14/src/win32/cairo-win32-printing-surface.c	Wed Oct 17 18:48:02 2018
@@ -1469,0 +1470 @@ _cairo_win32_printing_surface_stroke (void			*abst
+    cairo_bool_t cosmetic;
@@ -1523 +1524,10 @@ _cairo_win32_printing_surface_stroke (void			*abst
-    pen_style = PS_GEOMETRIC;
+    /* If (0 < line_width <= 1 printer unit), we should use PS_COSMETIC instead of PS_GEOMETRIC,
+       because that's what some CNC machines, like laser cutters, expect.
+       There might be some value to using PS_COSMETIC for zero-width lines as well (hairlines), but some
+       applications might be relying on drawing invisible zero-width lines, so we'll leave that use case as is.
+       We're still using geometric pens if we have dashes, because calculating dash lengths for cosmetic pens
+       requires them to be specified in device-specific "style units", and I can't find any documentation on
+       how to query that. */
+    cosmetic = scale * style->line_width > 0 && scale * style->line_width <= 1 && !style->num_dashes;
+    pen_style = cosmetic ? PS_COSMETIC : PS_GEOMETRIC;
@@ -1549,2 +1559,6 @@ _cairo_win32_printing_surface_stroke (void			*abst
-    pen_style |= _cairo_win32_line_cap (style->line_cap);
-    pen_style |= _cairo_win32_line_join (style->line_join);
+    /* Only geometric pens accept cap/join styles, which is fine, because you can't see them at <= 1
+       printer unit anyway. */
+    if (!cosmetic) {
+        pen_style |= _cairo_win32_line_cap (style->line_cap);
+        pen_style |= _cairo_win32_line_join (style->line_join);
+    }
@@ -1552 +1566 @@ _cairo_win32_printing_surface_stroke (void			*abst
-		       scale * style->line_width,
+		       cosmetic ? 1 : scale * style->line_width,

More information about the cairo mailing list