Rectify latest cairo SVG export

It seems Cairo got updated and its SVG export is now broken in a new and
exciting way. Now it exports documents with dimensionless w/h. The issue
with that is that Cairo thinks that means point @ 72 pt / inch, but
everyone else including the actual svg spec interpret that as raw document
units or pixels, AFAICT completely breaking dpi scaling in common
viewers. Since we have to mess with Cairo's SVG files anyway, we just
fix this as well by re-writing the broken w/h into physical units
according to a hardcoded conversion factor that matches cairo's
hardcoded scale.
modern_python
jaseg 2022-04-24 20:05:29 +02:00
rodzic 766c4eb4b3
commit b42b0e85fa
2 zmienionych plików z 19 dodań i 2 usunięć

Wyświetl plik

@ -151,6 +151,8 @@ def svg_soup(filename):
f.write(str(soup))
def cleanup_gerbv_svg(soup):
soup.svg['width'] = f'{float(soup.svg["width"])/72*25.4:.4f}mm'
soup.svg['height'] = f'{float(soup.svg["height"])/72*25.4:.4f}mm'
for group in soup.find_all('g'):
# gerbv uses Cairo's SVG canvas. Cairo's SVG canvas is kind of broken. It has no support for unit
# handling at all, which means the output files just end up being in pixels at 72 dpi. Further, it
@ -186,15 +188,28 @@ def gerber_difference_merge(ref1, ref2, actual, diff_out=None, composite_out=Non
gerbv_export(ref1, ref1_svg.name, size=size, export_format='svg')
gerbv_export(ref2, ref2_svg.name, size=size, export_format='svg')
gerbv_export(actual, act_svg.name, size=size, export_format='svg')
for var in ['ref1_svg', 'ref2_svg', 'act_svg']:
print(f'=== {var} ===')
print(Path(locals()[var].name).read_text().splitlines()[1])
with svg_soup(ref1_svg.name) as soup1:
if svg_transform1 is not None:
soup1.find('g', attrs={'id': 'surface1'})['transform'] = svg_transform1
svg = soup1.svg
children = list(svg.children)
g = soup1.new_tag('g', attrs={'transform': svg_transform1})
for c in children:
g.append(c.extract())
svg.append(g)
cleanup_gerbv_svg(soup1)
with svg_soup(ref2_svg.name) as soup2:
if svg_transform2 is not None:
soup2.find('g', attrs={'id': 'surface1'})['transform'] = svg_transform2
svg = soup2.svg
children = list(svg.children)
g = soup2.new_tag('g', attrs={'transform': svg_transform2})
for c in children:
g.append(c.extract())
svg.append(g)
cleanup_gerbv_svg(soup2)
defs1 = soup1.find('defs')

Wyświetl plik

@ -473,6 +473,8 @@ def test_svg_export(reference, tmpfile):
ref_svg = tmpfile('Reference export', '.svg')
ref_png = tmpfile('Reference render', '.png')
gerbv_export(reference, ref_svg, origin=bounds[0], size=bounds[1], fg='#000000', bg='#ffffff')
with svg_soup(ref_svg) as soup:
cleanup_gerbv_svg(soup)
svg_to_png(ref_svg, ref_png, dpi=300, bg='white')
out_png = tmpfile('Output render', '.png')