#1 2018-08-08 01:53:33

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Chinese symbols and fonts are incorrectly displayed

I used SynPdf to create my document in PDF format, but found that the Chinese symbol output was incorrect。

var
  lPdf: TPdfDocumentGDI;
begin
  lPdf := TPdfDocumentGDI.Create;
  try
    lPdf.ScreenLogPixels := 96;
    lPdf.DefaultPaperSize := TPDFPaperSize.psA4;
    lPDF.AddPage;

    lPdf.VCLCanvas.Brush.Style := bsClear;
    lPdf.VCLCanvas.Font.Name := '宋体';  // 注释掉正常
    lPdf.VCLCanvas.TextOut(20, 20, '发现双引号不正确“问题”');

    lPdf.SaveToFile('c:\Syntest.pdf');
  finally
    lPdf.Free;
  end;
end;

Chinese symbols

Offline

#2 2018-08-08 09:13:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

Try to force the UniScribe processing.

Offline

#3 2018-08-08 14:15:52

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

thanks,I tried it, but the problem still exists.

var
  lPdf: TPdfDocumentGDI;
begin
  lPdf := TPdfDocumentGDI.Create;
  try
    lPdf.UseUniscribe := True;  // 
    lPdf.ScreenLogPixels := 96;
    lPdf.DefaultPaperSize := TPDFPaperSize.psA4;
    lPDF.AddPage;

    lPdf.VCLCanvas.Brush.Style := bsClear;
    lPdf.VCLCanvas.Font.Name := '宋体';  // 注释掉正常
    lPdf.VCLCanvas.TextOut(20, 20, '发现双引号不正确“问题”');

    lPdf.SaveToFile('c:\Syntest.pdf');
  finally
    lPdf.Free;
  end;

Offline

#4 2018-08-10 04:49:56

5c4f394a
Member
Registered: 2013-03-22
Posts: 11

Re: Chinese symbols and fonts are incorrectly displayed

XE3:
synpdf_chinese_TextOut_XE3.png

var
  lPdf: TPdfDocumentGDI;
begin
  lPdf := TPdfDocumentGDI.Create;
  try
    //lPdf.UseUniscribe := True;
    lPdf.ScreenLogPixels := 96;
    lPdf.DefaultPaperSize := psA4;
    lPDF.AddPage;
    lPdf.VCLCanvas.Brush.Style := bsClear;
    lPdf.VCLCanvas.Font.Name := 'SimSun'; // 宋体
    lPdf.VCLCanvas.TextOut( 20, 20, '发现双引号不正确“问题”' );
    lPdf.SaveToFile('%TEMP%\SynPdfTest.pdf');
  finally
    lPdf.Free;
  end;
end;

D7:
synpdf_chinese_TextOut_D7.png

var
  lStr: WideString;
  lLen: integer;
  lPdf: TPdfDocumentGDI;
begin
  lStr := TntEdit1.Text; // Tnt Delphi Unicode Controls
  lLen := Length('TextOutW: ' + lStr);
  lPdf := TPdfDocumentGDI.Create;
  try
    //lPdf.UseUniscribe := True;
    lPdf.ScreenLogPixels := 96;
    lPdf.DefaultPaperSize := psA4;
    lPDF.AddPage;
    lPdf.VCLCanvas.Brush.Style := bsClear;
    lPdf.VCLCanvas.Font.Name := 'SimSun'; // 宋体
    lPdf.VCLCanvas.TextOut( 20, 20, 'TextOutA: ' + lStr );
    TextOutW( lPdf.VCLCanvas.Handle, 20, 40, PWideChar('TextOutW: ' + lStr), lLen );
    lPdf.SaveToFile( '%TEMP%\SynPdfTest.pdf' );
  finally
    lPdf.Free;
  end;
end;

Offline

#5 2018-08-10 08:39:53

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

@5c4f394a,Thank you, I've tried your code, the symbol is correct, but the font is not SimSun
abcjingtong_2018810162344.png

Offline

#6 2020-03-06 02:52:33

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

I found the cause of the problem(i'm poor english),the reason for the font style failure is:
in function TPdfDocument.TTFFontPostcriptName

Result := TrueTypeFontName(aFontName,AStyle);  // get font name and style

// if chinese font (CJK font?)
Rec := @name^.FirstNameRecord;
  for i := 0 to name^.count-1 do
    if (Rec^.nameID=NAME_POSTCRIPT) and (Rec^.platformID=TTFCFP_MS_PLATFORMID)
        and (Rec^.encodingID=1) and (Rec^.languageID=$409) then
    begin
      ...
      SetLength(Result,L);  // here,L is font name length,lost above style
      // so i add rejudging style after to solve this problem
      if pfsItalic in AStyle then
        if pfsBold in AStyle then
          Result := Result + ',BoldItalic'
        else
          Result := Result + ',Italic'
      else
      if pfsBold in AStyle then
        Result := Result + ',Bold';

Offline

#7 2020-03-06 03:11:21

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

the problem of chinese symbols(E.g “ unicode #8220) is:
TSynAnsiFixedWidth.Create
  for i := 127 to 255 do
    if (fAnsiToWide[ii]<>0) and (fAnsiToWide[ii]<>ord('?')) then
      fWideToAnsi[fAnsiToWide[ii]] := i;
     // fAnsiToWide[147] = 8220, fWideToAnsi[8220] = 147, witch “(chinese symbol) becomes "(english symbol),but ” and " display widths are different,causes display problems after generating pdf,so i remove three lines
The above are the problems and solutions I found, which may be inaccurate. If there is a better way, you can notify me, thank you, thank you synpdf.

Last edited by 18114532@qq.com (2020-03-06 03:27:04)

Offline

#8 2020-03-06 14:45:59

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

I have included - with some small refactoring - your  TPdfDocument.TTFFontPostcriptName fix.
Please check https://github.com/synopse/mORMot/commi … 162eb90d37

But I don't understand well why TSynAnsiFixedWidth.Create is involved here.

Please report back if you find something better.
Thanks a lot for your feedback!

Offline

#9 2020-03-06 14:56:21

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

because “ and " are different in unicode,“ unicode is #8220, " ansi is 147
TSynAnsiFixedWidth.Create
for i := 127 to 255 do
    if (fAnsiToWide[ii]<>0) and (fAnsiToWide[ii]<>ord('?')) then
      fWideToAnsi[fAnsiToWide[ii]] := i;  // i = 147, fAnsiToWide[147] = 8220, fWideToAnsi[8220] = 147, ”="

“ and " are different in unicode, In the same font, “ is wider than ",So it should not be the same

Last edited by 18114532@qq.com (2020-03-06 15:02:41)

Offline

#10 2020-03-06 15:13:11

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

I don't understand.
WinAnsi #147 (=#8220 Unicode) and " will have different glyph, so different width in SynPDF, because they are not the same character, even in WinAnsi.

Offline

#11 2020-03-06 15:23:34

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

WinAnsi #147 is "
Unicode #8220 is “
“ should not be equal to ", but becomes equal by fWideToAnsi[fAnsiToWide[ii]] := i where i = 147

Last edited by 18114532@qq.com (2020-03-06 15:24:05)

Offline

#12 2020-03-06 15:30:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

I am afraid you are a bit confused..
WinAnsi #147 is “  (Unicode #8220).
WinAnsi #34 is " (Unicode #34).

Offline

#13 2020-03-06 15:51:09

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

sorry,I did not notice WinAnsi #147 is not “  (Unicode #8220) in chinese font,
i test in Delphi7(because it's use ANSI) and Delphi2010(unicode),i set edit1's font name 宋体(a chinese font alias simsun)
Delphi7
edit1.Text := Char(#147);  i get empty
edit1.Text := Char(#34); i get "
Delphi2010
edit1.Text := Char(#147);  i get ?
edit1.Text := Char(#34); i get "
edit1.Text := Char(#8220); i get “
I haven't found the cause of this phenomenon yet

Last edited by 18114532@qq.com (2020-03-06 15:58:12)

Offline

#14 2020-03-06 16:01:46

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

This is as expected.

Your Windows uses MBCS for ANSI API I guess. It doesn't use WinAnsi, but a Chinese Code Page.
So under Delphi 7 - which uses the ANSI Windows API, Char=AnsiChar so Char(#147)  is not enough in MBCS, so it is not converted.

Whereas in Delphi 2010, Char=WideChar so Char(#147)=Unicode 147 which doesn't exist.
But WideChar(#8220) does exist in UTF-16 so is displayed.

Offline

#15 2020-03-07 02:14:35

18114532@qq.com
Member
Registered: 2018-08-08
Posts: 9

Re: Chinese symbols and fonts are incorrectly displayed

yes, my windows is Simplified Chinese, code page(936) and GBK for ANSI API,so I use MultiByteToWideChar modified it to
TSynAnsiFixedWidth.Create
...
  SetLength(fWideToAnsi, 65536);
  for i := 1 to 126 do
    fWideToAnsi[ii] := i;

  FillcharFast(fWideToAnsi[127], 65536 - 127, ord('?')); // '?' for unknown char
  GetMem(vPWideChar, SizeOf(WideChar));
  try
    for i := 127 to 255 do
      if (fAnsiToWide[ii] <> 0) and (fAnsiToWide[ii] <> ord('?')) then
      begin
        vLen := MultiByteToWideChar(DefaultSystemCodePage, 0, @AnsiChar(i), 1, nil, 0);
        if vLen > 0 then
        begin
          vLen := MultiByteToWideChar(DefaultSystemCodePage, 0, @AnsiChar(i), 1, vPWideChar, vLen);

          fWideToAnsi[fAnsiToWide[ii]] := Ord(vPWideChar^);
        end;
      end;
  finally
    FreeMem(vPWideChar);
  end;

  // fixed width Ansi will never be bigger than UTF-8
  fAnsiCharShift := 0;

Is this the most appropriate way to modify it?

Offline

#16 2020-03-07 15:18:28

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,612
Website

Re: Chinese symbols and fonts are incorrectly displayed

This doesn't make any sense to me.

TSynAnsiFixedWidth is for fixed-width characters, which CP 936 is not by definition.
I don't understand what you are willing to do.

Offline

Board footer

Powered by FluxBB