|
Rank: Newbie Groups: Member
Joined: 6/19/2014 Posts: 9
|
Hi,
I am trying to generate a pdf that contains tabulated data with sub-total lines. Using AcmTable and Row/Cell, I can relatively easily get what I'm looking for except when it comes to page breaks.
Ideally, I'd like to be able to tell the renderer where it can insert a page break (a bit like the css page-break-before/after/inside). Failing that, how can I compute the height of specific rows (that may have text wrapped inside cells) so that I can manually insert a page break (I can't seem to find any method that would allow be to compute a given text size given its font for example)
Apparently the html-to-pdf api sort of supports that, but I don't want to go through the double penalty of generating an html string to have it later parsed by Eo.Pdf when I have structured data in the first place and can directly use the AcmRenderer.
Thanks
Blaise
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi, The only way for you to compute the height of a content is to render it. Once you render it, you will be able to get the height of the content by calling this function on two consecutive AcmContent to get the height of the first content: http://www.essentialobjects.com/doc/4/eo.pdf.acm.acmcontent.createdestination.aspxOnce you have the PdfDestination object, you can use it's FitRect.Y1 property to get the top location of the content. Note that FitRect.X2/Y2 is not used, so you can not use Y2 - Y1 to get the height. Also please keep in mind that in case a paging occurred, you must count the pages in between. Another thing you might want to try is this class: http://www.essentialobjects.com/doc/4/eo.pdf.acm.acmpagebreak.aspxI agree with you that while the easiest way for to achieve best result might be to use the HTML to PDF feature but that does introduce a double penalty. However what the ACM objects can do is very limited --- it was designed to complement HTML to PDF so that for complex contents you can use HTML to PDF but for simple contents such as footer/header, you can use ACM to do it much faster. As a side note, we do have an internal build ready that exposed TextLeading property. That property were already there but wasn't exposed. It will be available in our next build. Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 6/19/2014 Posts: 9
|
Thanks for your answer. So I did a quick benchmark :
1) Using Acm api: First save : 6101 ms Next 10 saves : 30317 ms
2) Using Html2Pdf api (that is constructing a string buffer and feeding it to the api) First save : 6167 ms Next 10 saves : 34669 ms
The performance hit is negligible and the document size is actually smaller (184kb vs 214kb)
so it seems like a valid option.
BUT (there is always a but)
One thing I cannot manage to to with html2pdf is to specify borders smaller than 1pt.
In Acm api, I could specify 0.5pt borders
In html, if I specify a 1pt border it shows fine (.bottomborder { border-bottom: 1pt solid #CD171B; } ) If I specify a 0.5pt border nothing is displayed. ( .bottomborder { border-bottom: 0.5pt solid #CD171B; } )
Is this expected ? Do you have a workaround ?
Thanks
Blaise
|
|
Rank: Newbie Groups: Member
Joined: 6/19/2014 Posts: 9
|
One other point : the Html2Pdf api appears to be doing some scaling that I cannot disable. The 10pt font inside my html ends up beeing a 9.8pt font in the rendered pdf. There should be no scaling involved as the html width is set up to be the exact width of the outputarea. And I even set AutoFitX = HtmlToPdfAutoFitMode.None but the font is still scaled down. Steps to reproduce :
Code: C#
PdfDocument doc = new PdfDocument();
StringBuilder sb = new StringBuilder();
sb.AppendLine(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">");
sb.AppendLine(@"<html>");
sb.AppendLine(@"<head>");
sb.AppendLine(@"<style type=""text/css"">");
sb.AppendLine(@"body { font: 10pt 'Segoe UI'; margin: 0; padding: 0 }");
sb.AppendLine(@"</style>");
sb.AppendLine(@"</head>");
sb.AppendLine(@"<body>");
sb.Append("<div>").Append("Lorem Ipsum").AppendLine("</div>");
sb.AppendLine(@"</body>");
sb.AppendLine(@"</html>");
HtmlToPdfResult r = HtmlToPdf.ConvertHtml(sb.ToString(), doc);
doc.Save("Test.pdf");
If you inspect the resulting pdf (PDF-Exchange Viewer allows you to see the font associated to a selected text), you'll see that the font size is 9.8pt instead of 10pt. It's probably a problem of converting pt to px then back again to pt, and might be fixed by setting some dpi value somewhere, but I couldn't find where. Thanks Blaise
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi, Yes. By default it does automatic scaling. See here for more details: http://www.essentialobjects.com/doc/4/htmltopdf/auto_fit.aspxYou can turn it off by setting AutoFitX to None. Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 6/19/2014 Posts: 9
|
Like I said in my previous post, setting HtmlToPdf.Options.AutoFitX = HtmlToPdfAutoFitMode.None doesn't change anything If you try the following code, you should be able to reproduce :
Code: C#
StringBuilder sb = new StringBuilder();
sb.AppendLine(@"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">");
sb.AppendLine(@"<html>");
sb.AppendLine(@"<head>");
sb.AppendLine(@"<style type=""text/css"">");
sb.AppendLine(@"body { font: 10pt 'Segoe UI'; margin: 0; padding: 0 }");
sb.AppendLine(@"</style>");
sb.AppendLine(@"</head>");
sb.AppendLine(@"<body>");
sb.Append("<div>").Append("Lorem Ipsum").AppendLine("</div>");
sb.AppendLine(@"</body>");
sb.AppendLine(@"</html>");
HtmlToPdf.Options.AutoFitX = HtmlToPdfAutoFitMode.None;
HtmlToPdfResult r = HtmlToPdf.ConvertHtml(sb.ToString(), doc);
doc.Save("Test.pdf");
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Hi,
Sorry that I didn't read your previous post carefully and missed the fact that you have already set AutoFitX to None. You probably should avoid using pt. What you have mentioned in your previous post is correct: the HTML engine always align to pixels (which obviously has to do with your DPI setting). This is necessary for the engine to produce pixel accurate rendering on screen, which is always the #1 priority for a HTML rendering engine. The ACM interface bypasses the HTML engine so it does not have this problem.
For the HTML engine, since everything is rounded to pixel and 1pt is 1/72 inches, so at a screen DPI of 96 (the default window DPI value), 0.5 pt would be less than one pixel, and it seems that the HTML render would choose not to render it in this case. If you create a HTML file with the same content and load it with Chrome browser, it will not be rendered either.
Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 6/19/2014 Posts: 9
|
Ok.
Reasoning in pixels when creating a pdf is odd since pixels don't mean anything in the paper world, but anyway, I did find a reasonable workaround :
I transform all points measurements in pixels before sending the html to the API (1pt => 10px) then I apply a ZoomLevel of 96f / 720f which gives me exactly what I want: 1) no weird rounding errors (10pt fonts are exactly 10pt;) 2) Sub-pt lines (up to 1/10 pt)
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,196
|
Pixels aligning is necessary to render page properly on screen because many web pages are created only with pixels in mind. For those pages using sub-pixel rendering will only result in "artifacts" or even "wrong" result. For this reason the browser engine always do pixel aligning. Another reason is browsers need to ensure the page renders the same on screen and on paper (unless you explicitly uses different CSS rules). Taking the 10pt/9.8pt situation as an example, if the person who created the web page were to have some lines aligned to certain text, then the alignment would look different on screen and on paper if different font sizes are used. For this reason, even if you print the page on paper, the browser would use pixel aligned vlaue (9.8pt) instead of requested value (10pt). Our situation is very similar: we have to render the output exactly as they look on screen. Otherwise we would be explaining such differences to our users every days because only very few advanced developers like you understand the difference. As such our converter does pixel aligning too.
The workaround you come up is an extremely clever workaround. Unlike browser, which was designed for screen first, then printer, PDF was designed for printer first, then screen. So zooming on the PDF part is a very clever idea. Thanks for sharing!
|
|