问题现象:
使用pdfbox,将PDF转成图片后,其中的中文显示乱码(方块□□□□□)
控制台日志如下:
no glyph for 38472 (CID 04e7) in font STSong-Light
解读此行日志,先识别字体为STSong-Light,但系统中没有找到此字库,所以默认匹配到了MalgunGothic-Semilight。此字库为韩语字库,无法显示出中文,所以中文显示为□□□□□。
上述类中的63行打了一个日志表示找不到字体。大概就是这样的:
if (!font.hasGlyph(code)){int cid = font.getParent().codeToCID(code);String cidHex = String.format("%04x", cid);LOG.warn("No glyph for " + code + " (CID " + cidHex + ") in font " + fontName);}
从 提出字体的地址 中看到,AdobeSongStd-Light.otf,这个字体可以解决这个问题。
解决方案1:
AdobeSongStd-Light.otf
电脑安装上面字体,C:\Windows\Fonts目录下,或者在项目中加载字体,但是当时openshift时有时加载失败,windows暂没问题。
解决方案2:(推荐)
进入pdfbox包内的如下文件
找到如下位置,可以看到substitutes内的一个映射关系,我们可以将STSong-Light映射到另一已存在的字体
FontMapperImpl() {
this.substitutes.put("Courier", Arrays.asList("CourierNew", "CourierNewPSMT", "LiberationMono", "NimbusMonL-Regu"));
this.substitutes.put("Courier-Bold", Arrays.asList("CourierNewPS-BoldMT", "CourierNew-Bold", "LiberationMono-Bold", "NimbusMonL-Bold"));
this.substitutes.put("Courier-Oblique", Arrays.asList("CourierNewPS-ItalicMT", "CourierNew-Italic", "LiberationMono-Italic", "NimbusMonL-ReguObli"));
this.substitutes.put("Courier-BoldOblique", Arrays.asList("CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", "LiberationMono-BoldItalic", "NimbusMonL-BoldObli"));
this.substitutes.put("Helvetica", Arrays.asList("ArialMT", "Arial", "LiberationSans", "NimbusSanL-Regu"));
this.substitutes.put("Helvetica-Bold", Arrays.asList("Arial-BoldMT", "Arial-Bold", "LiberationSans-Bold", "NimbusSanL-Bold"));
this.substitutes.put("Helvetica-Oblique", Arrays.asList("Arial-ItalicMT", "Arial-Italic", "Helvetica-Italic", "LiberationSans-Italic", "NimbusSanL-ReguItal"));
this.substitutes.put("Helvetica-BoldOblique", Arrays.asList("Arial-BoldItalicMT", "Helvetica-BoldItalic", "LiberationSans-BoldItalic", "NimbusSanL-BoldItal"));
this.substitutes.put("Times-Roman", Arrays.asList("TimesNewRomanPSMT", "TimesNewRoman", "TimesNewRomanPS", "LiberationSerif", "NimbusRomNo9L-Regu"));
this.substitutes.put("Times-Bold", Arrays.asList("TimesNewRomanPS-BoldMT", "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", "LiberationSerif-Bold", "NimbusRomNo9L-Medi"));
this.substitutes.put("Times-Italic", Arrays.asList("TimesNewRomanPS-ItalicMT", "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", "LiberationSerif-Italic", "NimbusRomNo9L-ReguItal"));
this.substitutes.put("Times-BoldItalic", Arrays.asList("TimesNewRomanPS-BoldItalicMT", "TimesNewRomanPS-BoldItalic", "TimesNewRoman-BoldItalic", "LiberationSerif-BoldItalic", "NimbusRomNo9L-MediItal"));
this.substitutes.put("Symbol", Arrays.asList("Symbol", "SymbolMT", "StandardSymL"));
this.substitutes.put("ZapfDingbats", Arrays.asList("ZapfDingbatsITC", "Dingbats", "MS-Gothic"));
Iterator var1 = Standard14Fonts.getNames().iterator();
先按照这个FontMapperImpl类在自己的项目中建立一个和这个路径完全一致的FontMapperImpl类,代码内容复制过来。
并在substitutes中增加一个STSong-Light的映射关系,映射到我的环境中已有的AdobeSongStd-Light字体。
this.substitutes.put("STSong-Light", Arrays.asList("AdobeSongStd-Light"));
重新执行就成功了。