使用iText与Flying-Saucer转HTML/CSS为PDF时字体样式异常求助
问题描述
我在Chrome里预览带CSS的HTML页面时显示正常(蓝色加粗标题,排版符合预期),但用iText搭配Flying-Saucer转换成PDF后,页面显示效果不一致:设置font-weight: bold后,PDF里的字体没有呈现加粗效果,反而带有黑色描边。如果移除font-weight: bold样式,HTML和PDF的显示就完全一致了。
相关代码片段:
CSS
.title{ font-size: 2em; color: #4d82bf; font-weight: bold; padding-left: 20px; }
HTML
<p class="title">鎶ュ憡涔︽�昏 Summary Overview</p>
解决方案
这个问题我之前也碰到过,核心原因是Flying-Saucer不会像Chrome那样自动模拟字体粗体,而是依赖真实的粗体字体文件,如果找不到对应字重的字体,就会用描边来替代加粗效果。可以试试下面这几个方法:
引入带粗体版本的字体文件
不要依赖系统默认字体的自动加粗,手动引入包含粗体的字体(比如Noto Sans SC、微软雅黑等都有独立的粗体文件),用@font-face在CSS里声明:@font-face { font-family: 'MyCustomFont'; src: url('fonts/my-font-regular.ttf') format('truetype'); font-weight: normal; } @font-face { font-family: 'MyCustomFont'; src: url('fonts/my-font-bold.ttf') format('truetype'); font-weight: bold; } .title{ font-family: 'MyCustomFont', sans-serif; font-size: 2em; color: #4d82bf; font-weight: bold; padding-left: 20px; }在Flying-Saucer代码中注册字体
如果是Java项目,要确保Flying-Saucer能正确加载你的字体文件,在渲染PDF前注册字体:ITextRenderer renderer = new ITextRenderer(); // 注册常规字体 renderer.getFontResolver().addFont("fonts/my-font-regular.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 注册粗体字体 renderer.getFontResolver().addFont("fonts/my-font-bold.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 加载HTML并渲染 renderer.setDocumentFromString(htmlContent); renderer.layout(); renderer.createPDF(outputStream);避免浏览器的自动加粗模拟
Chrome会自动给没有粗体的字体生成模拟加粗效果,但Flying-Saucer不支持这个功能,反而会用描边来“模拟”,这就是你看到黑色描边的原因。所以一定要用真实的粗体字体文件,而不是依赖系统模拟。检查字体格式兼容性
优先使用TrueType(.ttf)或OpenType(.otf)格式的字体,Flying-Saucer对这两种格式的支持更稳定,尽量避免使用WOFF等Web字体格式,可能会出现识别问题。
内容的提问来源于stack exchange,提问作者Underthesun

