birt icon indicating copy to clipboard operation
birt copied to clipboard

PDF emitter: showFooterOnLast master page property not working

Open hvbtup opened this issue 10 months ago • 2 comments

While debugging #2026, I noticed that the master page setting showFooterOnLast does not work for the PDF emitter with a combined RunAndRenderTask.

Only with separate RunTask and RenderTask does it work as expected.

After several hours of debbuging, I failed to provide a fix for this. What I could find out:

In LayoutEngine.outputPage, a method showPageFooter is called. This compares the current page number to the total page number. But the total page number is 0 during the combined RunAndRenderTask, so this does not work.

Then I thought: Tell the PageContent object if it is the last page or not, so I added an attribute lastPage to PageContent and getter and setter methods, added it to the copied attributes in the cloning constructor, and call pageContent.setLastPage(true) in the HTMLPageLM.end method if the finished argument is true. And instead of comparing to context.totalPage in LayoutEngine.java, simply call page.isLastPage() to determine if the footer should be shown.

But this only works for reports with a single page (tested with the PDF emitter). For a single page report, this works as expected.

But for a report with an automatic page break (causes by a long table), the call sequence is strange, as I could see by adding some debug output with the System.identityHashCode of the PageContent objects:

Created new PageContent 143672479 Created new PageContent 154086004 cloning from 143672479 before layoutNodes Showing page 154086004 endPage 154086004 Created new PageContent 446551591 cloning from 154086004 after layoutNodes, isLastPage=true HTMLPageLM end, last Page Setting lastPage for PageContent 154086004 to true endPage 154086004 Showing page 446551591 endPage 446551591 endPage 154086004

The output line "Setting lastPage for ..." is basically from the HTMLPageLM.end method. The output line "endPage ..." is from ContentEmitterAdapter.endPage. The "Showing page ... " is from LayoutEngine.outputPage.

One can see that Setting lastPage" is called for a page which already has been shown, thus it is simply too late.

For a single page report, outputPage is called after HTMLPageLM.end.

I have to admit that I don'd really understand how the fixed layout emitter works, so I give up further attempts on fixing this issue.

hvbtup avatar Feb 27 '25 14:02 hvbtup

@hvbtup Hi Henning what you have figured out is according to our findings in generally of the topics of the RunAndRenderTask (all in one). We have this topic of the document generation at different locations:

  • showFooterOnLast
  • showHeaderOnFirst
  • page count

So #2026 the header topic has internally the same reason based on the header handling.

I assume that the original developer has decided to split the task into 2 different steps because I think to handle it over all lot of changes will be necessary. So this change would impact all dynamic element like tables, lists, cross tables or perhaps other elements which can cause dynamically page breaks.

And at all the change would need to rework the handling of the intermediate results. Sometimes it is not enough to have only 2 steps create the rptdocument and than render it. With the 2 steps RunTask & Render Task the rptdocument can be handled in different way and it couldbe that there is a kind of doubled validation which isn't possible if you try it only in 1 steps to get all.

Therefore commercial renderer works internally in evvery cases with multiple loops over the final document. Because 1example is a TOC with the page numbers which can be only created correctly with a post process. Or commercial renderer can reduce automatically the font size if you say your document should have only 10 pages. If the result is 12 pages it will be re-rendered wil smaller fonts based on a post-process.

I will only say that I assume that we have here a familiar topic which can only be solved with the 2 different task executions or with a kind of full change of the RunAndRender-Task.

speckyspooky avatar Feb 28 '25 05:02 speckyspooky

So https://github.com/eclipse-birt/birt/issues/2026 the header topic has internally the same reason based on the header handling.

Maybe, but I think this is a lot easier to solve, because whether a page is the first page or not is known at the beginning of the page.

What you say about page count is true, though.

hvbtup avatar Feb 28 '25 08:02 hvbtup