Closed ThomasJunk closed 5 years ago
svg2pdf does not support units, which means it treats all dimensions in the svg as if given in the unit that was passed to jsPDF. So in your example this means:
So for any dimension n
, the resulting dimension n'
is:
n' = n * (dpi/25.4) * (25.4/dpi) * (72/25.4)
n' = n * (72/25.4)
So, in order to receive the same dimensions in the output as in the input you must scale the input additionally by 25.4/72
, which, if you reduce the formula, basically means you convert the millimeters on your device (and its DPI) to PDF's 72 units per inch.
Sorry, I am having a bit of a hard time with this.
Setting the scale to 1
and the unit to mm
and leaving the rest as is - like I did in index3.html
(see gist- the result is in an expected range a box of 9x mm. Even the stroke-width
is 1mm.
From what you have written, I would have expected
you set the unit of jsPDF to "mm" (resulting in a scale of ´72/25.4`)
which seems not to be the case. From what you have written, I would have expected to do a rescale. Or am I misunderstanding you?
Edit: Further: if I scale papersize and increase the scalefactor proportionally I get the invariant result.
I'm having a hard time understanding what you mean, too. Maybe I try to clarify what I mean by
svg2pdf does not support units, which means it treats all dimensions in the svg as if given in the unit that was passed to jsPDF.
svg2pdf treats
<rect width="100px" height="100px"/>
exactly like
<rect width="100mm" height="100mm"/>
and the output is exactly the same. This means in your index2.html, the width/height you converted to px
are interpreted as mm
by svg2pdf.
Setting the unit of jsPDF to mm
produces the same results as if you would set svg2pdf's scale to 72/24.5
(apart from the page size, of course, which is also interpreted in the given unit).
You can prove the correct behavior of svg2pdf by setting the page width/height to the width/height of the rect (plus some margins so can actually see the rect):
const svgElement = document.querySelector("svg");
const width = 100 + 20;
const height = 100 + 20;
// create a new jsPDF instance
const pdf = new jsPDF("l", "mm", [width, height]);
// render the svg element
svg2pdf(svgElement, pdf, {
xOffset: 0,
yOffset: 0,
scale: 1
});
The resulting rect fits exactly into the page, which is 120x120mm large.
Thanks, for taking the time! :+1:
I'm having a hard time understanding what you mean, too. The niceties of textual conversation. :D
What I observed is, what you have written. If I have a rect like:
<rect width="100" height="100" />
set the scale to 1
, the unit to mm
and the dimensions 297x210
: the result is a rectangle from the expected dimensions (actually it is smaller by a factor of x where I am trying to understand where it comes from). That is fine.
If I leave the width
and height
at 100
but scale the papersize up and set the scale accordingly up,
e.g. 297*3
, 210*3
and scale 3
and print that out again, it works as expected.
If I change the width
and height
of the rect by a factor of 10
to 1000
(leaving the papersize at 297x210
) and scale down accordingly to 0.1
the outputsize is as expected.
Aside: my example SVG was a quick Inkscape scribble and had a given stroke width of 1.
If I set the papersize 297x210
, the units to mm
and the scale to 1
, I get the expected result, including the line width of 1mm
. Additionally, if I set the width
and height
of the rectangle to 1000
and increase the stroke's width to 10
and set the scale to 0.1
, the result is as expected:
a 10 by 10 square with a stroke width of 1mm .
Does that make any sense so far?
That said leads me to the assumption:
When increasing the pixels on screen, I have to use the inverse factor as scale.
I calculate millimeter2pixels and set the scale with converting 1 pixel to n millimeters.
For debugging purposes I draw a rect
and checked the results.
That seems to work so far: It scales well. But my initial problem is that the result on the printer doesn't quite match the dimensions given. As said above: The rect is in fact 9 x not 100mm. And until now, I assumed that this is due to scaling factor issues, which could be ruled out by now, I think.
OTOH: I am having the issue accross printers. So I would rule out that accordingly.
Just a thought: This might be an issue with the printing process and an automatic "fit page into printable area" feature of your PDF printer or printer driver. Did you measure the size of the resulting rectangle in the PDF?
So if I understand you correctly, the rect has the correct size when you view the PDF in a PDF viewer but has an incorrect size when you print it out? Then I must agree with @yGuy: this is probably because of your printing process scaling the PDF to fit the page size.
"fit page into printable area" feature of your PDF printer or printer driver.
Printer I rule out at this point.
But printer driver / PDF Viewer seems to be to blame. Indeed.
I actually made a rectangle 297x210
and it looked fine on sceen.
What I have learned:
you set the unit of jsPDF to "mm" (resulting in a scale of 72/25.4)
seems not to hold (see 1
)
Aside: To put my given d3 chart with a fixed DPI on paper there are further things to be scaled accordingly I am closing here. Thank you very much for your patience!
Describe the bug Given dimensions of diagram do not work as expected when using
mm
as unit in jsPDFTo Reproduce I prepared two minimal exaples as a gist
index1.html
shows a version with unitpt
the example was taken from the site here:0.352778
is the conversion factor of1pt
tomm
. Using this, the resulting rectangle is nearly10mm
(a bit off, perhaps due to rounding errors)index2html
shows a version withmm
. If I take the desired output inmm
and retrofit that on the screen, I usemillimeter2pixel
as a conversion function to calculate a given amount of pixels. The scale factor should be the inversepixel2millimeter(1, DPI)
. The result isn't 210x100 mm wide.Expected behavior Using
mm
as a unit, the result should be 210x100 mm wide.Additional Info From my understanding it shouldn't matter whether I calculate to pixels and scale accordingly.