按《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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~