PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Sun Sep 01, 2024 2:17 am

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Wed Aug 14, 2024 5:58 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
Hi there !

When creating a table using Migradoc I am facing the following rendering issue:

Image

The issue only occurs within table cells as I am able to have text right after numbers in other parts of the document without issue. I am clueless regarding what could cause this issue so any pointer would be greatly appreciated :( . I have tinkered with fonts, assumed that the problem is with trailing zeros (it isn't), and spent almost an hour troubleshooting.
This is also not a problem with padding since there is plenty of space left as can be seen.

I am using the 6.2.0 preview 1 as I needed a bug fix regarding a windows path separator character hardcoded that prevented images from being found on Linux. However just to be sure I've downgraded to 6.1.1 and the issue is also present there.
My code isn't doing anything fancy, for the subtotals:

Code:
let row = table.AddRow()
        row.Cells[0].Format.Font.Bold <- true
        row.Cells[0].AddParagraph(label) |> ignore
        row.Cells[1].MergeRight <- 2
        row.Cells[1].AddParagraph(value) |> ignore
        row.Cells[1].Format.Alignment <- ParagraphAlignment.Center


And for the product name it's a basic:

Code:
paragraph.AddSpace(3) |> ignore
paragraph.AddCharacter(SymbolName.Bullet) |> ignore
let featureFormattedText = paragraph.AddFormattedText("test" + string feature)
featureFormattedText.Italic <- true


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 6:44 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
It looks like the issue could be somehow relative to the culture used to render the numbers, as I was able to fix the overlap of the 1,000,000 number by rendering it using:

Code:
NumberOfFrancsIncluded.ToString("N0", culture)


instead of

Code:
NumberOfFrancsIncluded.ToString("N0")


However this fix does not seem to work with the other numbers overlaping.


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 6:55 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
Okay i got it, this looks like a bug with MigraDoc, the issue occurs when the number is rendered by a culture using spaces as thousands group separators instead of a comma (as is the case for the French culture). It looks like in this case migradoc/pdfsharp does not correctly calculate the space used by the number when positioning the next element. Setting the document's culture before rendering using the below does NOT seem to help:

Code:
document.Culture <- culture


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 7:00 pm 
Offline
PDFsharp Expert
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 971
Location: CCAA
I only see code fragments, so not much I can say now.

Is there more than one space used as a thousands separator for numbers?

An MDDDL file might help investigate what you get there.
https://www.pdfsharp.net/wiki/MigraDocDDL.ashx

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 7:24 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
Thanks for your swift reply, apparently the space separator only contains a single character.

I have just uploaded the mdddl file here: https://file.io/IvC3lTZjH2J8


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 7:33 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
From what I understand, this situation is supposed to be handled here

Code:
var culture = text.Document!.EffectiveCulture;

                    var decimalSeparator = culture.NumberFormat.NumberDecimalSeparator;
                    var decimalSeparatorLength = decimalSeparator.Length;
                    var groupSeparator = culture.NumberFormat.NumberGroupSeparator;
                    var groupSeparatorLength = groupSeparator.Length;

                    // Get the index of the decimal position the word should be aligned at.
                    var decimalPosIndex = -1;
                    var hasNumber = false;
                    for (var i = 0; i < word.Length;)
                    {
                        var c = word[i];

                        // Number is always accepted before decimal position.
                        if (char.IsNumber(c))
                        {
                            hasNumber = true;
                            i++;
                            continue;
                        }

                        var restLength = word.Length - i;

                        // Decimal Separator always determines decimal position.
                        if (decimalSeparatorLength <= restLength && word.Substring(i, decimalSeparatorLength) == decimalSeparator)
                        {
                            decimalPosIndex = i;
                            break;
                        }

                        // Group Separator is always accepted before decimal position.
                        if (groupSeparatorLength <= restLength && word.Substring(i, groupSeparatorLength) == groupSeparator)
                        {
                            i += groupSeparator.Length;
                            continue;
                        }

                        // Other characters determine decimal position, if word contains numbers by now.
                        if (hasNumber)
                        {
                            decimalPosIndex = i;
                            break;
                        }

                        // Otherwise other characters are accepted before decimal position.
                        i++;
                    }

                    if (decimalPosIndex >= 0)
                        word = word[..decimalPosIndex];

                    XUnitPt wordLength = MeasureString(word);
                    notFitting = _currentXPosition + wordLength >= _formattingArea.X + _formattingArea.Width + Tolerance;
                    if (!notFitting)
                        return _formattingArea.X + tabStopPosition - wordLength;

                    return _currentXPosition;
                }


The document culture is indeed used to determine the space used by both decimal separators and thousands separators in the current effective culture of the document (i've ensured that it is correctly set in my case). But for some reason, something does not work.


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 14, 2024 9:18 pm 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
Okay, apparently this issue is solely about the non-breakable narrow space character

https://unicode-explorer.com/c/202F

For some reason, PdfSharp is struggling to render it properly no matter which font I use.

As a workaround I have replaced the number group separator character for the French culture since I luckily have a culture factory allowing me to make this change in a single place, but this is something the core team may want to look into.


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 15, 2024 7:07 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3109
Location: Cologne, Germany
I still have to look into it.

First impression:
Problem seems to be that NNBSP has a narrow width when being measured, but is really wide when rendered in PDF - and thus text after NNBSP may overlap with other text.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 15, 2024 7:23 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3109
Location: Cologne, Germany
baraccuda7596 wrote:
For some reason, PdfSharp is struggling to render it properly no matter which font I use.
Which version of PDFsharp are you using? Which fonts have you tried?
Where did you get OpenSans from?
Have you tried Arial from the Windows folder?

I tried PDFsharp 6.2.0 Preview 1 under Windows 10.
Segoe WP in Core works fine.
Arial in GDI and WPF builds works fine.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 15, 2024 7:35 am 
Offline
PDFsharp Guru
User avatar

Joined: Mon Oct 16, 2006 8:16 am
Posts: 3109
Location: Cologne, Germany
I downloaded a version of "Open Sans" and it has no NNBSP, so in the PDF I see a rectangle as a placeholder. But yes, I get the overlap.

You can use the new "OnPrepareTextEvent" to replace all NNBSP by a supported character (a character included in your font).
I dunno how to use this with F#.

_________________
Regards
Thomas Hoevel
PDFsharp Team


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 15, 2024 9:33 am 
Offline

Joined: Wed Aug 14, 2024 5:47 pm
Posts: 7
Thank you a lot for your continued help with this

To answer your questions: I am using the version 6.2.0 preview 1 and I got the OpenSans font from the Google Font website. I am also using Linux to develop (as my production server is Unix-based).

Fantastic, the F# syntax is the following one:

Code:
pdfDocument.RenderEvents.PrepareTextEvent.Add(fun args -> args.Text <- args.Text.Replace(" ", " "))


And this approach is indeed much better than modifying the CultureInfo object across the whole application.

Apparently the rendering issue when the character is not supported by the font is not be specific to PdfSharp as I have found the following issue for another project:

https://github.com/bpampuch/pdfmake/issues/2614

However the overlap seems to be specific to PdfSharp.

This time since i do not have any hard requirement to use the OpenSans font I have simply switched to the Arimo font (from Google fonts) which supports this character and the issue is gone. The issue above links to a page breaking down all the fonts supporting NNBSP. However, the PrepareTextEvent will be quite a useful tool to keep in my toolbelt, thanks again!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 81 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group