typemytype / drawbot

http://www.drawbot.com
Other
398 stars 62 forks source link

Add svg resoltion options #428

Open typemytype opened 3 years ago

typemytype commented 3 years ago

Requested by @MauriceMeilleur:

Is it possible to add units and resolution as options for .svg export in saveImage()? I have a very niche reason for asking: I want to use exported .svg files with a plotter, and it might make the files easier to use if the units/resolution (effectively, scale) information in the .svg file.

Specifically, I want to plot .svg outputs with an AxiDraw, and I'm having trouble convincing Inkscape that the files should be treated as 72dpi rather than stubbornly insisting (1) that they are sized in pixels, not DTP, and (2) that it should treat them as if they're 96ppi.

https://forum.drawbot.com/topic/312/svg-resolution-units-options-for-saveimage

add an option here https://github.com/typemytype/drawbot/blob/master/drawBot/context/svgContext.py#L265-L267

and use the input value during saveImage of the svg context --> https://github.com/typemytype/drawbot/blob/master/drawBot/context/svgContext.py#L330

@ MauriceMeilleur could you provide some info what the svg xml tag is and possible options?

MauriceMeilleur commented 3 years ago

Doing some research on that now. Weirdly, it's hard to find that kind of documentation—at least the way I'm looking, maybe.

The tag is 'units', but I don't know all the options.

MauriceMeilleur commented 3 years ago

But searching specifically for xml tags helped. I think our options are here: https://www.w3.org/TR/SVG2/coords.html

MauriceMeilleur commented 3 years ago

… and the W3C .svg structure documentation is here: https://www.w3.org/TR/SVG2/struct.html

justvanrossum commented 3 years ago

Are you saying that replacing

<svg width="300" height="400" viewBox="0 0 300 400" ...>

with

<svg width="300pt" height="400pt" viewBox="0pt 0pt 300pt 400pt" ...>

Would fix your problem? Or if you aren't, could you try to see if it does?

MauriceMeilleur commented 3 years ago
newPage('LetterLandscape')
stroke(0)
fill(None)
path = BezierPath()
path.rect(72, 108, 432, 432)
drawPath(path)
saveImage('~/Desktop/axi_test.svg')

yields the following .xml file:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="792" height="612" viewBox="0 0 792 612" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <path d="M72,108 l432,0 l0,432 l-432,0 Z M72,108" fill="none" stroke="rgb(0,0,0)" stroke-width="1" transform="matrix(1,0,0,-1,0,612)"/>
</svg>

Adding pt to width, height, viewBox measurements sets the page size properly when I open the file in Inkscape, but leaves the rectangle the same (wrong) size and position. When I add pt to its path's measurements, I somehow lose the path.

justvanrossum commented 3 years ago

Can you try only adding "pt" to the width and height values, and not to viewBox?

MauriceMeilleur commented 3 years ago

That does the trick. Conversion values are a little off: .993 instead of 1in, 6.014 instead of 6in, presumably because of whatever math is happening under Inkscape's hood.

justvanrossum commented 3 years ago

Since DrawBot works in points, it may make sense to always add "pt" to the width and height values. If that's somehow problematic for other uses, perhaps it could indeed be a keyword argument to saveImage(), say svgUnits, which defaults to "pt".

MauriceMeilleur commented 3 years ago

For what it's worth, Illustrator also works in pxs=pts, so the AxiDraw folks had to create an extension for Inkscape to convert .svg files made in Illustrator properly that also works on .svgs out of DB.

typemytype commented 3 years ago

Im unable to test or check: but the conclusion is that adding pt to the width and height arguments of the svg tags resolves this issue?

like this?

...
<svg width="792pt" height="612pt" viewBox="0 0 792 612" version="1.1"
...
MauriceMeilleur commented 3 years ago

Pretty sure that's right. I have DB stuck in a massive render, but I'll confirm as soon as I can.