秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  278 随笔 :: 0 文章 :: 308 评论 :: 20万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

按《lazreport的pdf导出插件lrPDFExport的DoMemoView(View: TfrMemoView)功能缺失》修复后英文显示正常,但中文显示为框框的问题。
前几天经网友“安全生产监管”提醒我,使用freepascal自带的fpPDF创建的pdf可以正常显示中文,字体名称不能用中文。lazreport的lrPDFExport就是使用fpPDF来创建pdf的。

引起这个问题的根源:
由于TfrMemoView的字体名称是中文的,如宋体等,但fpPDF使用字体本身的名称,如仿宋对应的FangSong,设置PDF字体时默认直接使用TfrMemoView的中文字体名称,所以生成pdf时找不到对应的字体。还有个问题,设置字体时还要注意字体名称的大小写,错了也不能正常显示。

lrPDFExport导出含中文的pdf中文变为框框:

修复步骤:
打开lazreport/source/addons/lrFclPDFExport/lr_e_fclpdf.pas
1、修改348行的function DefFontName:string; 
增加缺省字体:宋体/仿宋/楷体/和黑体等字体对名称,修改后如果系统如已安装以下字体之一就可以正常显示中文,但所有字体都会用缺省字体显示。

复制代码
function DefFontName:string;
const
  DefFontNames : array [1..7] of string =
     ('STSong','FangSong','KaiTi','SimHei','Liberation Sans', 'Arial', 'FreeSans');
var
  i: Integer;
begin
  for i:=1 to 7 do
    if Assigned(gTTFontCache.Find(DefFontNames[i], false, false)) then
    begin
      Result:=DefFontNames[i];
      exit;
    end;
  raise Exception.Create('Not found Sans font');
end;
复制代码

2、将memoview的中文字体名称转为系统对应字体名称,修改后就可以显示对应的中文字体,你也可以根据自己的需要添加相应的字体(233行)。

复制代码
function TExportFonts.AddItem(AFontName: string; AFontStyle: TFontStyles
  ): TExportFontItem;
var
  S1, S2, S3: String;
begin
  if AFontName='仿宋' Then AFontName:='FangSong';
  if AFontName='楷体' Then AFontName:='KaiTi';
  if AFontName='幼圆' Then AFontName:='YouYuan';
  if AFontName='黑体' Then AFontName:='SimHei';
  if AFontName='宋体' Then AFontName:='STSong';

  Result:=FindItem(AFontName, AFontStyle);
  if Assigned(Result) then exit;

  if Assigned(gTTFontCache.Find(AFontName, Graphics.fsBold in AFontStyle, Graphics.fsItalic in AFontStyle)) then
  begin
    Result:=TExportFontItem.Create(Self, AFontName, AFontStyle);
    S1:=ExtractFileDir(Result.FTTFFontInfo.FileName);
    S2:=ExtractFileName(Result.FTTFFontInfo.FileName);
    S3:=AFontName;
    FOwner.FPDFDocument.FontDirectory:=S1;
    Result.FPdfFont:=FOwner.FPDFDocument.AddFont(S2, S3);
  end
  else
    Result:=FDefaultFontNormal;
end;
复制代码

3、在linux,字体可能安装到用户目录的.local/share/fonts,还要修改下383行的procedure CreateFontDirList,添加1行。如果自行安装的字体不在这些目录,只需添加对应的目录即可。

gTTFontCache.SearchPath.Add(ExpandFileName('~/')+'.local/share/fonts');

修改后:

复制代码
procedure CreateFontDirList;
{$IFDEF WINDOWS}
var
  s: String;
{$ENDIF}
begin
  {$IFDEF WINDOWS}
  s := SHGetFolderPathUTF8(20); // CSIDL_FONTS = 20
  if s <> '' then
    gTTFontCache.SearchPath.Add(s);
  {$ENDIF}
  {$IFDEF linux}
  //tested on Fedora 24
  gTTFontCache.SearchPath.Add('/usr/share/cups/fonts/');
  gTTFontCache.SearchPath.Add('/usr/share/fonts/');
  gTTFontCache.SearchPath.Add('/usr/share/wine/fonts/');
  gTTFontCache.SearchPath.Add('/usr/local/lib/X11/fonts/');
  gTTFontCache.SearchPath.Add(ExpandFileName('~/')+'.local/share/fonts');//linuxs要添加这行
  gTTFontCache.SearchPath.Add(GetUserDir + '.fonts/');
  {$ENDIF}

end;
复制代码

2024-10-22更新:
发现新的procedure TlrPdfExportFilter.InitFonts更改了部分代码,gTTFontCache.ReadStandardFonts只读取的fonts.conf不包含我的字体目录(~/.local/share/fonts),在linux不执行CreateFontDirList,造成字体设置失败,生成只pdf只使用默认字体,添加字体目录就可以【

gTTFontCache.SearchPath.Add(GetUserDir+'.local/share/fonts');】。

复制代码
procedure TlrPdfExportFilter.InitFonts;
procedure CreateFontDirList;
{$IFDEF WINDOWS}
var
  s: String;
{$ENDIF}
begin
  {$IFDEF WINDOWS}
  s := SHGetFolderPathUTF8(20); // CSIDL_FONTS = 20
  if s <> '' then
    gTTFontCache.SearchPath.Add(s);
  {$ENDIF}
  {$IFDEF linux}
  //tested on Fedora 24
  gTTFontCache.SearchPath.Add('/usr/share/cups/fonts/');
  gTTFontCache.SearchPath.Add('/usr/share/fonts/');
  gTTFontCache.SearchPath.Add('/usr/share/wine/fonts/');
  gTTFontCache.SearchPath.Add('/usr/local/lib/X11/fonts/');
  gTTFontCache.SearchPath.Add(GetUserDir + '.fonts/');
  {$ENDIF}

end;
begin
  if gTTFontCache.Count = 0 then
  begin
    gTTFontCache.BuildFontCacheIgnoresErrors:=true;
    {$IFDEF WINDOWS}
    CreateFontDirList;
    {$ELSE}
    gTTFontCache.ReadStandardFonts;
    gTTFontCache.SearchPath.Add(GetUserDir+'.local/share/fonts');//linuxs要添加这行
    {$ENDIF}
    gTTFontCache.BuildFontCache;
  end;
end;
复制代码

修改后重新安装lrPDFExport后就可以.

如果按以上方面修改后还不能正常显示中文,请安装相关字体。

以上方法在linux已验证,上述截图是在银河麒麟 aarch64运行lazreport导出的。

lrPDFExport中文导出的效果比lazreportpdfexport强太多了,不会出现字间距的Bug。

posted on   秋·风  阅读(167)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示