wxPDFDocument Auto-height Topic is solved

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

wxPDFDocument Auto-height

Post by evstevemd »

Is there a way to specify only width and let wxPdfDocument calculate height based on text size?
I want to create PDF with 80mm/Portrait width but let the library determine the height. Right now I do not know how and cannot find a sample or documentation.

Any help is apprecuated
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
utelle
Moderator
Moderator
Posts: 1117
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxPDFDocument Auto-height

Post by utelle »

evstevemd wrote: Wed Oct 18, 2023 8:32 am Is there a way to specify only width and let wxPdfDocument calculate height based on text size?
This is currently not possible. Your application has to calculate the cell height. However, this should be rather trivial, because you know the font size you use for writing text or can retrieve it by calling wxPdfDocument::GetFontSize(). The font size is measured in points. Multiply the font size by 25.4/72 and you will get the font size in millimeter. Usually the line height should be a bit more than the font size, maybe 10% - that is multiply the former value by 1.1 and you will get a reasonable line height.

Kind regards,
Ulrich
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

Thank you.
I will try to find a way forward using this information as guide.
One more question, how do I know line length so that I can calculate number of lines needed? Especially for non-fixed width fonts?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
utelle
Moderator
Moderator
Posts: 1117
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxPDFDocument Auto-height

Post by utelle »

evstevemd wrote: Wed Oct 18, 2023 3:23 pm One more question, how do I know line length so that I can calculate number of lines needed? Especially for non-fixed width fonts?
The available line length depends on the left and right margin. That is, the available line length is "page width minus (left plus right margin)". The width required by a certain text string can be determined with the method GetStringWidth(). However, it will not be trivial to determine the actual number of lines, because it depends on the distribution of space characters in the text where line breaks can occur.
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

I see, it seems to be complex than I thought.
Since you have experience with this how do you deal with this? I'm generating PDF for Receipts to be printed on thermal printer.
I have hard time dealing with this since it can have as few items as one or as many as 20. Is it possible to have a sample that roughly deals with this to help on this one?

Because am stranded as whether should I count tags like td, col, table, et al or just text?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

This is what am working with now and gives height of 0. I'm still debugging but If I misunderstood anything please correct me

Code: Select all

    wxString html = "<p>THE THEXT HERE</p>";
    wxPdfDocument pdf;
    pdf.SetFont(wxS("Courier"), wxS("N"), 8);
    pdf.SetTextColour(*wxBLACK);
    float sizeInMm = pdf.GetFontSize() * 25.4 / 72;
    auto lineHeight = sizeInMm * 1.1;
    float margin = 2.0;
    float width = 80.0;
    float availableWidth = width - (margin * 2); // equal left and right margins
    float textWidth = pdf.GetStringWidth(html);
    float numberOfLines = textWidth / availableWidth;
    float pageHeight = lineHeight * numberOfLines;

    pdf.SetMargins(margin, margin, margin);
    pdf.AddPage(wxPORTRAIT, width, pageHeight);
    pdf.WriteXml(html);
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
utelle
Moderator
Moderator
Posts: 1117
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxPDFDocument Auto-height

Post by utelle »

evstevemd wrote: Thu Oct 19, 2023 5:43 am Since you have experience with this how do you deal with this?
Yes, as the author of wxPdfDocument I should know how to accomplish various tasks. However, the devil can be in the detail.
evstevemd wrote: Thu Oct 19, 2023 5:43 am I'm generating PDF for Receipts to be printed on thermal printer.
And you want pages of different height, depending on the content, right?
evstevemd wrote: Thu Oct 19, 2023 5:43 am I have hard time dealing with this since it can have as few items as one or as many as 20. Is it possible to have a sample that roughly deals with this to help on this one?
Without knowing how your text is structured, it is hard to tell how this should be dealt with. You may contact me via PM, to sort out the details, if you don't want to disclose implementation details of your application.
evstevemd wrote: Thu Oct 19, 2023 5:43 am Because am stranded as whether should I count tags like td, col, table, et al or just text?
Obviously, you want to use XML for formatting the text. This makes it a bit more involved to determine the required page height. It really depends on whether you have for example a single table or multiple tables, one column or multiple columns etc. Probably you will have to reserve some extra vertical space for the structure. For determining the required number of lines, you will have to analyze the separate text blocks individually. This task will be easier, if you use a fixed width font like Courier, because you simply have to count characters. For variable-width fonts you will have to calculate the string width. In any case, you will have to take line breaks into account.

Below find some comments to your code snippet:
evstevemd wrote: Thu Oct 19, 2023 5:43 am This is what am working with now and gives height of 0.I'm still debugging but If I misunderstood anything please correct me

Code: Select all

    wxString html = "<p>THE THEXT HERE</p>";
    wxPdfDocument pdf;
    pdf.SetFont(wxS("Courier"), wxS("N"), 8);
    pdf.SetTextColour(*wxBLACK);
    float sizeInMm = pdf.GetFontSize() * 25.4 / 72;
    auto lineHeight = sizeInMm * 1.1;
Most likely you will have to adjust the factor a bit to account for letters with descender like g, q, y. Maybe 1.2 or 1.25 - you will have to experiment a bit, until you are satisfied with the result.
evstevemd wrote: Thu Oct 19, 2023 5:43 am

Code: Select all

    float margin = 2.0;
    float width = 80.0;
    float availableWidth = width - (margin * 2); // equal left and right margins
    float textWidth = pdf.GetStringWidth(html);
    float numberOfLines = textWidth / availableWidth;
The last statement won't work. The number of lines is an integer, and even if the text fills only half of a line, you will still need a whole line. Therefore you should use a statement like the following:

Code: Select all

    int numberOfLines = textWidth / availableWidth + 1;
evstevemd wrote: Thu Oct 19, 2023 5:43 am

Code: Select all

    float pageHeight = lineHeight * numberOfLines;

    pdf.SetMargins(margin, margin, margin);
    pdf.AddPage(wxPORTRAIT, width, pageHeight);
wxPdfDocument defaults to automatic page break, if the text doesn't fit on a page. The page break margin is 20 mm from the bottom, unless you specify it differently. That is, you will most likely want to disable automatic page break, like in the following statement:

Code: Select all

    pdf.SetAutoPageBreak(false, 0);
You will have to place this statement before the AddPage statement.
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

Hi Ulrich,
Thanks for the help and corrections. Am going to incorporate those and may be when successful make a sample demonstrating that.
While am adjusting things as you suggested, I though I would put more details in what I do

I do a receipt which is basically three tables
1. Header table with business details. It is divided into two columns
2. Contents table with Product | Quantity | Price. So three columns
3. Footer table with Subtotals.

Apart from them having varying column and heights they are of the same width
Table 2 is always the one that changes.

I don't mind haveing auto added new page if the height is beyond paper but thermal printers lack such concept. It is an "endless" piece of paper to print on.

Again thanks for help let me work on your invaluable comments
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

Your suggestion worked quiet well but I cannot disable page break on the PDF
Am trying to print and see
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
utelle
Moderator
Moderator
Posts: 1117
Joined: Tue Jul 05, 2005 10:00 pm
Location: Cologne, Germany
Contact:

Re: wxPDFDocument Auto-height

Post by utelle »

evstevemd wrote: Thu Oct 19, 2023 3:36 pm I do a receipt which is basically three tables
1. Header table with business details. It is divided into two columns
2. Contents table with Product | Quantity | Price. So three columns
3. Footer table with Subtotals.

Apart from them having varying column and heights they are of the same width
Table 2 is always the one that changes.
Except for date and totals header and footer usually do not change and require a fixed amount of vertical space. In contrast the content list can have an arbitrary length. Here is the question whether a single entry in the list can occupy more than one line or not. Quite often the variable text of an entry is truncated to a fixed length, so that it fits on a single line. If you want to support multiple lines per entry, you will have to analyze the product text of each entry and count the lines it will occupy. If you truncate the product text to at most 1 line, the calculation is simple: just multiply the height of a single line with the number of list entries and you have the required height for table 2.
evstevemd wrote: Thu Oct 19, 2023 3:36 pm I don't mind haveing auto added new page if the height is beyond paper but thermal printers lack such concept. It is an "endless" piece of paper to print on.
Actually, you will not want to work with a fixed page size in your use case, because that would waste paper. That is, calculating the required page height, before adding a new page with the calculated height, is certainly a good approach.
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxPDFDocument Auto-height

Post by evstevemd »

Thanks Urlich.
The library makes life easier.
I will find time to add CMake as well as an example for this scenario
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
Post Reply