Recent

Author Topic: Use mORMot2 to export PDF file output Chinese string prompt error problem.  (Read 925 times)

jianwt

  • Full Member
  • ***
  • Posts: 125
Please consult everyone, in windows10 platform lazarUS3.0, export PDF file with mORMot2 output Chinese string prompt error.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Pdf: TPdfDocumentGDI;
  4. begin
  5.   Pdf := TPdfDocumentGDI.Create;
  6.   try
  7.     Pdf.AddPage;
  8.     with Pdf.VCLCanvas do
  9.     begin
  10.       Pen.Color := clRed;
  11.       Pen.Width := 2;
  12.       Brush.Color := clInfoBk;
  13.       Rectangle(100, 100, 400, 200);
  14.       Font.Name := '宋体';
  15.       Font.Size := 20;
  16.  
  17.       TextOut(200, 120, '测试内容'); {An error is reported as long as the input is a Chinese string. How to solve it? }
  18.       //TextOut(200, 120, 'AAAA123');  {This output is normal}
  19.       Pen.Color := clYellow;
  20.       Pen.Width := 5;
  21.       MoveTo(100, 250);
  22.       LineTo(400, 250);
  23.     end;
  24.     Pdf.SaveToFile(ExtractFilePath(Application.ExeName) +'ceshi.pdf');
  25.   finally
  26.     Pdf.Free;
  27.   end;
  28. end;                    
  29.  
  30.  
An indication of the problem can be found in the picture below.
Thank you all.

dbannon

  • Hero Member
  • *****
  • Posts: 3156
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #1 on: September 27, 2024, 07:22:35 am »
Well, thats interesting  jianwt.

Please see https://forum.lazarus.freepascal.org/index.php/topic,68657.msg531140

I note your use of Wide char, is that necessary ?  In my project, I believe its all UTF8 and Wide is not needed, a three byte character is used for each Chinese character. But mine does not work too !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

rvk

  • Hero Member
  • *****
  • Posts: 6512
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #2 on: September 27, 2024, 10:22:49 am »
Yes, there seems to be some problems with Chinese characters (widestring conversion?) in mORMot2 in Lazarus.
(I also answered this on the mORMot2 forum, hopefully it can be fixed)

This seems to work fine in Delphi (both Canvas.TextOut and Windows.TextOutW):

Code: Pascal  [Select][+][-]
  1. var
  2.   pdf: TPdfDocumentGDI;
  3.   S: WideString;
  4. begin
  5.   pdf := TPdfDocumentGDI.Create;
  6.   try
  7.     pdf.AddPage;
  8.  
  9.     // pdf.UseUniscribe := True; // not needed?
  10.     // pdf.AddTrueTypeFont('SimSun'); // not needed?
  11.  
  12.     pdf.VCLCanvas.Font.Name := 'SimSun'; // 宋体
  13.     pdf.VCLCanvas.Font.size := 20;
  14.     S := WideString('测试内容');
  15.  
  16.     pdf.VCLCanvas.TextOut(200, 120, S);
  17.  
  18.     Windows.TextOutW(pdf.VCLCanvas.Handle, 200, 160, PWidechar(S), Length(S));
  19.  
  20.     pdf.SaveToFile(ExtractFilePath(Application.ExeName) + 'ceshi.pdf');
  21.     ShellExecute(Application.Handle, 'open', pChar(ExtractFilePath(Application.ExeName) + 'ceshi.pdf'), '', '', SW_SHOWNORMAL);
  22.   finally
  23.       pdf.Free;
  24.   end;
  25.  
  26. end;

I thought I'd try direct TPdfDocument, skipping the GDI entirely... but that also only works in Delphi and crashes on Lazarus.
(With TextOut instead of TextOutW it works but produces garbage characters logically)

Code: Pascal  [Select][+][-]
  1. var
  2.   pdf: TPdfDocument;
  3.   S: WideString;
  4. begin
  5.   pdf := TPdfDocument.Create;
  6.   try
  7.     pdf.AddPage;
  8.  
  9.     S := '发现双引号不正确“问题”';
  10.     pdf.Canvas.SetFont('SimSun', 12, []);
  11.     Pdf.Canvas.TextOutW(100, 600, PWideChar(S));
  12.  
  13.     pdf.SaveToFile(ExtractFilePath(Application.ExeName) + 'ceshi.pdf');
  14.     ShellExecute(Application.Handle, 'open', pChar(ExtractFilePath(Application.ExeName) + 'ceshi.pdf'), '', '', SW_SHOWNORMAL);
  15.   finally
  16.       pdf.Free;
  17.   end;
  18. end;

So yes, definitely a problem with that code on Lazarus.

PierceNg

  • Sr. Member
  • ****
  • Posts: 393
    • SamadhiWeb
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #3 on: September 28, 2024, 10:27:16 am »
@jianwt @rvk Can you show the full program source and compilation command line please.

When I use the standalone SynPDF unit in my test program, compilation fails with "cannot find unit Graphics".

When I use mormot.ui.pdf:

Code: Pascal  [Select][+][-]
  1. Compiling ...\lcl\nonwin32\messages.pp
  2. messages.pp(22,4) Error: User defined: This unit is not for MS Windows. Windows has unit windows for that.
  3. messages.pp(32,30) Fatal: Circular unit reference between Messages and LMessages

Windows 11, Lazarus 3.4 and its bundled FPC 3.2.2


rvk

  • Hero Member
  • *****
  • Posts: 6512
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #4 on: September 28, 2024, 05:07:03 pm »
@jianwt @rvk Can you show the full program source and compilation command line please.

When I use the standalone SynPDF unit in my test program, compilation fails with "cannot find unit Graphics".
I haven't got a console app but a complete Lazarus LCL app.
This is just a small empty LCL app with a button (as per example) in Lazarus with mORMot2 installed.

You're missing Graphics is just because you didn't add LCL (which is done automatically with a LCL app).

But... more important... SynPdf isn't really updated anymore (I thought).
If you want the latest you need mORMot2 (which pulls in even more).

I tried the older SynPdf but you need to download some SynFPCMetaFile source (found in the older mORMot 1 version).
And after that, the error keep coming. (I gave up after fixing a few there)

When I use mormot.ui.pdf:

Code: Pascal  [Select][+][-]
  1. Compiling ...\lcl\nonwin32\messages.pp
  2. messages.pp(22,4) Error: User defined: This unit is not for MS Windows. Windows has unit windows for that.
  3. messages.pp(32,30) Fatal: Circular unit reference between Messages and LMessages

Windows 11, Lazarus 3.4 and its bundled FPC 3.2.2
You also need to extract a zip with some binaries in the static directory.
See the documentation on https://github.com/synopse/mORMot2

It also says:
Quote
Note that FPC 3.2.2 has a regression with variant late binding - use FPC 3.2.2 fixes branch instead.
So not sure if Lazarus 3.4 had FPC 3.2.2 fixes version (I use trunk here).

After that adding mormot.ui.pdf and Windows to that empty LCL app with one button will do as test application.
I did have to setup extra paths in "other unit-files" to make Lazarus find the sources.
Somehow the mormot2.lpk and mormot2ui.lpk as required packages doesn't add the search path.
So I needed to add:
Quote
Q:\dev32\extras\mORMot2\src\ui;Q:\dev32\extras\mORMot2\src\lib;Q:\dev32\extras\mORMot2\src\core;Q:\dev32\extras\mORMot2\src\crypt

After that the shown code gives error (which works fine in Delphi):
Quote
Project project1 raised exception class 'External: ACCESS VIOLATION' with message:
Access violation reading from address $00000002.

 In file 'mormot.ui.pdf.pas' at line 5216

Code: Pascal  [Select][+][-]
  1. procedure TPdfWrite.AddGlyphFromChar(Char: WideChar; Canvas: TPdfCanvas;
  2.   Ttf: TPdfFontTrueType; NextLine: PBoolean);
  3. var
  4.   changed: boolean;
  5.   fnt: TPdfFontTrueType;
  6.   Glyph: word;
  7. begin
  8.   assert((Ttf <> nil) and (Ttf = Ttf.WinAnsiFont));
  9.   changed := fAddGlyphFont = fNone;
  10.   Glyph := Ttf.fUsedWide[Ttf.FindOrAddUsedWideChar(Char)].Glyph;
  11.   with Canvas.fDoc do
  12.     if (fPdfA <> pdfaNone) and
  13.        (Glyph = 0) and
  14.        (fFontFallBackIndex < 0) then
  15.       raise Exception.Create('PDF/A expects font fallback to be enabled, ' +
  16.         'and the required font is not available on this system')      

BTW This works fine so it's just when Chinese characters are used.
Code: Pascal  [Select][+][-]
  1.     S := 'Testen';
  2.     pdf.Canvas.SetFont('Arial', 12, []);
  3.     Pdf.Canvas.TextOutW(100, 600, PWideChar(S));
« Last Edit: September 28, 2024, 05:08:34 pm by rvk »

PierceNg

  • Sr. Member
  • ****
  • Posts: 393
    • SamadhiWeb
Thank you for the comprehensive reply @rvk.

dbannon

  • Hero Member
  • *****
  • Posts: 3156
    • tomboy-ng, a rewrite of the classic Tomboy
Pierce, are you watching https://forum.lazarus.freepascal.org/index.php/topic,68657.msg531140

There we got jianwt working nicely using just fpdpf, a unit in FCL. No external packages needed.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

PierceNg

  • Sr. Member
  • ****
  • Posts: 393
    • SamadhiWeb
Pierce, are you watching https://forum.lazarus.freepascal.org/index.php/topic,68657.msg531140

There we got jianwt working nicely using just fpdpf, a unit in FCL. No external packages needed.

Davo

Yes I have been, from your first message, and tested your original programs too. That's when I tried mORMot and saw this thread. I've written some little CLI and fired-by-cron programs using mORMot, so wanted to check out mORMot's PDF generator.

jianwt

  • Full Member
  • ***
  • Posts: 125
Quote
Yes I have been, from your first message, and tested your original programs too. That's when I tried mORMot and saw this thread. I've written some little CLI and fired-by-cron programs using mORMot, so wanted to check out mORMot's PDF generator.
@piereng, if you use linux in mORMot2 to generate PDF files containing Chinese, no matter it is win or linux, you will report an error directly.

rvk

  • Hero Member
  • *****
  • Posts: 6512
I think mORMot2 has more advanced capabilities with mimicking GDI for 'printing' to PDF.

You can almost use the same code when printing to a TCanvas for a printer as for the PDF.
As far as I know, that's not possible with fppdf (unless I'm wrong).
mORMot2 is much more like the normal TCanvas (unlike fppdf).

Otherwise, fppdf is fine if you just want to create pdf with separate code.

(In my code I have elaborate printing code and it was a breeze to add the creation of a pdf through SynPdf (and later mORMot2). Nearly no changes where needed. That shouldn't have been possible with fppdf, if I had this in Lazarus).



dbannon

  • Hero Member
  • *****
  • Posts: 3156
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #10 on: October 05, 2024, 07:49:02 am »
... mORMot2 .... You can almost use the same code when printing to a TCanvas for a printer as for the PDF.
You are correct, while similar in concept, there is no (visible) canvas with fpPDF. You still call Page.TextOut(...) type function so can still write anywhere you like and with any compliant font.

And you can still draw on the fpPDF Page, much as you would draw on a canvas.

So, while a TPDFPage does not seem to have TCanvas in its ancestry it is obviously modeled on it to some degree.  But TPDFPage has lots of PDF specific things too, options to embed fonts, derive italic/bold from a base font, and so on.

I like that it does not require any additional package, its all there in FPC.  But, and this may be relevant to using mORMot2, fpPDF does not work work with all fonts. Don't, for example, use a font that bundled into a collection, *.otc or *.ffc.  Use a font that exists as a *.ttf or *.otf.  And your operating system probably does not want to discuss what sort of file a particular fonts lives in.  Maybe the same thing is happening in the case discussed here ?

Davo



Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

rvk

  • Hero Member
  • *****
  • Posts: 6512
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #11 on: October 05, 2024, 10:13:38 am »
... mORMot2 .... You can almost use the same code when printing to a TCanvas for a printer as for the PDF.
You still call Page.TextOut(...) type function so can still write anywhere you like and with any compliant font.

And you can still draw on the fpPDF Page, much as you would draw on a canvas.
Yes, but I saw recently (from a question) that it can't do DT_RIGHT to right align text, like you can in Windows. PDF natively also has TextAlign, which fppdf doesn't seem to use or support anywhere. You need to calculate the position yourself. Imagine doing that with right aligned languages  :D

And what about a TRichMemo. I have lots of TRichEdits in Delphi which would need to be 'printed' to PDF (and not as bitmap of course). With the RichEdit dll you can instruct Windows to print it to a handle (of a canvas). The content of the richedit is users choice so you can't deconstruct it and get away with just printing some text. RichEdit is far too complex for that. If fpPDF could handle TMetaFile like SynPdf, you could go that route. But it doesn't.

So the TextOut in fpPDF is rather rudimentary and isn't advanced as the TextOut from Windows.
It works fine for something like a report generator but going more advanced...  ::)

(Don't get me wrong. This isn't to criticize fpPDF. It works perfect the way it is. It's just to point out the differences and use cases for both.)

dbannon

  • Hero Member
  • *****
  • Posts: 3156
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #12 on: October 05, 2024, 12:33:49 pm »
.....
So the TextOut in fpPDF is rather rudimentary and isn't advanced as the TextOut from Windows.
....
Er, yes, I am sure that is the case. fpPDF is cross platform, works anywhere. I expect the TextOut from Windows really only works on Windows.

Quote
And what about a TRichMemo. I have lots of TRichEdits in Delphi which would need to be 'printed' to PDF (and not as bitmap of course). With the RichEdit dll you can instruct Windows to print it to a handle (of a canvas). The content of the richedit is users choice so you can't deconstruct it and get away with just printing some text. RichEdit is far too complex for that.

Well, concentrating on FPC and open source (I have not used Delphi since version2).

I use KMemo, a similar but more complete thing than TRichMemo.  KMemo has a printer unit but it is Windows only. So, my KMemo printer unit is somewhat less that 300 lines long. Does all the text alignment. It is left aligned, I guess I could make it Right Aligned in 15 minutes. My fpPDF using unit is more complicated (700 lines), due to the PDF features it exposes but making it right aligned certainly would be no harder. 

When I first started my project, I looked at using (lazarus)TRichEdit so have a basic understanding of how it works, making a similar printer or fpPDF unit for it would most certainly not be "far too complex". I know for a fact you have far more experience than I do, you would find it trivial.

But, as you said, choices in something like this never obvious. You mention "Right Align", I mention "no extra packages". My guess is a considered decision would look at very many more factors than these !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

jianwt

  • Full Member
  • ***
  • Posts: 125
Re: Use mORMot2 to export PDF file output Chinese string prompt error problem.
« Reply #13 on: October 06, 2024, 02:00:40 pm »
Quote
I think mORMot2 has more advanced capabilities with mimicking GDI for 'printing' to PDF.

I also think mORMot2 is very suitable for beginners to use, in the beginning, I used mORMot2, but it is not very friendly to the current lazarus, the output of Chinese kept reporting errors, I also reported this problem to the official mORMot forum, but there has been no response.

 

TinyPortal © 2005-2018