Fastreport3.14的中文PDF输出

本文介绍了在使用Fastreport3.14时遇到的两个问题:仅Adobe Reader能正确显示中文,而Foxit Reader显示为空白;以及在Adobe Acrobat或Reader中打开PDF时提示重建。通过分析源代码,发现3.14版的一个小bug导致字体对象引用缺失。修复此bug后,可以解决Foxit Reader的显示问题。但嵌入字体仍存在问题,作者期待Fastreport3.15的增强PDF导出功能。
摘要由CSDN通过智能技术生成

参考 《让Fastreport3.x支持中文PDF的输出》一文,确实可以支持中文。但是发现两个问题:

1、只能在Adobe Reader下打开,在Foxit Reader下空白。

2、用Adobe Acrobat或者Adobe Reader打开时提示rebuild,关闭时提示save

研究了一下Fastreport3.14和3.07的源代码,发现关于字体这部分重新调整了。在3.07下,每个type0的字体有三个obj表示,而在3.14下只用两个obj(把FontDescriptor放进实际字体中去了)。3.14中源代码中有个小bug,漏掉了实际字体obj的ref(原frxPDFfile.pas的985行和986行之间)。Foxit Reader应该是严格按照ref去找obj的,找不到obj,所以显示不出来。Adobe Reader应该不是按ref找的,能够正常显示汉字,但是它会重新ref,所以提示rebuild。

修改后的TfrxPDFFont.SaveToStream替换原来的即可。

镶入字体还不行。有时间再说。3.15的说明中有说增强了PDF导出的功能,期待中。

procedure TfrxPDFFont.SaveToStream(Stream: TStream);
var
  s: string;
  b: TBitmap;
  pm: ^OUTLINETEXTMETRIC;
  FontName: string;
  i: Cardinal;
  pfont: PChar;
  FirstChar, LastChar: Integer;
  MemStream: TMemoryStream;
  MemStream1: TMemoryStream;
  pwidths: PABC;
  Charset: TFontCharSet;

  // support DBCS font name encoding
  function EncodeFontName(AFontName: string): string;
  var
    s: string;
    Index, Len: Integer;
  begin
    // Add Begin by ijia 2004.12.20
    // 修正在简体系统下繁体字体名的问题
    // 只提供 MingLiU, PMingLiU --> 细明体, 新细明体的修正
    s:=UpperCase(AFontName);
    if Copy(s, 1, 7)='MINGLIU' then
      AFontName:='细明体';

    if Copy(s, 1, 8)='PMINGLIU' then
      AFontName:='新细明体';
    // Add end
    s := '';
    Len := Length(AFontName);
    Index := 0;
    while Index < Len do
    begin
      Index := Index + 1;
      if Byte(AFontName[Index]) > $7F then
        s := s + '#' + IntToHex(Byte(AFontName[Index]), 2)
      else
        s := s + AFontname[Index];
    end;
    Result := s;
  end;

begin
  inherited SaveToStream(Stream);
  b := TBitmap.Create;
  b.Canvas.Font.Assign(Font);
  b.Canvas.Font.PixelsPerInch := 96;
  b.Canvas.Font.Size := 750;
  i := GetOutlineTextMetrics(b.Canvas.Handle, 0, nil);
  GetMem(pm, i);
  try
    try
      GetOutlineTextMetrics(b.Canvas.Handle, i, pm);
      FirstChar := Ord(pm.otmTextMetrics.tmFirstChar);
      LastChar := Ord(pm.otmTextMetrics.tmLastChar);
      FontName := StringReplace(Font.Name, ' ', '#20', [rfReplaceAll]);
      s := '';
      if fsBold in Font.Style then
        s := s + 'Bold';
      if fsItalic in Font.Style then
        s := s + 'Italic';
      if s <> '' then
        FontName := FontName + ',' + s;

      Charset := pm.otmTextMetrics.tmCharSet;
      FontName := EncodeFontName(FontName);

      Parent.XRefAdd(Stream);
      WriteLn(Stream, IntToStr(Index + Parent.FStartFonts) + ' 0 obj');
      WriteLn(Stream, '<<');
      WriteLn(Stream, '/Type /Font');
      WriteLn(Stream, '/Name /F' + IntToStr(Index - 1));
      WriteLn(Stream, '/BaseFont /' + FontName);

      // Add by ijia 2004.12.20
      //if Charset <> CHINESEBIG5_CHARSET then
      if not (Charset in [CHINESEBIG5_CHARSET, GB2312_CHARSET]) then
        WriteLn(Stream, '/Subtype /TrueType')
      else
        WriteLn(Stream, '/Subtype /Type0');

      case Charset of
        SYMBOL_CHARSET, ANSI_CHARSET:
          WriteLn(Stream, '/Encoding /WinAnsiEncoding');

        RUSSIAN_CHARSET: {1251}
          begin
            WriteLn(Stream, '/Encoding <</Type/Encoding /BaseEncoding /WinAnsiEncoding');
            Write(Stream, '/Differences [129 /afii10052');
            Write(Stream, '/quotesinglbase/afii10100/quotedblbase/ellipsis/dagger/daggerdbl/Euro/perthousand/afii10058/guilsinglleft/afii10059/afii10061/afii10060/afii10145/afii10099/quoteleft');
            Write(Stream, '/quoteright/quotedblleft/quotedblright/bullet/endash/emdash/space/trademark/afii10106/guilsinglright/afii10107/afii10109/afii10108/afii10193/space/afii10062');
            Write(Stream, '/afii10110/afii10057/currency/afii10050/brokenbar/section/afii10023/copyright/afii10053/guillemotleft/logicalnot/hyphen/registered/afii10056/degree/plusminus');
           

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值