问题:

使用Adobe Reader将一份pdf文件通过我的虚拟打印机输出后(输出的是中间文件,等同于EMF文件),查看的时候发现有时候是乱码。最简单的必现步骤:

1、使用Adobe Reader打开pdf文件,选择我的虚拟打印机打印(取消掉adobe打印高级选项中“作为图像打印”),生成中间文件。

2、此时可以通过工具查看这个中间文件(EMF),发现并没有乱码。

3、关闭刚才打印的Adobe Reader打开的Pdf文件,再次查看中间文件,这时候就乱码了。

分析:

根据上面的必现步骤,再测试使用FoxitReader、JisuPdf打开pdf文件然后选择我的虚拟打印机打印,都没有复现。此外,生成中间文件后,即使重新用Adobe Reader打开pdf,查看中间文件的时候,仍然是乱码。

根据上述现象,去对比使用JisuPdf和Adobe Reader执行打印后生成的中间文件的区别,发现存在比较大的区别。猜测Adobe Reader在打印输出的时候为不存在的字体创建了临时字体文件,所以Adobe Reader在没关闭的时候查看不会乱码,一旦关闭了就删掉了临时文件,所以就乱码了。

比如我第一次输出的是中文文件A,不关闭Adobe Reader,查看A正常。关闭Adobe Reader查看A乱码,再次打开Adobe Reader并打印出B,查看A乱码,B不乱码。由此说明,创建的这个临时字体文件,还是和对应的中间文件相关联的,并不是所有的都一样。

我分别比较上述A和B文件内容上的区别,发现其中一个区别就是EMR_EXTCREATEFONTINDIRECTW结构中的字段不一样,而且有个比较明显的字段内容lfFaceName不一样。

查看MSDN上对EMR_EXTCREATEFONTINDIRECTW的介绍,基本可以确定就是Adobe Reader在打印输出这个pdf文件的时候创建了临时字体文件,所以一旦Adobe Reader进程关闭了,就会删除临时字体文件导致中间文件乱码。这也说明了为什么直接输出到打印机时不会,而通过我的虚拟打印机输出中间文件,如果在同一台机器上不关闭Adobe Reader进程时将中间文件输出到真实打印机不会乱码,而在另一台机器上输出会乱码。

为了确认这个问题,我使用JisuPdf和FoxitReader再分别打印出中间文件C和D。用A和C、A和D比较,发现C和D中都不存在EXTCREATEFONTINDIRECTW这个记录,由此证明以上结论。

也就是说,我这个pdf文件中使用了非内嵌并且系统尚未安装的字体,pdf阅读器在打开的时候使用了相关的字体去替换显示。

进一步分析:

现在问题转变成,为什么Adobe Reader在打印时会调用CreateFontIndirect(生成EXTCREATEFONTINDIRECTW记录),而JisuPdf和FoxitReader却不会?

另外如果生成的EMF中有EXTCREATEFONTINDIRECTW记录,如何根据这个记录创建好需要的字体从而不乱码显示呢?

经过自己解析EMF中的记录进行绘制,发现是可以通过调用CreateFontIndirect函数去实现这条EXTCREATEFONTINDIRECTW记录的,但是仍然是乱码,也就是说无法找到实际能与之匹配上的字体。

解决方案:

问题拖了比较久,最终也没找到好的解决方案,目前采用的办法是对于这种情况,要么直接使用勾选上adobe reader的矢量图打印(这种方式比较万能,原理是将每页文档都转变成一张图片,相应的占据的空间也大,并且慢很多),要么就干脆换一个pdf阅读器,比如国产的foxit。

 

pdf打印乱码问题的更多相关文章

  1. 开源免费且稳定实用的.NET PDF打印组件itextSharp(.NET组件介绍之八)

    在这个.NET组件的介绍系列中,受到了很多园友的支持,一些园友(如:数据之巅. [秦时明月]等等这些大神 )也给我提出了对应的建议,我正在努力去改正,有不足之处还望大家多多包涵.在传播一些简单的知识的 ...

  2. AndroidStudio开发Java工程(解决java控制台中文打印乱码+导入jar包运行工程)

    这篇分享一点个人AS开发java工程经验,虽然有时候还是得打开eclipse来运行java项目,但能用AS的时候还是尽量用AS,毕竟一个字,爽~ 废话不多说,进入正题. 一.开发Java工程 你有两种 ...

  3. 解决idea控制台打印乱码问题

    idea控制台打印乱码,用起来总别扭,也是在网上搜索了一番,靠一点猜测解决了. 首先打开你自己的idea的安装目录下(即右键桌面图标,点击打开文件所在位置),然后找到idea.exe.vmoption ...

  4. 基于iTextSharp的PDF操作(PDF打印,PDF下载)

    基于iTextSharp的PDF操作(PDF打印,PDF下载) 准备 1. iTextSharp的简介 iTextSharp是一个移植于java平台的iText项目,被封装成c#的组件来用于C#生成P ...

  5. NetSuite实现pdf打印中的条形码的功能

    2020-11-27 提起NS,在程序员这一块应该不怎么被人知道,算是比较小众的一门技术了,毕竟Netsuite兴起的时间算不上早,进入中国的时间更晚,除了从事这一块的程序员,可能都没有见过,恰好我是 ...

  6. .Net下的PDF打印

    简单研究了一下.Net下的PDF打印,一路发现了很多小坑. 第三方组件 这里使用的解析PDF的组件是mupdf,特点和C#调用在 这里 有介绍. 实现的功能 支持页面大小.边距.打印机选择.打印机dp ...

  7. 驰骋CCFlow开源工作流程引擎如何设置PDF打印

    前言 经常有驰骋CCFlow爱好者朋友提问关于打印相关问题.在这篇博文中大家介绍一下工作流引擎CCFlow的HTML打印和PDF打印,针对Java版本和.NET版本有不同的操作步骤,包括开关设置.水印 ...

  8. Java 创建PDF打印小册子

    概述 PDF打印小册子是指将PDF格式文档在打印成刊物前需要提前进行的页面排版,以便在打印后装订成册.下面以Java代码展示如何来实现.这里调用Free Spire.PDF for Java中的Pdf ...

  9. libreoffice转换文件为pdf文件乱码问题解决办法

    最近系统需要一个office文件预览功能 解决方案为使用libreoffice将office文件转换为pdf文件,然后使用swftools将pdf文件转换为swf文件 最后在前台使用flexpaper ...

随机推荐

  1. Camera2Raw

    This sample demonstrates how to use the Camera2 API to capture RAW camera buffers and save them as D ...

  2. yii自动登陆的验证机制浅析

    一直在使用yii进行开发, 也知道如何去使用, 也仅仅是知道怎么去用罢了, 终归是没研究过源码, 心里发虚, 今天遇到一个问题, 关于自动登陆的问题. 要求就是, 修改登陆保存session天数为自定 ...

  3. Linux 下Mysql自动备份脚本

    backdb.sh 文件 #!/bin/bash USER="root" PASSWORD="888888" DATABASE="mydb" ...

  4. 一道在知乎很火的 Java 题——如何输出 ab【转】

    这是一个源自知乎的话题,原贴链接:一道百度的面试题,有大神会嘛? 虽然我不是大神,但我也点进去看了一下,思考了一会之后有了一些思路,然后去看其它人的答案的时候果然全都已经被各路大神们先想到并贴出来了, ...

  5. call, apply, bind作用

    call, apply作用就是(改变方法中的this指向)借用别人的方法来调用,就像调用自己的一样 function Person(name) { this.name = name; } Person ...

  6. jQuery 表单验证插件——Validation(基础)

    这个插件不错,是用jquery写的.能进行表单验证.我喜欢它的原因是因为 1.他有自带的验证规则 2.你可以自己写验证规则 3.可以通过ajax与后台交互,与后台数据比较.最后返回结果!我在表单中要验 ...

  7. MSChart使用之双Y轴使用

    protected void SearchChart() { Chart1.ChartAreas.Clear(); Chart1.Series.Clear(); ChartArea _ChartAre ...

  8. 重新开始学习javase_多态(动态绑定、推迟绑定或者运行期绑定)

    一,谈向上转换,或者上溯造型 什么是向上转换(上溯造型),一句话就是父类的引用指向子类的对象.或者把子类的对象当作父类来用 为什么要进行向上转换?我们先看一个例子吧! @Test public voi ...

  9. Direct2D 加载位图

    说明: 通过WIC从文件加载位图. 可缩放后加载到内存. 源码: HRESULT LoadImageFormFile( IWICImagingFactory *pWicFactory, ID2D1Re ...

  10. 手机端MVC-js框架-Gillie-中文版本

    译者声明: 1.代码库发布在http://pablovallejo.github.io/gillie/ 2.查看API介绍直接戳这里看整理. Gillie是一个轻型MVC框架,受Backbone的启发 ...