问题:

使用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. 第五章:最后一步准备,1.8的Json模型、状态描述机制详解

    <基于1.8 Forge的Minecraft mod制作经验分享> 1.8的所有纹理材质都需要一个Json来对其描述,这一块感觉是各大神的教程里面涉及最少最浅的,我就斗胆在这分享下我研究了 ...

  2. POJ 2049 Finding Nemo

    Finding Nemo Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 8631   Accepted: 2019 Desc ...

  3. ZOJ 3822 Domination(概率dp)

    一个n行m列的棋盘,每天可以放一个棋子,问要使得棋盘的每行每列都至少有一个棋子 需要的放棋子天数的期望. dp[i][j][k]表示用了k天棋子共能占领棋盘的i行j列的概率. 他的放置策略是,每放一次 ...

  4. Electron

    跨平台桌面app开发 Appjs hex nwjs electron 官网:http://electron.atom.io/ 中文文档:https://github.com/atom/electron ...

  5. JS 点击事件失效

    有时候,会发现js失效 ,代码如果是如下的时候 <input type="button" onclick="change()"value="変更 ...

  6. 手动导出Excel及Excel导出原理探究

    前言:不知道大家有没碰到过,官方大型网站(例如中国移动)上很多地方查询列表是不提供数据导出的,而且界面上的筛选也无法满足我们的需求. 这时候我就想,如果能导出成Excel并借助自带的数据筛选方便多了. ...

  7. ASP.NET 多线程 监控任务执行情况,并显示进度条

    关于多线程的基本概念和知识在本文中不多讲,而且我懂的也不是很透,说的太多误人子弟...对于我来说,做本文提到的功能够用就行,等实现其他效果不够用的时候,再深入研究 推荐看园子里的两篇博客应该就有个基本 ...

  8. Hive学习之六 《Hive进阶— —hive jdbc》 详解

    接Hive学习五 http://www.cnblogs.com/invban/p/5331159.html 一.配置环境变量 hive jdbc的开发,在开发环境中,配置Java环境变量 修改/etc ...

  9. 绘图时,根据size()和自定义rect编程的区别

    在绘图的时候,很多时候编写的代码需要根据当前窗口自身的size来进行绘制,这个时候可以添加一个额外的中间rect来做过度,这样以后的绘图机制不会 随着size的变化而不断变化.你的处理逻辑可以保持不变 ...

  10. OOCSS学习(一)

    OOCSS —— 面向对象CSS 搜集一些该搜集的,然后汇总一下. 1.OOCSS 概念篇: 1)什么是面向对象 确定“对象”,并给这个对象创建CSS样式规则. 2)面向对象的CSS理论 OOCSS最 ...