You are not logged in.
I'm using latest SynPdf code with Delphi7 on Windows10, Slovenian locale.
Preview (TGDIPages.ShowPreviewForm) is rendered correctly but the saved PDF opened in a PDF reader displays wrong characters. Acrobat Reader reports the fonts are embedded with ANSI encoding.
Can anyone help with what should I check, set, change?
Offline
I managed to pinpoint the cause .. my system is using code-page 1250, PDF gets rendered using
code-page 1252.
Problematic character is the one with code 200 (010C in cp1250 and 00C8 in cp1252) , it differs between both code-pages. Unfortunately this character is fairly frequently used in our language.
Is there a way to set proper code-page for PDF for it to render using cp1250? I couldn't find anything such in the code
Last edited by Warpedone (2017-05-15 07:36:51)
Offline
Hi, I'm using same codepage (CP 1250 , Croatian locale)
1. Default TPdfDocument.Create should use correct codepage (ACP codepage in our case cp1250)
2. You can specify codepage in constructor i.e. TPdfDocument.Create(false,1250);
try something like :
FPDF := TPdfDocument.Create; //or TPdfDocument.Create(false,1250);
try
FPDF.EmbeddedTTF := true;
//FPDF.EmbeddedWholeTTF := true;
FPDF.DefaultPaperSize := psA4;
with FPDF.AddPage do
begin
FPDF.Canvas.SetFont(StringToUTF8('Arial'),12, [] );
PDF.Canvas.TextOut(100,100, #$8A#$D0#$C8#$C6#$8E); // show characters ŠĐČĆŽ
end
FPDF.SaveToFile('Something.pdf')
finally
FreeAndNil(FPDF);
end;
However, I've found some bugs that we need to fix and I thinks it's related to your problem.
-Text that we need to print goes trough TPdfCanvas.ShowText method
-Fonts are chosen via TPdfCanvas.SetFont methos
But in order to write AnsiString #$8A#$D0#$C8#$C6#$8E (5 capital diacritics in our languages),
document uses 2 fonts : Unicode and WinAnsi (cp1252) not cp1250.
ShowText method tries to determine if any non-WinAnsi chars exist in text and sets font to
Unicode or WinAnsi font. Note that 2 chars from out text exists in WinAnsi cp1252 (#$8A and #$8E).
Those 2 letters are written using TPdfFontTrueType.WinAnsiFont, and #$D0#$C8#$C6 are written
using TPdfFontTrueType.UnicodeFont.
Problem arises when we have last ANSI character that is not in cp1252.
TPdfCanvas.ShowText switches to WinAnsi font but doesn't swith back to Unicode on next ShowText.
Furthermore TPdfCanvas.TextRect method calls TPdfCanvas.TextWidth method to calculate text position,
and fails at TPdfFontWinAnsi.GetAnsiCharWidth because fWinAnsiWidth = nil,
and TPdfCanvas.TextWidth method returns DefaultWidth * number of chars.
QuickFix would be :
1. add one blank char after text if text does not need to be aligned right
2. call TPdfCanvas.SetFont before each call to TPdfCanvas.ShowText
Of course, it won't help if you are using higher level components like TGDIPages / TRenderPages.
I've made 2 little changes to SynPDF that works for me but would need confirmation from AB :
procedure TPdfCanvas.ShowText(const text: PDFString; NextLine: boolean);
begin
if (FContents<>nil) and (text<>'') then
if (fDoc.FCharSet=ANSI_CHARSET) or IsAnsiCompatible(text) then begin
if FPage.Font.Unicode and (FPage.FFont.FTrueTypeFontsIndex<>0) then
SetPDFFont(TPdfFontTrueType(FPage.Font).WinAnsiFont,FPage.FontSize);
FContents.Writer.Add('(').AddEscapeText(pointer(text),FPage.Font).Add(')').
Add(SHOWTEXTCMD[NextLine])
end else begin
if not FPage.Font.Unicode and (FPage.FFont.FTrueTypeFontsIndex<>0) then //
if FPage.Font <> TPdfFontTrueType(FPage.Font).UnicodeFont then // gigo
SetPDFFont(TPdfFontTrueType(FPage.Font).UnicodeFont,FPage.FontSize); //
if FPage.FFont.FTrueTypeFontsIndex<>0 then
// write TrueType text after conversion to unicode
FContents.Writer.AddToUnicodeHexText(text,NextLine,self) else
// this standard font should expect MBCS encoding
FContents.Writer.Add('<').AddHex(text).Add('>').Add(SHOWTEXTCMD[NextLine]);
end;
end;
override of TPdfFontWinAnsi.GetAnsiCharWidth :
function TPdfFontTrueType.GetAnsiCharWidth(const AText: PDFString; APos: integer): integer; // gigo
var
aWideChar: WideChar;
begin
if Unicode then
begin
aWideChar := #32;
CurrentAnsiConvert.AnsiBufferToUnicode(@aWideChar,@(AText[APos]),1,True);
Result := GetWideCharWidth(aWideChar);
end
else
Result := inherited GetAnsiCharWidth(AText,APos);
end;
Best regards.
Offline