mORMot and Open Source friends
Check-in [539c340a81]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:
  • now handle device or bitmap fonts as the most close true-type font available
  • speed-up of internal true-type fonts list (using binary search)
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 539c340a81b1c5d46a0e30895acad22ecb5df6ab
User & Date: ab 2012-08-03 15:30:24
Context
2012-08-03
18:45
fix potential random issue in TObjectHash (and TListFieldHash), and some speed enhancment check-in: d51876633f user: ab tags: trunk
15:30
  • now handle device or bitmap fonts as the most close true-type font available
  • speed-up of internal true-type fonts list (using binary search)
check-in: 539c340a81 user: ab tags: trunk
05:48
fixed issue about BLOB unproperly serialized into JSON (e.g. now uses null) check-in: 0dfada3aa2 user: ab tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SynPdf.pas.

173
174
175
176
177
178
179


180
181
182
183
184
185
186
...
975
976
977
978
979
980
981


982
983
984
985
986
987
988
....
1038
1039
1040
1041
1042
1043
1044


1045
1046
1047
1048
1049
1050
1051
....
1322
1323
1324
1325
1326
1327
1328



1329
1330
1331
1332
1333
1334
1335
....
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
....
4245
4246
4247
4248
4249
4250
4251

4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
....
4440
4441
4442
4443
4444
4445
4446

4447
4448
4449
4450
4451
4452
4453
4454
....
4894
4895
4896
4897
4898
4899
4900













4901
4902
4903
4904
4905
4906
4907
....
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
....
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269

5270
5271
5272
5273
5274
5275
5276
....
5292
5293
5294
5295
5296
5297
5298


5299
5300

5301


5302
5303
5304
5305




5306
5307

5308
5309






5310
5311
5312
5313
5314
5315
5316
....
5349
5350
5351
5352
5353
5354
5355
5356

5357
5358
5359
5360
5361
5362
5363
....
7700
7701
7702
7703
7704
7705
7706

7707
7708
7709
7710
7711
7712
7713
  Version 1.17
  - new TPdfDocument.UseFontFallBack property (enabled by default) and
    associated FontFallBackName property (set to 'Arial Unicode MS' by default),
    used to define if the PDF document will handle "font fallback" for characters
    not existing in the current font: it will avoid rendering block/square
    symbols instead of the correct characters (e.g. for Chinese text)



}


{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64

{$define USE_UNISCRIBE}
................................................................................
    FDefaultPageHeight: Cardinal;
    FDefaultPaperSize: TPDFPaperSize;
    FCompressionMethod: TPdfCompressionMethod;
    FUseOutlines: boolean;
    FCharSet: integer;
    FCodePage: cardinal;
    FTrueTypeFonts: TRawUTF8DynArray;


    FDC: HDC;
    FScreenLogPixels: Integer;
    FStandardFontsReplace: boolean;
    fEmbeddedTTF: boolean;
    fEmbeddedWholeTTF: boolean;
    fEmbeddedTTFIgnore: TRawUTF8List;
    fRawPages: TList;
................................................................................
    // use the UnicodeFont property to get the corresponding Unicode aware
    // version, if it was used
    function GetRegisteredTrueTypeFont(AFontIndex: integer;
      AStyle: TFontStyles; ACharSet: byte): TPdfFont; overload;
    /// get the supplied TrueType Font from the internal font list
    // - if the true type font doesn't exist yet, returns NIL
    function GetRegisteredTrueTypeFont(const AFontLog: TLogFontW): TPdfFont; overload;


    // select the specified font object, then return the fDC value
    function GetDCWithFont(TTF: TPdfFontTrueType): HDC;
    /// release the current document content
    procedure FreeDoc;
  public
    /// create the PDF document instance, with a Canvas and a default A4 paper size
    // - the current charset and code page are retrieved from the SysLocale
................................................................................
    /// if Uniscribe-related methods must handle the text from right to left
    fRightToLeftText: Boolean;
{$endif}
    /// parameters taken from RenderMetaFile() call
    fUseSetTextJustification: Boolean;
    fKerningHScaleBottom: Single;
    fKerningHScaleTop: Single;



    // result := FOffsetX + (X * fFactorX);
    function I2X(X: Integer): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetX + (X * fFactorX);
    function I2X(X: Single): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetY - Y * fFactorY;
    function I2Y(Y: Integer): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetY - Y * fFactorY;
................................................................................
    // - expect the font name to be either a standard embedded font
    // ('Helvetica','Courier','Times') or its Windows equivalency (i.e.
    // 'Arial','Courier New','Times New Roman'), either a UTF-8 encoded
    // True Type font name available on the system
    // - if no CharSet is specified (i.e. if it remains -1), the current document
    // CharSet parameter is used
    function SetFont(const AName: RawUTF8; ASize: Single; AStyle: TFontStyles;
      ACharSet: integer=-1; AForceTTF: integer=-1): TPdfFont; overload;
    /// set the current font for the PDF Canvas
    // - this method use the Win32 structure that defines the characteristics
    // of the logical font
    function SetFont(ADC: HDC; const ALogFont: TLogFontW; ASize: single): TPdfFont; overload;

    /// show some text at a specified page position
    procedure TextOut(X, Y: Single; const Text: PDFString);
................................................................................
  FDC := CreateCompatibleDC(0);
  FScreenLogPixels := GetDeviceCaps(FDC, LOGPIXELSY);
  FCanvas := TPdfCanvas.Create(Self); // need FScreenLogPixels
  // retrieve true type fonts available for all charsets
  FillChar(LFont, sizeof(LFont), 0);
  LFont.lfCharset := DEFAULT_CHARSET; // enumerate ALL fonts
  EnumFontFamiliesExW(FDC, LFont, @EnumFontsProcW, PtrInt(@FTrueTypeFonts), 0);

  FCompressionMethod := cmFlateDecode; // deflate by default
  fBookMarks := TRawUTF8List.Create;
  fMissingBookmarks := TRawUTF8List.Create;
  FUseOutlines := AUseOutlines;
  fUseFontFallBack := true;
  fFontFallBackIndex := FindRawUTF8(FTrueTypeFonts,'Arial Unicode MS');
  if fFontFallBackIndex<0 then
    for i := 0 to high(FTrueTypeFonts) do
      if PosEx('Unicode',FTrueTypeFonts[i])>0 then begin
        fFontFallBackIndex := i;
        break;
      end;
  NewDoc;
................................................................................
    (Name: 'Times-Bold'; Widths: @TIMES_BOLD_W_ARRAY),
    (Name: 'Times-Oblique'; Widths: @TIMES_ITALIC_W_ARRAY),
    (Name: 'Times-BoldOblique'; Widths: @TIMES_BOLDITALIC_W_ARRAY) );
var i: integer;
    FontName2: PDFString;
begin
  // handle default embedded fonts

  if StandardFontsReplace then begin // fonts width are for WinAnsi encoding only
    FontName2 := RawUTF8ToPDFString(FontName);
    for i := 0 to high(STANDARDFONTS) do
      if SameTextU(STANDARDFONTS[i].Name,FontName) then begin
        result := TPdfFontType1.Create(FXref,FontName2,STANDARDFONTS[i].Widths);
        RegisterFont(result);
        Exit;
      end;
................................................................................
begin
  if (L1.lfWeight<>L2.lfWeight) or (L1.lfItalic<>L2.lfItalic) then
    // ignore lfHeight/lfUnderline/lfStrikeOut:
    // font size/underline/strike are internal to PDF graphics state
    result := false else
    result := (AnsiICompW(L1.lfFaceName,L2.lfFaceName)=0);
end;














function TPdfDocument.GetRegisteredTrueTypeFont(const AFontLog: TLogFontW): TPdfFont;
var i: integer;
begin
  // if specified font exists in fontlist, returns the WinAnsi version
  with FFontList do
    for i := 0 to Count-1 do begin
................................................................................
begin
  fPDFA1 := Value;
  NewDoc;
end;

procedure TPdfDocument.SetFontFallBackName(const Value: string);
begin
  fFontFallBackIndex := FindRawUTF8(FTrueTypeFonts,StringToUTF8(Value));
end;

function TPdfDocument.GetFontFallBackName: string;
begin
  if fFontFallBackIndex>=0 then
    result := UTF8ToString(FTrueTypeFonts[fFontFallBackIndex]) else
    result := '';
................................................................................
    lfUnderline := Byte(fsUnderline in AStyle);
    lfStrikeOut := Byte(fsStrikeOut in AStyle);
    UTF8ToWideChar(lfFaceName,Pointer(aFontName));
  end;
end;

function TPdfCanvas.SetFont(const AName: RawUTF8; ASize: single; AStyle: TFontStyles;
  ACharSet: integer=-1; AForceTTF: integer=-1): TPdfFont;
const
  STAND_FONTS_PDF: array[0..2] of RawUTF8 = ('Helvetica','Courier','Times');
  STAND_FONTS_WIN: array[0..2] of RawUTF8 = ('Arial','Courier New','Times New Roman');

procedure SetEmbeddedFont(ABaseFont: RawUTF8);
begin
  ABaseFont := StandardFontName(ABaseFont,AStyle);
  result := fDoc.GetRegisteredNotTrueTypeFont(RawUTF8ToPDFString(ABaseFont));
  if result=nil then
    // font not already registered -> try to add now
    result := fDoc.CreateEmbeddedFont(ABaseFont);
................................................................................
        if SameTextU(AName,STAND_FONTS_PDF[i]) or
           SameTextU(AName,STAND_FONTS_WIN[i]) then begin
          SetEmbeddedFont(STAND_FONTS_PDF[i]);
          if result<>nil then
            exit; // we got a standard/embedded font
        end;
    end;


    // search the font in the global system-wide true type fonts list
    FontIndex := FindRawUTF8(fDoc.FTrueTypeFonts,AName,False);

    if FontIndex<0  then


      // do not exist as is: find equivalency of some "standard" font
      for i := low(STAND_FONTS_PDF) to high(STAND_FONTS_PDF) do
        if SameTextU(AName,STAND_FONTS_PDF[i]) then
          FontIndex := FindRawUTF8(fDoc.FTrueTypeFonts,STAND_FONTS_WIN[i],False);




    if FontIndex<0 then
      FontIndex := FindRawUTF8(fDoc.FTrueTypeFonts,'Arial'); // default font

    if FontIndex<0 then
      raise EPdfInvalidValue.CreateFmt('SetFont %s',[string(AName)]); // error






  end;
  if ACharSet<0 then
    ACharSet := fDoc.CharSet; // force the current PDF Document charset
  result := fDoc.GetRegisteredTrueTypeFont(FontIndex+1,AStyle,ACharSet);
  if result=nil then begin
    // a font of this kind is not already registered -> create it
    fillchar(AFont,sizeof(AFont),0);
................................................................................
    byte(AStyle) := 0;
  if ALogFont.lfUnderline<>0 then
    include(AStyle,fsUnderline);
  if ALogFont.lfStrikeOut<>0 then
    include(AStyle,fsStrikeOut);
  if ALogFont.lfWeight>=FW_SEMIBOLD then
    include(AStyle,fsBold);
  result := SetFont(AName,ASize,AStyle,ALogFont.lfCharSet);

end;

procedure TPdfCanvas.TextOut(X, Y: Single; const Text: PDFString);
begin
  if FContents<>nil then begin
    FContents.Writer.Add('BT'#10).AddWithSpace(X).AddWithSpace(Y).Add('Td'#10);
    ShowText(Text);
................................................................................
  Old := SelectObject(destDC,HF);
  GetTextMetrics(destDC,TM);
  SelectObject(destDC,Old);
  DeleteObject(HF);
  with obj[aLogFont^.ihFont-1] do begin
    kind := OBJ_FONT;
    move(aLogFont^.elfw.elfLogFont,LogFont,sizeof(LogFont));

    if LogFont.lfOrientation<>0 then
      FontSpec.angle := LogFont.lfOrientation div 10 else // -360..+360
      FontSpec.angle := LogFont.lfEscapement div 10;
    FontSpec.ascent := TM.tmAscent;
    FontSpec.descent := TM.tmDescent;
    FontSpec.cell := TM.tmHeight-TM.tmInternalLeading;
  end;






>
>







 







>
>







 







>
>







 







>
>
>







 







|







 







>





|







 







>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|



>







 







>
>
|
<
>
|
>
>
|
|
<
<
>
>
>
>
|
<
>
|
<
>
>
>
>
>
>







 







|
>







 







>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
....
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
....
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
....
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
....
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
....
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
....
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
....
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
....
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
....
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326

5327
5328
5329
5330
5331
5332


5333
5334
5335
5336
5337

5338
5339

5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
....
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
....
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
  Version 1.17
  - new TPdfDocument.UseFontFallBack property (enabled by default) and
    associated FontFallBackName property (set to 'Arial Unicode MS' by default),
    used to define if the PDF document will handle "font fallback" for characters
    not existing in the current font: it will avoid rendering block/square
    symbols instead of the correct characters (e.g. for Chinese text)
  - now handle device or bitmap fonts as the most close true-type font available
  - speed-up of internal true-type fonts list (using binary search) 

}


{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64

{$define USE_UNISCRIBE}
................................................................................
    FDefaultPageHeight: Cardinal;
    FDefaultPaperSize: TPDFPaperSize;
    FCompressionMethod: TPdfCompressionMethod;
    FUseOutlines: boolean;
    FCharSet: integer;
    FCodePage: cardinal;
    FTrueTypeFonts: TRawUTF8DynArray;
    FTrueTypeFontLastName: RawUTF8;
    FTrueTypeFontLastIndex: integer;
    FDC: HDC;
    FScreenLogPixels: Integer;
    FStandardFontsReplace: boolean;
    fEmbeddedTTF: boolean;
    fEmbeddedWholeTTF: boolean;
    fEmbeddedTTFIgnore: TRawUTF8List;
    fRawPages: TList;
................................................................................
    // use the UnicodeFont property to get the corresponding Unicode aware
    // version, if it was used
    function GetRegisteredTrueTypeFont(AFontIndex: integer;
      AStyle: TFontStyles; ACharSet: byte): TPdfFont; overload;
    /// get the supplied TrueType Font from the internal font list
    // - if the true type font doesn't exist yet, returns NIL
    function GetRegisteredTrueTypeFont(const AFontLog: TLogFontW): TPdfFont; overload;
    /// find an index of in FTrueTypeFonts[]
    function GetTrueTypeFontIndex(const AName: RawUTF8): integer;
    // select the specified font object, then return the fDC value
    function GetDCWithFont(TTF: TPdfFontTrueType): HDC;
    /// release the current document content
    procedure FreeDoc;
  public
    /// create the PDF document instance, with a Canvas and a default A4 paper size
    // - the current charset and code page are retrieved from the SysLocale
................................................................................
    /// if Uniscribe-related methods must handle the text from right to left
    fRightToLeftText: Boolean;
{$endif}
    /// parameters taken from RenderMetaFile() call
    fUseSetTextJustification: Boolean;
    fKerningHScaleBottom: Single;
    fKerningHScaleTop: Single;
    // some cache
    FPreviousRasterFontName: RawUTF8;
    FPreviousRasterFontIndex: integer;
    // result := FOffsetX + (X * fFactorX);
    function I2X(X: Integer): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetX + (X * fFactorX);
    function I2X(X: Single): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetY - Y * fFactorY;
    function I2Y(Y: Integer): Single; overload; {$ifdef HASINLINE}inline;{$endif}
    // result := FOffsetY - Y * fFactorY;
................................................................................
    // - expect the font name to be either a standard embedded font
    // ('Helvetica','Courier','Times') or its Windows equivalency (i.e.
    // 'Arial','Courier New','Times New Roman'), either a UTF-8 encoded
    // True Type font name available on the system
    // - if no CharSet is specified (i.e. if it remains -1), the current document
    // CharSet parameter is used
    function SetFont(const AName: RawUTF8; ASize: Single; AStyle: TFontStyles;
      ACharSet: integer=-1; AForceTTF: integer=-1; AIsFixedWidth: boolean=false): TPdfFont; overload;
    /// set the current font for the PDF Canvas
    // - this method use the Win32 structure that defines the characteristics
    // of the logical font
    function SetFont(ADC: HDC; const ALogFont: TLogFontW; ASize: single): TPdfFont; overload;

    /// show some text at a specified page position
    procedure TextOut(X, Y: Single; const Text: PDFString);
................................................................................
  FDC := CreateCompatibleDC(0);
  FScreenLogPixels := GetDeviceCaps(FDC, LOGPIXELSY);
  FCanvas := TPdfCanvas.Create(Self); // need FScreenLogPixels
  // retrieve true type fonts available for all charsets
  FillChar(LFont, sizeof(LFont), 0);
  LFont.lfCharset := DEFAULT_CHARSET; // enumerate ALL fonts
  EnumFontFamiliesExW(FDC, LFont, @EnumFontsProcW, PtrInt(@FTrueTypeFonts), 0);
  QuickSortRawUTF8(FTrueTypeFonts,length(FTrueTypeFonts),nil,StrIComp);
  FCompressionMethod := cmFlateDecode; // deflate by default
  fBookMarks := TRawUTF8List.Create;
  fMissingBookmarks := TRawUTF8List.Create;
  FUseOutlines := AUseOutlines;
  fUseFontFallBack := true;
  fFontFallBackIndex := GetTrueTypeFontIndex('Arial Unicode MS');
  if fFontFallBackIndex<0 then
    for i := 0 to high(FTrueTypeFonts) do
      if PosEx('Unicode',FTrueTypeFonts[i])>0 then begin
        fFontFallBackIndex := i;
        break;
      end;
  NewDoc;
................................................................................
    (Name: 'Times-Bold'; Widths: @TIMES_BOLD_W_ARRAY),
    (Name: 'Times-Oblique'; Widths: @TIMES_ITALIC_W_ARRAY),
    (Name: 'Times-BoldOblique'; Widths: @TIMES_BOLDITALIC_W_ARRAY) );
var i: integer;
    FontName2: PDFString;
begin
  // handle default embedded fonts
  if StandardFontsReplace then begin
    // fonts width are for WinAnsi encoding only
    FontName2 := RawUTF8ToPDFString(FontName);
    for i := 0 to high(STANDARDFONTS) do
      if SameTextU(STANDARDFONTS[i].Name,FontName) then begin
        result := TPdfFontType1.Create(FXref,FontName2,STANDARDFONTS[i].Widths);
        RegisterFont(result);
        Exit;
      end;
................................................................................
begin
  if (L1.lfWeight<>L2.lfWeight) or (L1.lfItalic<>L2.lfItalic) then
    // ignore lfHeight/lfUnderline/lfStrikeOut:
    // font size/underline/strike are internal to PDF graphics state
    result := false else
    result := (AnsiICompW(L1.lfFaceName,L2.lfFaceName)=0);
end;

function TPdfDocument.GetTrueTypeFontIndex(const AName: RawUTF8): integer;
begin
  if StrIComp(pointer(FTrueTypeFontLastName),pointer(AName))=0 then begin
    result := FTrueTypeFontLastIndex; // simple but efficient cache
    exit;
  end;
  result := FastFindPUTF8CharSorted(pointer(FTrueTypeFonts),high(FTrueTypeFonts),pointer(AName),StrIComp);
  if result>=0 then begin
    FTrueTypeFontLastName := AName;
    FTrueTypeFontLastIndex := result;
  end;
end;

function TPdfDocument.GetRegisteredTrueTypeFont(const AFontLog: TLogFontW): TPdfFont;
var i: integer;
begin
  // if specified font exists in fontlist, returns the WinAnsi version
  with FFontList do
    for i := 0 to Count-1 do begin
................................................................................
begin
  fPDFA1 := Value;
  NewDoc;
end;

procedure TPdfDocument.SetFontFallBackName(const Value: string);
begin
  fFontFallBackIndex := GetTrueTypeFontIndex(StringToUTF8(Value));
end;

function TPdfDocument.GetFontFallBackName: string;
begin
  if fFontFallBackIndex>=0 then
    result := UTF8ToString(FTrueTypeFonts[fFontFallBackIndex]) else
    result := '';
................................................................................
    lfUnderline := Byte(fsUnderline in AStyle);
    lfStrikeOut := Byte(fsStrikeOut in AStyle);
    UTF8ToWideChar(lfFaceName,Pointer(aFontName));
  end;
end;

function TPdfCanvas.SetFont(const AName: RawUTF8; ASize: single; AStyle: TFontStyles;
  ACharSet: integer=-1; AForceTTF: integer=-1; AIsFixedWidth: boolean=false): TPdfFont;
const
  STAND_FONTS_PDF: array[0..2] of RawUTF8 = ('Helvetica','Courier','Times');
  STAND_FONTS_WIN: array[0..2] of RawUTF8 = ('Arial','Courier New','Times New Roman');
  STAND_FONTS_UPPER: array[0..2] of PUTF8Char = ('HELVETICA','COURIER','TIMES');
procedure SetEmbeddedFont(ABaseFont: RawUTF8);
begin
  ABaseFont := StandardFontName(ABaseFont,AStyle);
  result := fDoc.GetRegisteredNotTrueTypeFont(RawUTF8ToPDFString(ABaseFont));
  if result=nil then
    // font not already registered -> try to add now
    result := fDoc.CreateEmbeddedFont(ABaseFont);
................................................................................
        if SameTextU(AName,STAND_FONTS_PDF[i]) or
           SameTextU(AName,STAND_FONTS_WIN[i]) then begin
          SetEmbeddedFont(STAND_FONTS_PDF[i]);
          if result<>nil then
            exit; // we got a standard/embedded font
        end;
    end;
    if (FPreviousRasterFontName<>'') and (FPreviousRasterFontName=AName) then
      FontIndex := FPreviousRasterFontIndex else begin
      // search the font in the global system-wide true type fonts list

      FontIndex := fDoc.GetTrueTypeFontIndex(AName);
      if FontIndex<0 then begin // unknown, device or raster font
        if AIsFixedWidth then // sounds to be fixed-width -> set 'Courier'
          FontIndex := fDoc.GetTrueTypeFontIndex(STAND_FONTS_WIN[1]);
        // do not exist as is: find equivalency of some "standard" font
        for i := low(STAND_FONTS_UPPER) to high(STAND_FONTS_UPPER) do


          if (FontIndex<0) and IdemPChar(pointer(AName),STAND_FONTS_UPPER[i]) then
            FontIndex := fDoc.GetTrueTypeFontIndex(STAND_FONTS_WIN[i]);
        if FontIndex<0 then begin // use variable width default font
          FontIndex := FDoc.fFontFallBackIndex;
          if FontIndex<0 then

            FontIndex := fDoc.GetTrueTypeFontIndex('Arial');
          if FontIndex<0 then

            exit;
        end;
        FPreviousRasterFontName := AName;
        FPreviousRasterFontIndex := FontIndex;
      end;
    end;
  end;
  if ACharSet<0 then
    ACharSet := fDoc.CharSet; // force the current PDF Document charset
  result := fDoc.GetRegisteredTrueTypeFont(FontIndex+1,AStyle,ACharSet);
  if result=nil then begin
    // a font of this kind is not already registered -> create it
    fillchar(AFont,sizeof(AFont),0);
................................................................................
    byte(AStyle) := 0;
  if ALogFont.lfUnderline<>0 then
    include(AStyle,fsUnderline);
  if ALogFont.lfStrikeOut<>0 then
    include(AStyle,fsStrikeOut);
  if ALogFont.lfWeight>=FW_SEMIBOLD then
    include(AStyle,fsBold);
  result := SetFont(AName,ASize,AStyle,ALogFont.lfCharSet,-1,
    ALogFont.lfPitchAndFamily and TMPF_FIXED_PITCH=0);
end;

procedure TPdfCanvas.TextOut(X, Y: Single; const Text: PDFString);
begin
  if FContents<>nil then begin
    FContents.Writer.Add('BT'#10).AddWithSpace(X).AddWithSpace(Y).Add('Td'#10);
    ShowText(Text);
................................................................................
  Old := SelectObject(destDC,HF);
  GetTextMetrics(destDC,TM);
  SelectObject(destDC,Old);
  DeleteObject(HF);
  with obj[aLogFont^.ihFont-1] do begin
    kind := OBJ_FONT;
    move(aLogFont^.elfw.elfLogFont,LogFont,sizeof(LogFont));
    LogFont.lfPitchAndFamily := TM.tmPitchAndFamily;
    if LogFont.lfOrientation<>0 then
      FontSpec.angle := LogFont.lfOrientation div 10 else // -360..+360
      FontSpec.angle := LogFont.lfEscapement div 10;
    FontSpec.ascent := TM.tmAscent;
    FontSpec.descent := TM.tmDescent;
    FontSpec.cell := TM.tmHeight-TM.tmInternalLeading;
  end;