More PDF Issues

I seem to be running into encoding issues with the new PDF class in 2022r2.

I open a file using a TextInputStream and set each ReadLine to DefineEncodings(Encodings.UTF8). When loading a ListBox with the lines, the Unicode characters are displayed properly:

However, the same lines sent to the PDF class’ DrawText method results in ??? instead of the Unicode characters:

I’m using:

CatLine = fTis.ReadLine.DefineEncoding(Encodings.UTF8)

and then processing CatLine.

@Javier_Menendez ?

PDFDocument doesn’t support Unicode at the moment.

https://tracker.xojo.com/xojoinc/xojo/-/issues/60248

1 Like

Ugh!

:face_exhaling:

Well, there are plugins from MBS and Einhugur to do PDF with unicode characters…

1 Like

Yep, I know… :pensive: Working at that now (is the only main feature to implement from the initial list… some other pieces were needed first, so…).

In the meantime, and I know is far far away from being the right solution, you can render utf-8 / utf-16 to a Picture and add it to the PDF page (remember to create the picture at double the size you are going to include it in the PDF; for example 200 x 200 if you are going to add it at 100 x 100).

For example:

Var d As New PDFDocument
Var g As Graphics = d.Graphics
Var s As String = "ぐ 園ヅ尉ュゟ"

Var p As New Picture(500, 500)
p.Graphics.FontSize = 24
p.Graphics.DrawText(s, 0, p.Graphics.FontAscent)

g.DrawPicture(p, 20, 20, 250, 250, 0, 0, p.Width, p.Height)

d.Save(SpecialFolder.Desktop.Child("UTF-8.pdf"))

2 Likes

Thanks, but this is generated from a list that could have 100,000’s of entries, so that would be economically disastrous. For now, I’ve returned to using the Windows and macOS Print methods and letting the user choose the “PDF” dropdown on the Print dialog. For Linux, the user just ends up with question marks unil the Linux PrinterSetup issue is sorted.

Why " p.Graphics.DrawText(s, 0, p.Graphics.FontAscent)" and not p.Graphics.DrawText(s, 0, 0)?

Without taking the Ascent height into account, the text was being cut off - especially when things like graves and umlauts were in the text.

Thanks Tim.
I had already noticed it, but my question is:
According to the Documentation.

DrawText(Text As String, X As Double, Y As Double, [WrapWidth As Double, Condense As Boolean])

Draws the text at the specified location and in the current color. The current color is set with the DrawingColor property.

The X parameter specifies the distance from the left of the Graphics object in pixels. The Y parameter specifies the baseline for the text. The optional WrapWidth parameter specifies the width at which text should wrap. The text will wrap if WrapWidth is provided and Condense is False (The default is False). If WrapWidth is omitted, then text will print on one line, even if the drawing area is too narrow to contain the text. If the optional Condense property is True, DrawText truncates the text to fit into the space specified by WrapWidth and uses an ellipsis (“…”) to indicate that there is additional text that is not shown. The default values of WrapWidth and Condense are zero and False, respectively. The default behavior is to print the text on one line.

"y " is the Baseline. I understand that if I put a 0 the text is cut off in its lower part, but I’d like to know why we have to put the FontAscend value.

No.

Specifying 0 would cause anything above the baseline to be clipped. You need to add the ascender to y so that you see everything.

1 Like

Thank you very much Kevin.
But…
If The Y parameter specifies the baseline for the text.
Why should I enter the Ascent value for the BaseLine?
That is what I don’t understand.

The vertical origin of a font is the baseline.

The y parameter tells DrawText where you want the baseline to draw.

If you specify 0 it means the baseline will draw at 0 and anything above the baseline will be a negative y thus clipped.

To prevent clipping you need to offset the y position by the ascender value (ie: everything above the baseline).

NOTE. This is how text works and is the same when you are drawing text on-screen and to a printer. The PDF co-ordinate system is usually bottom up rather than top down but I imagine Xojo is handling this for you.

2 Likes

Now I understand it.
Thank you!

In fact I was using DrawText not in the PDF, but the problem is the same.

Yep, we handle it in PDF so it exhibits the same behaviour that when working with a regular Graphics context (i.e: a Graphics context from Canvas or Picture).

1 Like

Thanks @kevin_g - that’s a perfect example.

Since there is no UTF-8 support yet for PDF creation I tried the suggested solution (text2picture).
I have a strange behaviour in PDF document with 2 pages.
I draw one picture per page and the result is PDF document replays first picture to second page and ignores second picture.
Example (2022R3.2)

Var pDocument As New PDFDocument
pDocument.Creator = “Xojo”
pDocument.Author = “Xojo”
pDocument.Keywords = “Xojo, PDF, Example”
pDocument.Title = “PDF - Page Layout Example”
pDocument.Subject = “PDF - Page Layout Example”
pDocument.Compressed = False

Var G As Graphics=pDocument.Graphics

//MAKE PAGE1
Var p1 As New Picture(g.Width2, g.Height2)
p1.Graphics.FontSize = 22
For i As Integer=1 To 10
p1.Graphics.DrawText(“AAAAAAAAAAA”+Str(i), 10, p1.Graphics.FontAscent*i,300,True)
Next
G.DrawPicture(p1, 20, 20, g.Width, g.Height, 0, 0, p1.Width, p1.Height)

pDocument.Graphics.NextPage
//MAKE PAGE2
Var p2 As New Picture(g.Width2, g.Height2)
p2.Graphics.FontSize = 22
For i As Integer=1 To 10
p2.Graphics.DrawText("BBBBBBBBBBB "+Str(i), 0, p2.Graphics.FontAscent*i)
Next
G.DrawPicture(p2, 20, 20, g.Width, g.Height, 0, 0, p2.Width, p2.Height)

Var f As FolderItem = SpecialFolder.Desktop.Child(“output.pdf”)
Try
pDocument.Save(f)
f.Open
Catch e As IOException
MessageBox(e.Message)
End Try

That’s the result I get using 2023r3. Seems ok to me.

So it is fixed in latest version.

Thank you

This is good for simple operations, but I’m generating very large PDFs (sometimes 100’s of pages) that must be searchable. This method is not searchable.

2 Likes