0%

【Linux技术分享】处理adobe打印pdf不全问题

处理adobe打印pdf不全问题

问题

wine下使用adobe打开pdf文件后打印到cups-pdf打印机的时候无法打印pdf图片

分析

  1. 使用wine10.14打印,打印多页但是pdf打印机输出的pdf只有一页
  2. 打开psdrv和winspool发现startpage/endpage存在次数和我本地pdf页数文件一致
    1
    2
    3
    4
    5
    6
    7
    8
    0184:trace:psdrv:PSDRV_StartPage 440101A3
    0184:trace:psdrv:PSDRV_EndPage 440101A3
    0184:trace:psdrv:PSDRV_StartPage 440101A3
    0184:trace:psdrv:PSDRV_EndPage 440101A3
    0184:trace:psdrv:PSDRV_StartPage 440101A3
    0184:trace:psdrv:PSDRV_EndPage 440101A3
    0184:trace:psdrv:PSDRV_StartPage 440101A3
    0184:trace:psdrv:PSDRV_EndPage 440101A3
  3. wine中模拟window打印是将打印的目标pdf文件转换为ps(Photo Graphic)文件进行输出
  4. 截取wine下打印数据目前在高版本wine下需要从/dlls/localspl/cups.c中打印逻辑中提取
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    static NTSTATUS write_doc(void *args)
    {
    const struct write_doc_params *params = args;
    doc_t *doc = (doc_t *)(size_t)params->doc;

    /* =========== 新增:保存 PostScript 数据 =========== */
    static FILE *ps_file = NULL;
    if (!ps_file)
    {
    ps_file = fopen("/tmp/wine_print.ps", "wb");
    if (!ps_file)
    ERR("Failed to open PS debug file\n");
    }

    if (ps_file)
    {
    fwrite(params->buf, 1, params->size, ps_file);
    fflush(ps_file);
    TRACE("Saved %u bytes to /tmp/wine_print.ps\n", params->size);
    }
    /* =============================================== */

    return doc->write_doc(doc, params->buf, params->size);
    }
  5. 打印截取的.ps文件直接用pdf查看工具打开发现页面正常
  6. 将该ps文件使用lpr命令打印发现文件只有第一页,后面的未能正常显示
  7. 查看/var/spool/cups/d00060-001文件,该文件是发送至cups的文件,该文件也是正常的
  8. 怀疑本地pdf打印机问题,不支持wine下的ps格式写法,通过命令gs -dNOPAUSE -dBATCH -sDEVICE=ps2write -sOutputFile=1_fixed.ps 1.ps后ps文件打印正常
  9. 新建系统其他的pdf打印机,基于cups,在http://localhost:631/网页上进行打印机添加
  • 在/etc/cups/cups-files.conf文件中修改FileDevice Yes这一项
  • 添加打印机中选择 AppSocket/HP JetDirect这一项
  • 在Connection这一项中填写file:/tmp/1.ps
  • 选择驱动的时候选Generic-PDF_Printer-PDF.ppd
  • 打印后生成文件在/tmp/1.ps下可以直接打开
  1. wine下使用基于cups的pdf打印机进行文件打印,页数正常

解决方案

  • 创建一个自定义的pdf打印机解决
    1. 仿照pdf打印机中的ppd,创建一个自己的ppd文件
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      *PPD-Adobe: "4.3"
      *FormatVersion: "4.3"
      *FileVersion: "1.1"
      *LanguageVersion: English
      *LanguageEncoding: ISOLatin1
      *PCFileName: "GENERIC.PPD"
      *Manufacturer: "Generic"
      *Product: "(PostScript Printer)"
      *ModelName: "Generic PostScript Printer"
      *ShortNickName: "Generic PostScript Printer"
      *NickName: "Generic PostScript Printer"
      *PSVersion: "(2014.0) 0"
      *LanguageLevel: "2"
      *ColorDevice: True
      *DefaultColorSpace: RGB
      *FileSystem: False
      *Throughput: "8"
      *LandscapeOrientation: Plus90
      *TTRasterizer: Type42
      *DefaultResolution: 600dpi
      *OpenUI *PageSize/Media Size: PickOne
      *OrderDependency: 10 AnySetup *PageSize
      *DefaultPageSize: A4
      *PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
      *CloseUI: *PageSize
      *OpenUI *PageRegion: PickOne
      *OrderDependency: 10 AnySetup *PageRegion
      *DefaultPageRegion: A4
      *PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
      *CloseUI: *PageRegion
      *DefaultImageableArea: A4
      *ImageableArea A4/A4: "0 0 595 842"
      *DefaultPaperDimension: A4
      *PaperDimension A4/A4: "595 842"
    2. 创建一个自己的backend,里面运行命令类似是gs -dNOPAUSE -dBATCH -sDEVICE=ps2write -sOutputFile=1_fixed.ps 1.ps,将pdf输出到指定目录
    3. 在deb安装脚本中将backend和ppd关联起来lpadmin -p "MyManualPDF" -v "mypdf://" -E -P /usr/share/cups/model/manual_generic.ppd, 我的backend就是mypdf,打印用到我这个ppd就会找到我的backend