Synopse PDF Engine使ってみる

PDFを作成するライブラリSynopse PDF Engineを使ってみました。

基本的な使い方は、TPdfDocumentを作成して、そのCanvasに対して操作をしていくみたい。
Canvasの座標は、FormとかのCanvasと違って左下が原点になってるようです。

とりあえず、テキストを書いてみようと思ったもののアルファベットなら大丈夫だけど日本語だと表示されず。

usesにSynPdfを追加する。

procedure TForm1.Button1Click(Sender: TObject);
var
  vPDF: TPdfDocument;
  vPage: TPdfPage;
begin
  vPDF := TPdfDocument.Create(False);
  try
    vPDF.Info.Author := 'テスト';
    vPDF.Info.CreationDate := Now;
    vPDF.DefaultPaperSize := psA4;
    vPage := vPDF.AddPage;

    vPDF.Canvas.SetFont('MS Pゴシック', 9, []);
    vPDF.Canvas.BeginText;
    vPDF.Canvas.MoveTextPoint(10,300);
    vPDF.Canvas.ShowText('abcde', true);
    vPDF.Canvas.MoveTextPoint(10,200);
    vPDF.Canvas.ShowText('日本語', true);

    vPDF.Canvas.SetFont('MS P明朝', 9, []);
    vPDF.Canvas.MoveTextPoint(10,250);
    vPDF.Canvas.ShowText('あいうえお', true);

    vPDF.Canvas.EndText;
    vPDF.SaveToFile('aa.pdf');
  finally
    FreeAndNil(vPDF);
  end;
end;

ソースを追っていくと、フォント名が日本語なのがまずいらしいという事が判ったので、日本語のフォント名から英語表記のフォント名に変換出来ないかと調べてみたものの方法が判らなかった為、結局固定で変換する事にする。

SynPdf.pasの4780行目辺りTrueTypeFontNameメソッドの中身をちょっと修正。

function TPdfDocument.TTFFontPostcriptName(aFontIndex: integer; AStyle: TFontStyles;
  const ALogFont: TLogFontW): PDFString;
// see http://www.microsoft.com/typography/OTSPEC/name.htm
function TrueTypeFontName(const aFontName: RawUTF8; AStyle: TFontStyles): PDFString;
var i: Integer;
begin // from PDF 1.3 § 5.5.2end;
const NAME_POSTCRIPT = 6;
var fName: TWordDynArray;
    name: ^TNameFmt4;
    gdi, old: THandle;
    aFontName: RawUTF8;
    i, L: integer;
    Rec: ^TNameRecord;
begin
  aFontName := FTrueTypeFonts[aFontIndex];
  result := TrueTypeFontName(aFontName,AStyle);

を、下のように変更。

function TPdfDocument.TTFFontPostcriptName(aFontIndex: integer; AStyle: TFontStyles;
  const ALogFont: TLogFontW): PDFString;
// see http://www.microsoft.com/typography/OTSPEC/name.htm
function TrueTypeFontName(const aFontName: RawUTF8; AStyle: TFontStyles): PDFString;
var i: Integer;
begin // from PDF 1.3 § 5.5.2end;
const
  NAME_POSTCRIPT = 6;
  FONT_MAPPING: Array[0..3,0..1] of RawUTF8 = (
             (RawUTF8('MS ゴシック'),RawUTF8('MS Gothic'))
           , (RawUTF8('MS 明朝'), RawUTF8('MS Mincho'))
           , (RawUTF8('MS Pゴシック'), RawUTF8('MS PGothic'))
           , (RawUTF8('MS P明朝'), RawUTF8('MS PMincho')));
var fName: TWordDynArray;
    name: ^TNameFmt4;
    gdi, old: THandle;
    aFontName: RawUTF8;
    i, L: integer;
    Rec: ^TNameRecord;
begin
  aFontName := FTrueTypeFonts[aFontIndex];
  for i := Low(FONT_MAPPING) to High(FONT_MAPPING) do
  begin
    if SameTextU(aFontName, FONT_MAPPING[i][0]) then
    begin
      aFontName := FONT_MAPPING[i][1];
      break;
    end;
  end;

  result := TrueTypeFontName(aFontName,AStyle);

これで、PDFに日本語が出るようになりました。