Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi page PDF. #127

Open
takasurazeem opened this issue Nov 16, 2024 · 22 comments
Open

Multi page PDF. #127

takasurazeem opened this issue Nov 16, 2024 · 22 comments
Assignees

Comments

@takasurazeem
Copy link

Hi, I am trying to generate a PDF using DataTemplate and scrollview (CollectionView behavior) and it works, however the generated PDF is just one page instead of multipage. Is there some configuration to let it move to new page when page size exceeds A4 or letter?

@taublast
Copy link
Owner

As i see it we have to manually calculate and split our rendering into pdf pages. Again, pdf is just a canvas like a screen canvas would be for a usual rendering so it's up to the developer to organize the UI.
If I understand correctly your context you should not use any scroll view here when rendering to pdf. I can propose a quick not optimized way to split into pages:

1 Remove any scrolls. You can still use a SkiaLayout with ItemTemplate, just it will take the height it would need.
2 You would prepare and measure your layout into a wrapper SkiaLayout with height request as -1, this way you would get a real content height and not fixed page height.
3 After measuring you would get the final height, divide it by the A4 (for example) height in pixels = your number of pages
4 Then you would iterate through pages to render each to its own canvas /page.

Could go in details in the upcoming days.

@takasurazeem
Copy link
Author

As i see it we have to manually calculate and split our rendering into pdf pages. Again, pdf is just a canvas like a screen canvas would be for a usual rendering so it's up to the developer to organize the UI. If I understand correctly your context you should not use any scroll view here when rendering to pdf. I can propose a quick not optimized way to split into pages:

1 Remove any scrolls. You can still use a SkiaLayout with ItemTemplate, just it will take the height it would need. 2 You would prepare and measure your layout into a wrapper SkiaLayout with height request as -1, this way you would get a real content height and not fixed page height. 3 After measuring you would get the final height, divide it by the A4 (for example) height in pixels = your number of pages 4 Then you would iterate through pages to render each to its own canvas /page.

Could go in details in the upcoming days.

Maybe if you could add an A4 portrait page example in demos that would help a lot of people as this is most demanded page layout used by people.

@takasurazeem
Copy link
Author

takasurazeem commented Nov 17, 2024

I tried the dividing and it is cutting the text too, maybe I will add margins and it might solve it.

Edit, it won't as that would be top and bottom margin only, maybe I need to manually handle generating PDF.

@taublast
Copy link
Owner

taublast commented Nov 17, 2024

No-no, i mean first you render everything into a fake in-memory canvas, then iterating through pages you render the appropriate part of it to the pdf page. I сould provide an example tomorrow.

@takasurazeem
Copy link
Author

No-no, i mean first you render everything into a fake in-memory canvas, then iterating through pages you render the appropriate part of it to the pdf page. I сould provide an example tomorrow.

That'd be so helpful, thank you for your amazing work to the community. I had almost moved to Flutter for better solutions to this problem. 😅 I have done it in Swift but that is like my backyard technology and I can keep up with advance tech there but this is new territory to me.

@taublast
Copy link
Owner

No probs, been a bit busy again, still on it sorry for delay!

@taublast
Copy link
Owner

Okay, i see i need to add page margins to the logic... :)
image

@taublast
Copy link
Owner

Will post code tonight..
image

@taublast taublast self-assigned this Nov 19, 2024
@taublast
Copy link
Owner

Okay this is it with the new nuget 1.2.9.1
image
Added example for multi-paged PDF:

async Task CreatePdfPages(SKSize inches, int dpi)

@taublast
Copy link
Owner

Please use nuget 1.2.9.2 an do not reference skiasharp 2.88.9 for windows.. had to revert back to 2.88.9-preview.2.2

@takasurazeem
Copy link
Author

I have updated to 1.2.9.2 on Mac and tried iOS/Android and mac desktop but it does not render the Grid with item template.

https://github.com/takasurazeem/AlTanzeel/blob/Generate-Quiz-PDF/AlTanzeel/Pages/QuizReport.xaml
https://github.com/takasurazeem/AlTanzeel/blob/Generate-Quiz-PDF/AlTanzeel/Pages/MainPage.xaml.cs

@takasurazeem
Copy link
Author

Also, the PDF still clips the content from the demo application, I think before drawing we should check if the text is clipping then just move to the next page and don't draw the text there, this all has to be programmatically done.

DrawnUi_2024-11-23_170026.pdf

@taublast taublast reopened this Nov 24, 2024
@taublast
Copy link
Owner

I have updated to 1.2.9.2 on Mac and tried iOS/Android and mac desktop but it does not render the Grid with item template.

https://github.com/takasurazeem/AlTanzeel/blob/Generate-Quiz-PDF/AlTanzeel/Pages/QuizReport.xaml https://github.com/takasurazeem/AlTanzeel/blob/Generate-Quiz-PDF/AlTanzeel/Pages/MainPage.xaml.cs

Thanks for the example, will make it work ok.

@taublast
Copy link
Owner

taublast commented Nov 27, 2024

So i added some fixes: takasurazeem/AlTanzeel#3, we have a problem with splitting to pages left, it seems.

@takasurazeem
Copy link
Author

So i added some fixes: takasurazeem/AlTanzeel#3, we have a problem with splitting to pages left, it seems.

Hmmm, in Swift, when I was generating the PDF, I would check if the text that is to be drawn ends up having y position above the page's length; I would move that entire block to the next page. Working with low-level APIs in Swift was easy for me; they were not that low level but gave me access to what I wanted, but in MAUI and DrawnUI, wouldn't we want to use the same approach? I plan on adding horizontal rules below the Arabic text that gets drawn as it is sort of a quiz thing.

Below is my Swift app generated document.

PDF document-4A35-A0D7-CC-0.pdf

@taublast
Copy link
Owner

taublast commented Dec 6, 2024

I see the idea. Can you share the swift code please where you are able to check if you should postpone to next page? Would think on implementing the same stuff here if it's technically possible.

@takasurazeem
Copy link
Author

takasurazeem commented Dec 7, 2024

I see the idea. Can you share the swift code please where you are able to check if you should postpone to next page? Would think on implementing the same stuff here if it's technically possible.

Here: https://github.com/takasurazeem/QuranMajeed/blob/develop/QuranMajeed/Quiz/PDFPreview/Utility/PDFGenerator.swift#L167

Specific logic: https://github.com/takasurazeem/QuranMajeed/blob/develop/QuranMajeed/Quiz/PDFPreview/Utility/PDFGenerator.swift#L229-L236

I will see if I can add comments inside the function, function name is drawVerses in case me adding comments moves the lines up or down.

@takasurazeem
Copy link
Author

I see the idea. Can you share the swift code please where you are able to check if you should postpone to next page? Would think on implementing the same stuff here if it's technically possible.

Here: https://github.com/takasurazeem/QuranMajeed/blob/develop/QuranMajeed/Quiz/PDFPreview/Utility/PDFGenerator.swift#L167

Specific logic: https://github.com/takasurazeem/QuranMajeed/blob/develop/QuranMajeed/Quiz/PDFPreview/Utility/PDFGenerator.swift#L229-L236

I will see if I can add comments inside the function, function name is drawVerses in case me adding comments moves the lines up or down.

Hi, did you have a chance to look at this?

@taublast
Copy link
Owner

Hey, yes failed to find where/how you were checking if should postpone to next page, must be my lack with swift. Could you point me to it please? Sorry for delay.

@takasurazeem
Copy link
Author

Hey, yes failed to find where/how you were checking if should postpone to next page, must be my lack with swift. Could you point me to it please? Sorry for delay.

Hmm, would you like to schedule a zoom call or google meet call to go over my implementation in Swift? There's a lot going on in that file, and at the time when I implemented it, it was not in blogs or easy to find on Google, but I took some help from ChatGPT and did the rest of the math myself.

@taublast
Copy link
Owner

You can ping me at https://discordapp.com/users/taublast though i think i'd take a different approach here.
As I see it you have implemented a pdf-dedicated content renderer so it's aware of where to break content while outputting it.
At the same time with drawnui we try to use a renderer that would just output to an abstract canvas, whatever would it be, recording context, bitmap, pdf..
So I think I see a solution (unoptimized concept):

  1. First pass: render to bitmap. A renderingtree is generated, containing rectangles of the controls.
  2. Use the RenderingTree to split the bitmap into chunks that would fit into pdf pages without breaking content in the middle.

Would work on implementing this in the very near future but no promises about delays. I hope that's ok.
Normally all layout already generate that tree today, I need to make it more "easily browsable" and (hold me) thinking about adding accessibility data to it.

@taublast
Copy link
Owner

I have added a method

    /// <summary>
    /// Pages will be split upon first found vertical stick children.
    /// Must specify if stack is templated.
    /// If no stack is found will split to pages as usual.
    /// </summary>
    public static List<PdfPagePosition> SplitStackToPages(SkiaControl control, bool isTemplated, SKSize paper, float scale = 1)

and created a PR for you to check: https://github.com/takasurazeem/AlTanzeel/pulls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants