Scaling moves content and doesn't change page count
My objective is to create a PDF of an html table containing user-defined content that affects both the number of columns and rows in the table. For a selected paper size, the number of columns may cause the content to extend beyond the width of the page. I implemented a user-defined scale that effectively inserts body {-webkit-transform: scale(0.80);} as a style if the user sets the scale to 80%. This has the effect of reducing the height and width of the table to 80% but two undesired side effects occur:
- The left margin width is inversely proportional to the scale. The lower the scale, the greater the left margin width resulting in the right of the table still extending beyond the page width. This seems to be caused by the pdf content centered on the page even though the html page is aligned left. I've experimented with margins for
html,body, and@pagebut these cause other undesired side effects. - The number of table rows per page isn't increased when the content is scaled down resulting in the same number of pages consumed and content having greater top and bottom margins.
Is there a solution for reducing the scale of the content but keeping a consistent margin on all sides of the content regardless of scale?
@wardjk yes, there is, but not with stock dompdf.
I patched dompdf to allow this and it's working fine for several years now :) With this patch you can even scale the content to fit on one single page.
It basically renders the pdf twice. In the first step it collects the maximum draw position in the canvas class and in the second step it renders the PDF using this new values as the paper size (using $dompdf->set_paper()).
I can provide you with the details/code, if you want :)
Great. I'm guessing that as it is now, dompdf first decides the content for each page then performs the scaling rather than the other way around in which case it's a good thing my users are not likely scale up instead which would cause the content to exceed both the page width and height.
How can I get your solution?
@wardjk you are correct, scaling occurs after the page layout is complete. But more importantly scaling only affect the visual appearance of the element, not it's layout on the page.
From the W3C Transform spec:
Note: Transformations do affect the visual layout on the canvas, but have no affect on the CSS layout itself.
@wardjk I'll create a github project for this :) I think this would be the simplest solution. And maybe we even can get some of this changes upstream :)
@wardjk done. You can get it here: https://github.com/tmolitor-stud-tu/dompdf/tree/0.6.2-scaling See render_scaled_pdf.php for an example using this patched version. If you have any questions: feel free to ask :)
@wardjk did you test my solution?
I just returned to this project to try your solution. Thanks for making it available. After replacing dompdf-0.6.2 with dompdf-0.6.2-scaling, I also copied dompdf/lib/php-font-lib from dompdf-0.6.2 which was trivial.
Upon running $dompdf->render(), I encountered Undefined offset: 1 ...dompdf\include\cpdf_adapter.cls.php(279)
276 protected function _update_yscaleflags($args=array())
277 {
278 foreach($args as $entry)
279 $this->_yscaleflag[$this->_page_number]=max($this->_yscaleflag[$this->_page_number], $this->y($entry));
280 }
Stack Trace
cpdf_adapter.cls.php(635):
635 $this->_update_yscaleflags(array($y));
page_frame_reflower.cls.php(130):
130 $this->_frame->get_renderer()->render($child);
While debugging, I only got as far as discovering that the $_yscaleflag array is empty and the $args array contains one float value. I haven't investigated further.
Well, that seems to be a php notice. In my environment notices are turned off via error_reporting().
If you don't want to turn off notices, you can just use this:
$this->_yscaleflag[$this->_page_number]=max(isset($this->_yscaleflag[$this->_page_number]) ? $this->_yscaleflag[$this->_page_number] : 0, $this->y($entry));
I added your suggestion which eliminated the problem.
My scaling test using dompdf-0.6.2-scaling didn't produce the desired results. At 100% scaling, my test table requires 3 pages. At 50% scaling, 3 pages are still consumed and the number of rows per page is the same even though the page contents are scaled down. This is the same result as with dompdf-0.6.2.
@wardjk What html did you try to scale? And how did you invoke my code?
My changes only make it possible to have everything on one page or everything on multiple pages (always ensuring the content is not overflowing the right edge of a page).
If you want to do continous scaling by percent values, my approach isn't what you need (but it could be changed to allow percent scaling as well, I think).
Just noting, an appropriate modification to Dompdf to support this would be to implement the zoom CSS property.