[原]lpr成功打印中文

本文接上篇《cups-pdf编译安装》,内容都为本身根据项目经验总结,可以转载但请注明出处。作者简书id: weogkoii

开发环境:

Linux 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

CUPS及周边安装请参考前篇:《CUPS-PDF编译安装》

https://www.jianshu.com/p/4e9b15fe9386

1. lp和lpr命令简介

这两个命令都是CUPS系统自带的打印命令,为了兼容老系统而保留下来的,也是使用起来最方便的。但是,在中文打印时经常出现乱码。命令参考:

https://www.cups.org/doc/man-lp.html

https://www.cups.org/doc/man-lpr.html

已安装好的cups-pdf打印机:

#lpstat -a

cups-pdf 自从 2019年08月02日 星期五 09时13分34秒 开始接受请求

基本用法:

lpr [-P 打印机] [-#  打印份数] -U [用户名] file

lpr -P cups-pdf /tmp/3333.txt

lp [-d 打印机] [-n 打印份数] file

lp -d cups-pdf /tmp/3333.txt

2. lpr命令打印中文txt文档

使用vim随意编辑一个中文txt文档,内容如下:

#cat /tmp/ChinesePrintTest.txt

一须abc是口

调用lpr或lp使用cups-pdf进行打印,得到pdf文件却是乱码:

lpr -P cups-pdf /tmp/ChinesePrintTest.txt

期望的”一须abc是口“没有出现,而是用空白方框代替了4个中文字符,只剩余中间的abc正常打印出来。



3. 解决乱码调试分析过程

初步分析,生成的pdf文档中只有位置中间的abc正常打印了,中文字符均为空白,有可能是不支持中文字符打印。于是上网google百度了很久,发现竟然都说lp/lpr命令不支持中文,要打印pdf的话,最好是用图形化Linux的软件。但是我有点不甘心,因为cups的文档中并未说明不支持中文,而且现在utf8格式都这么多年了,这些命令也应该与时俱进了吧。反正是编译安装的,索性自己看日志看代码尝试解决。

3.1 首先分析cups日志

查看/var/log/cups/error_log,本次打印是把txt文档转换成pdf文档,一共使用4个filters,分别是texttopdf、pdftopdf、pdftops、cups-pdf,4个filter的作用分别如日志所描述:

[Job 124] 4 filters for job:

[Job 124] texttopdf (text/plain to application/pdf, cost 32)

[Job 124] pdftopdf (application/pdf to application/vnd.cups-pdf, cost 66)

[Job 124] pdftops (application/vnd.cups-pdf to application/vnd.cups-postscript, cost 100)

[Job 124] - (application/vnd.cups-postscript to printer/cups-pdf, cost 0)

由于texttopdf是cups-filters项目编译而来的,所以直接查看相应代码。接下来模拟cups调用texttopdf(如果不熟悉这部分,可以去查看相关cups filters的原理文档)。从error_log中获取调用texttopdf的参数:

[Job 124] argv[0]="cups-pdf"

[Job 124] argv[1]="124"

[Job 124] argv[2]="root"

[Job 124] argv[3]="ChinesePrintTest.txt"

[Job 124] argv[4]="1"

[Job 124] argv[5]="finishings=3 number-up=1 job-uuid=urn:uuid:431814bd-dd50-3e6b-6fbc-ae490d3763a9 job-originating-host-name=localhost date-time-at-creati    on= date-time-at-processing= time-at-creation=1564970267 time-at-processing=1564970267 document-name-supplied=ChinesePrintTest.txt"

[Job 124] argv[6]="/var/spool/cups/d00124-001"

环境变量:

[Job 124] envp[0]="CUPS_CACHEDIR=/var/cache/cups"

[Job 124] envp[1]="CUPS_DATADIR=/usr/share/cups"

[Job 124] envp[2]="CUPS_DOCROOT=/usr/share/doc/cups"

[Job 124] envp[3]="CUPS_FONTPATH=/usr/share/cups/fonts"

[Job 124] envp[4]="CUPS_REQUESTROOT=/var/spool/cups"

[Job 124] envp[5]="CUPS_SERVERBIN=/usr/lib/cups"

[Job 124] envp[6]="CUPS_SERVERROOT=/etc/cups"

[Job 124] envp[7]="CUPS_STATEDIR=/var/run/cups"

[Job 124] envp[8]="HOME=/var/spool/cups/tmp"

[Job 124] envp[9]="PATH=/usr/lib/cups/filter:/usr/bin:/usr/sbin:/bin:/usr/bin"

[Job 124] envp[10]="SERVER_ADMIN=root@ximi"

[Job 124] envp[11]="SOFTWARE=CUPS/2.2.9"

[Job 124] envp[12]="TMPDIR=/var/spool/cups/tmp"

[Job 124] envp[13]="USER=root"

[Job 124] envp[14]="CUPS_MAX_MESSAGE=2047"

[Job 124] envp[15]="CUPS_SERVER=/var/run/cups/cups.sock"

[Job 124] envp[16]="CUPS_ENCRYPTION=IfRequested"

[Job 124] envp[17]="IPP_PORT=631"

[Job 124] envp[18]="CHARSET=utf-8"

[Job 124] envp[19]="LANG=zh_CN.UTF-8"

[Job 124] envp[20]="PPD=/etc/cups/ppd/cups-pdf.ppd"

[Job 124] envp[21]="RIP_MAX_CACHE=128m"

[Job 124] envp[22]="CONTENT_TYPE=text/plain"

[Job 124] envp[23]="DEVICE_URI=cups-pdf:/"

[Job 124] envp[24]="PRINTER_INFO=cups-pdf"

[Job 124] envp[25]="PRINTER_LOCATION="

[Job 124] envp[26]="PRINTER=cups-pdf"

[Job 124] envp[27]="PRINTER_STATE_REASONS=none"

[Job 124] envp[28]="CUPS_FILETYPE=document"

[Job 124] envp[29]="FINAL_CONTENT_TYPE=application/vnd.cups-postscript"

[Job 124] envp[30]="AUTH_I****"

3.2 使用shell脚本模拟cups调用texttopdf,将stdout重写向到文件中,这个文件中就包括转换的pdf格式文件。查看其中内容:

  6 stream

  7 q

  8 0 g

  9 BT

10  18 745.884 Td

11  105.522 Tz

12  /FN02 11.333 Tf <00000000> Tj

13 ET

14 0 g

15 BT

16  46.800 745.884 Td

17  105.522 Tz

18  /FN00 11.333 Tf <004400450046> Tj

19 ET

20 0 g

21 BT

22  68.400 745.884 Td

23  105.522 Tz

24  /FN02 11.333 Tf <00000000> Tj

25 ET

26 Q

27 endstream

可以看到在stream中,原本的中文字符变成了<00000000>,只剩余<004400450046>(abc,ASCII码16进制)。从这里可以判断,应该是这一步转换出了问题,原来txt文件中的中文,在生成的pdf格式文件中已经被0000所代替了。找到了问题点,再继续分析出问题的原因。

3.3 查看txt文件格式和编码

:set ff

fileformat=unix

:set fileencoding

fileencoding=utf-8

经过查看,文件格式和编码都没有问题

3.4 查看texttopdf源码

为什么会把中文弄成空格呢?经过查看代码终于是有所发现,texttopdf没有找到中文字体?!为什么呢,vim都已经可以显示中文字符了,那为什么texttopdf却又找不到字体呢?

查看cups-filters的README发现一点线索:

TEXTTOPDF

=========

This implements a texttopdf filter, and is derived from cups' texttops.

To configure:

-------------

- texttopdf uses CUPS_DATADIR/charset/pdf.utf-8 for font configuration

  (when utf-8 was requested as charset). The font names given there are

  used as fontconfig selectors; the best matching font, that is both

  monospaced and in a supported format (TTC, TTF or OTF) will then be used.

- As a special exception, all fontnames that start with a '.' or '/' are

  considered filenames, and fontconfig is skipped; the name is used directly

  for loading the font file.

- Implementation note: TrueType Collections (.TTC) are internally handled

  by appending '/' and the index of the font inside the collection to

  the filename (e.g. to use the second font of uming.ttc, the filename

  uming.ttc/1 must be given to the fontembed-library).

  By appending the index-field returned from fontconfig, this is completely

  transparent to the user (but currently not widely tested).

- You may look at the two examples: pdf.utf-8.simple and pdf.utf-8.heavy.

To use:

-------

The filter is called just like any other cups filter. Have a

look at test.sh for example.

Known Issues

------------

- Text extraction does not work (at least for pdftotext from xpdf)

  for the resulting pdfs.

- OTF(CFF) embedding currently does not subset the fonts.

- Text wrapping in pretty-printing mode does not respect double-wide

  characters (CJK), and thus produce wrong results (wrap too late)

  for lines where they occur.  The fix is not trivial, since all the

  pretty-printing processing is done without knowledge of / prior to

  the font configuration (which is where single or double width

  code-ranges are specified).

- The hebrew example in test5.pdf shows one of our limitations:

  Compose glyphs are not composed with the primary glyph but printed

  as separate glyphs.

原来texttopdf使用CUPS_DATADIR/charset/pdf.utf-8文件配置自身的字体和字符集,看样子是这个文件配置不对。

3.5 研究pdf.utf-8配置格式

这个配置文件是一段注释,但是说得不是特别清楚,还是根据代码反推才搞明白。原来texttopdf是读取fontconfig字体配置。需要texttopdf中使用的字体都需要在这个配置文件中添加,相应字体才能被加载到texttopdf中正常使用。打开文件一看,果然没有中文字体:

charset utf8

#

# This file defines the font mappings used for Unicode/UTF-8 text printing

# through PDF.

#

# Each line consists of:

#

#  first last direction width normal bold italic bold-italic

#

# First and last are the first and last glyphs in the font mapping

# that correspond to that font; contrary to PostScript printing

# they only select the font. To find the glyph the complete unicode

# character will be looked up in the (3,1) resp. (3,0) cmap of the

# TrueType font. The glyph values are hexadecimal.

#

# Direction is the string "ltor" or "rtol", indicating left-to-right or

# right-to-left text.

#

# Width is the string "single" or "double"; double means that the glyphs

# are twice as wide as ASCII characters in the Courier typeface.

#

# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use

# for each presentation.  If characters are only available in a single

# style then only one typeface should be listed (e.g. "Symbol")

#

# Each font that is listed will be used (and downloaded if needed) when

# printing.

#

0000 04FF ltor single monospace monospace:bold monospace:oblique monospace:bold:oblique

0500 05FF rtol single monospace

“#”号开头的都是注释可以直接跳过。重点在最后面两排,表示utf8编码范围使用的对应字体。

3.5 fontconfig配置字体

用fc-list查看当前已经配置字体

/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold

/usr/share/fonts/truetype/arphic/uming.ttc: AR PL UMing TW MBE:style=Light

/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf: DejaVu Sans Mono:style=Book

/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book

/usr/share/fonts/truetype/wqy/wqy-microhei.ttc: 文泉驿微米黑,文泉驛微米黑,WenQuanYi Micro Hei:style=Regular

/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold

/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf: DejaVu Sans Mono:style=Bold

/usr/share/fonts/truetype/arphic/uming.ttc: AR PL UMing TW:style=Light

/usr/share/fonts/truetype/arphic/uming.ttc: AR PL UMing CN:style=Light

/usr/share/fonts/truetype/arphic/uming.ttc: AR PL UMing HK:style=Light

/usr/share/fonts/truetype/wqy/wqy-microhei.ttc: 文泉驿等宽微米黑,文泉驛等寬微米黑,WenQuanYi Micro Hei Mono:style=Regular

/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf: DejaVu Serif:style=Book

3.6 修改pdf.utf-8配置文件

参考pdf.utf-8.heavy文件,配置中文字体,添加下面一行在配置文件中

3000 9FFF ltor double /usr/share/fonts/truetype/arphic/uming.ttc/0

7. 成功打印中文

再次执行打印,查看pdf格式文件:

  6 stream

  7 q

  8 0 g

  9 BT

10  18 745.884 Td

11  127.059 Tz

12  /FN02 11.333 Tf <086149ba> Tj

13 ET

14 0 g

15 BT

16  46.800 745.884 Td

17  105.522 Tz

18  /FN00 11.333 Tf <004400450046> Tj

19 ET

20 0 g

21 BT

22  68.400 745.884 Td

23  127.059 Tz

24  /FN02 11.333 Tf <1dad0e10> Tj

25 ET

26 Q

27 endstream

这一次,相应的中文编码不再是0000了,变成实际对应的utf-8编码。再查看打印出来的文件:


终于使用lp/lpr命令成功打印中文了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容