Bug: SVG font-size with absolute CSS units (mm, cm, in) is not converted per SVG specification

SVG font-size with absolute CSS units (mm, cm, in) is not converted per SVG specification

Description:
LightBurn appears to ignore absolute CSS length units on SVG font-size values.

Instead of converting mm to SVG/CSS px units per the SVG specification, LightBurn appears to interpret the numeric value directly. This could be a feature of the viewbox that I’ve specified in the example below, where the user units are equal to 1mm, but this is valid SVG to the best of my knowledge

Expected behaviour (per SVG spec):
SVG uses CSS absolute length conversions:

  • 1 in = 96 px
  • 1 mm = 96 / 25.4 px ≈ 3.7795 px
  • 1 cm = 96 / 2.54 px ≈ 37.795 px

Therefore:

10 mm × 96 / 25.4 ≈ 37.795 px

So:

font-size="10mm"

should render equivalently to:

font-size="37.795px"

Observed behavior:
LightBurn renders font-size="10mm" approximately the same as font-size="10px" resulting in text that is underscaled by approximately 3.78×.

This behaviour is correctly observed in:

Reproduction steps:

  1. Create the SVG below
  2. Open in Inkscape or a web browser
  3. Observe correct rendering size
  4. Open the same file in LightBurn
  5. Observe text rendered approximately 3.78× smaller

Impact:
Text in SVG files appears ~3.78x smaller in LightBurn than intended, making laser engraving text sizes inconsistent with design tools.

Sample SVG

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50mm" height="50mm">
  <rect x="0" y="0" width="50" height="50" fill="none" stroke="black" stroke-width="0.5"/>
  <text x="25" y="25" text-anchor="middle" font-size="10mm" font-family="sans-serif" fill="blue">Test</text>
</svg>

Ok, the code renderer is broken. Try this:

&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50mm" height="50mm">
  &lt;rect x="0" y="0" width="50" height="50" fill="none" stroke="black" stroke-width="0.5"/>
  &lt;text x="25" y="25" text-anchor="middle" font-size="10mm" font-family="sans-serif" fill="blue">Test&lt;/text>
&lt;/svg>

If you look at the settings boxes, you will see Lightburn does not use pixels to size fonts. It uses mm or inches.

Are you saying it does not properly render 10mm SVG text as 10mm text in Lightburn? Can you provide both your .svg and .lbrn2 files that show this for evaluation.

I’ve provided a sample SVG in my previous comment. You’ll get the same importing it into Lightburn (I’m using 2.0.05 which I believe is latest).

After some more investigation:

This SVG has font-size="10px" which renders the same in Inkscape, Lightburn and Chrome. This is also the same size text that you would get by creating text directly in Lightburn and setting it’s height to “10”.

&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50mm" height="50mm">
  &lt;rect x="0" y="0" width="50" height="50" fill="none" stroke="black" stroke-width="0.5"/>
  &lt;text x="25" y="25" text-anchor="middle" font-size="10px" font-family="sans-serif" fill="blue">Test&lt;/text>
&lt;/svg>

Next up, it’s probably worth mentioning that Inkscape lies when you enter 10mm as your text height, and explicitly saves 10px in the SVG that it generates, and if you set it to 10px in the UI, it actually writes 2.64583px to the SVG (which is that same 3.7795px/mm factor again).

This next SVG has font-size="2mm" which renders the same in Inkscape and Chrome, but differently in Lightburn.

&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50mm" height="50mm">
  &lt;rect x="0" y="0" width="50" height="50" fill="none" stroke="black" stroke-width="0.5"/>
  &lt;text x="25" y="25" text-anchor="middle" font-size="2mm" font-family="sans-serif" fill="blue">Test&lt;/text>
&lt;/svg>

Firefox and Opera also match Chrome/Inkscape.

I ran into a similar situation involving SVG scaling in a Python program creating SVG files to print and cut reproduction punched cards.

I eventually used a command-line flag to select the scale factor corresponding to Inkscape or LightBurn:

SVGSCALE = 96.0/25.4            # converts "millimeters as SVG points" to real millimeters
parser.add_argument('--lbsvg', action='store_true',
                    help="Work around LightBurn SVG issues")
… snippage …
transform="scale(" + repr(1.0 if args.lbsvg else SVGSCALE) + ")",
            stroke=Tooling if args.layout == "laser" else CardMark,
            stroke_width=svg.mm(DefStroke if args.lbsvg else DefStroke/SVGSCALE),
            fill="none",
        )
    )

Perhaps SVG scaling has as many dialects as G-Code …

1 Like