如何修改从 1992 年开始的纯文本到 PDF 转换 PostScript 以实际指定页面大小?

Posted

技术标签:

【中文标题】如何修改从 1992 年开始的纯文本到 PDF 转换 PostScript 以实际指定页面大小?【英文标题】:How to modify this plaintext-to-PDF-converting PostScript from 1992 to actually specify a page size? 【发布时间】:2020-01-29 02:23:18 【问题描述】:

我正在尝试将纯文本文档转换为 PDF。唯一接近实际工作的方法是安装“GhostScript”,然后使用由 SE 用户@RedGrittyBrick 挖掘的以下 PostScript 脚本(谢谢),该脚本采用纯文本文档(在脚本下方)并生成 PDF来自它。

它在技术上是可行的,但在视觉上会弄乱每个页面的顶部和左侧边距,以至于顶部边距变得“太多”而左边距“有点太不适合”(与右侧相比)利润)。至少在 SumatraPDF 中查看时,这是我唯一的 PDF 查看器。

脚本声明:

/topmargin 1 inch def
/leftmargin 1 inch def

但是,它在视觉上看起来上边距可能是 4 英寸而不是 1 英寸文件中说。如果我将其修改为 0,则完成的 PDF 视觉上 似乎有 1 英寸的上边距。另一方面,如果我将左边距修改为 0 英寸,它会一直到左边框。

看来,它在视觉上看起来是正确的,在顶部/右侧/底部/左侧有适当、均匀的边距,是:

/topmargin 0 inch def
/leftmargin 0.8 inch def

但我不能一直这样,因为它很可能会在其他人的计算机/PDF 查看器上中断。即使没有,我仍然很烦我,我不明白发生了什么。

有人告诉我,发生这种情况的原因是 PostScript 没有指定“页面大小”。但是,我不知道如何将其指定到文档中,也不知道脚本的作者怎么可能一开始就没有这样做。这似乎是一个基本的重大错误,但给我它的人声称已经在许多不同的环境中成功使用它多年,那是什么意思? SumatraPDF 有非常奇特的默认设置?那个人的标准很低吗?说我要疯了?我真的不知道该怎么做,或者如何解决它。

我认为 PDF 的全部意义在于始终创建 1:1 副本,在尺寸和渲染方式上没有任何歧义......显然不是。这是脚本:

%!
%
% From: Jonathan Monsarrat (jgm@cs.brown.edu)
% Subject: PostScript -> ASCII *and* ASCII -> PostScript programs
% Newsgroups: comp.lang.postscript
% Date: 1992-10-01 04:45:38 PST 
%
% "If anyone is interested, here is an interesting program written by
% Professor John Hughes here at Brown University that formats ASCII
% in PostScript without a machine generator of any kind."
%
%%%
%%% Plan:
%%% Start with an empty string.
%%% For each character in the input stream, 
%%%    check to see if it's a carriage return.
%%%    if so, show the current string and reset it to empty
%%%    if not, add it to the current string.

/Courier findfont 10 scalefont setfont  %% Choose a fixed width font
/lineheight 
currentfont /FontBBox get dup      %% bbox bbox
0 2 getinterval    %% bbox xm ym
exch     %% xm ym bbox
2 2 getinterval    %% xm ym xM yM
aload pop    %% xm ym xM yM
3 2 roll     %% xM yM xm ym
aload pop
currentfont /FontMatrix get  %% xM yM xm ym MAT
transform    %% xM yM xm' ym'
4 2 roll
currentfont /FontMatrix get  %% xm' ym' xM yM MAT
transform    %% xm' ym' xM' yM'
exch pop     %% xm' ym' yM'
sub     %% xm' ym'-yM'
exch pop    %% dy
neg def 

lineheight pstack pop

/str 500 string def   %% Room to store a long string...
/empty 500 string def   %% An empty string to work with
/stringindex 0 def   %% How far we've filled the string
/inch 72 mul  def   %% A useful tool...
/pageheight 11 inch def
/topmargin 1 inch def
/botmargin 1 inch def
/leftmargin 1 inch def
/linesperpage pageheight topmargin sub botmargin sub lineheight div cvi def
/linenumber 1 def   %% the line we're about to write on

/newline    %% move to a new line; flush page if necessary
   linenumber linesperpage gt /linenumber 1 def showpage  if
   leftmargin pageheight topmargin sub linenumber lineheight mul sub moveto
   /linenumber linenumber 1 add def
 def

/cleanup   %% print out the last bit of whatever you had there...
   str show showpage
 def

/startstring   %% empty the string and reset its counter.
   str 0 empty putinterval
   /stringindex 0 def
 def

/showstring   %% print the string on a new line and flush it
   newline
   str show 
   startstring
 def

pstack 

/addtostring   %% put another character in the string, if there's room
   dup 500 gt popstr exch stringindex exch put
   /stringindex stringindex 1 add def ifelse
 def

%
% Main program: get characters and deal with them
%

   currentfile read cleanup exit ifelse
   dup 10 eq                   %% if it's a carriage return...
      pop showstring         %% write out this line of text and start over
      dup 0 eq         %% if it's an end-of-file mark...
       exit                %% stop!
       addtostring           %% otherwise, add the character to current string
       ifelse
      ifelse                   %% Sample data follows.
 loop

然后我运行:

ps2pdf in.ps out.pdf

【问题讨论】:

【参考方案1】:

)

将“纯文本文档”转换为 PDF 的简单方法是在您喜欢的文本编辑器中打开文档,然后从那里“另存为 PDF”或“打印为 PDF”。它比尝试使用缺乏功能的古老 PostScript 程序可靠得多(正如它对您不起作用的事实清楚地表明的那样)。最新版本的 Linux、Windows 和 Mac 都具有此功能,并避免了您所看到的那种问题。

不是假设媒体大小为 11 英寸,程序应该询问解释器以发现当前媒体大小并使用它。或者正如我回答您之前的问题here 那样,程序应该向解释器请求给定的媒体大小。正如我之前所说,您需要添加如下内容:

<<
  /PageSize [612 792]
>> setpagedevice

数组中由“[]”分隔的数字是请求的宽度和高度,以磅为单位(1/72 英寸)。显然你需要把它放在程序中主循环之前的某个地方。 setpagedevice 运算符初始化图形状态并擦除页面,因此请确保在绘制任何内容之前执行此操作。

显然,上述请求适用于 11 英寸长的美国信函媒体,正如您的程序所期望的那样。

您继续说 PDF 应该避免歧义,是的,确实如此,因为 PDF 文件中有一个媒体大小。但是你这里的不是 PDF 文件,它是一个 PostScript 程序。

PostScript 程序不需要(在您的情况下也不需要)请求媒体大小,它可以简单地使用解释器默认的任何内容。例如;美国的打印机通常有 US Letter,欧洲的打印机有 A4。因此,当您运行 PostScript 程序时,它会使用当前的默认值。在美国,您的程序可能会生成使用 US Letter 的 PDF 文件,在欧洲可能是 A4,因此您通过运行该程序生成的 PDF 文件将使用 A4。我想这就是为什么您的体验与最初为您提供程序的人不同的原因,您的环境也不同。

名称 /topmargin 并不神奇,它只是一个变量名。我不知道你熟悉哪些编程语言,但是如果我在 C++ 中创建了一个名为 topmargin 的局部变量,我不会因为它被称为 topmergin 而期望它对我的程序有任何影响。

但这与 PDF 无关,它是在两个不同环境中运行程序的结果。无论您选择使用哪种 PDF 查看器,您创建的每个 PDF 文件都将保持一致,但如果这两个文件是使用两种不同的媒体尺寸创建的,那么这两个文件看起来会有所不同。

【讨论】:

嗯,“类似的东西”并不像我需要的那样具体。至于“在您喜欢的文本编辑器中打开文档,然后‘另存为 PDF’或‘打印为 PDF’”,这不是自动化的,甚至手动也不可能。 Notepad++当然没有这样的功能。至于使用一个古老的 PostScript 程序,你不知道我花了多少无数小时尝试每一个可以想象的“解决方案”,但从未能够用任何方法创建一个合适的 PDF。它总是以某种方式中断或根本不起作用。我尝试了许多毫无价值的程序,但它们根本不起作用。 有很多方法可以自动在编辑器中打开文本文件并进行打印。我的回答的哪一部分不够具体?我已经给了你精确的调用,告诉你这些数字的含义,并解释说你需要在它进行任何绘图之前将它插入到你的程序中。很难看出我还能告诉你什么。这取决于您输入的数字,我无法为您回答,因为我不知道您的期望(例如,您没有提供完整的示例进行比较)。正如我所说,这些数字是针对 11 英寸页面的。 缺少一个完整的例子(即一个正在绘制一些实际文本的例子)意味着我不能简单地为你提供一个修改过的程序,即使我想。 好吧,我尝试添加额外的代码,它只是作为文本文档的一部分。我试图将它移到 PostScript 的不同部分,然后它什么也没做。我不是 PostScript 专家,只是希望将 80 字符行的 .txt 文件变成漂亮漂亮的 PDF 的人。一个完整的示例实际上是带有换行符后跟“abc”的脚本。 将文本文件转换为 PDF Google 文本转换为 PDF 并使用其中的一种解决方案。【参考方案2】:

因为你有 ghostscript 并且想要自动执行此操作:

#!/bin/sh
exec gs -q -sDEVICE=pdfwrite -sPAPERSIZE=letter -dNOSAFER -dNOPAUSE -sOutputFile=$1.pdf -sPROGNAME=$0 -- gslp.ps --heading-center "`date`" "$@"

请参阅 gslp 手册页以获取一些适用的帮助。

编辑:当只转换一个文本文件时,这也适用于 gs 9.50 及更高版本的 -dNOSAFER:

#!/bin/sh
exec gs -q -sDEVICE=pdfwrite -sPAPERSIZE=letter --permit-file-read="$1" -dNOPAUSE -sOutputFile=$1.pdf -sPROGNAME=$0 -- gslp.ps --heading-center "`date`" "$1"

【讨论】:

【参考方案3】:

您的 Y 问题是如何更新在 windows 成熟之前在其自己的时代非常先进的 GS 程序,以在现代 widows X 系统上工作。

专家级 GS 编写者/维护者已尝试就此提出建议,但如今有如此简单的方法可以在 Windows 中回归该 XY 任务。

Windows 使用记事本处理 PlainText,您只需在此处设置一次字体和边距即可。然后自动手动右键单击“打印”或在命令行上使用打印 /PT 选项,然后记事本将使用任何 PS 驱动程序(例如 GhostScript pdf writer 或更容易地 MS Print to PS/PDF)对其进行格式化。您还应该知道 SumatraPDF 可以读取 PlainText 并具有可以打印到 Image.PDF 的命令行打印。

所以 PrintScript 有很多方法可以获取 Text 或 Image 结构化的 PostScripted.PDF

我建议编码顺序是 a) 通过 GUI 或 CLI 使用打印管理来准备您喜欢的自定义表单,或者最简单地使用系统默认的 A4 或 Letter 页面比例。

b) 复制内置 PDF 驱动程序或添加任何其他虚拟 PS/PDF 驱动程序并将其重定向到 NonPromptPort(您可以使用默认 PromptPort 进行比较交互式测试)我将 Mine 设置为 C:\MyData\PrintOut。 PDF

c) 将记事本配置为所需的页面形式、方向,即横向或纵向和边距,如果您在 SumatraPDF 中保持先前的输出 run.pdf 打开,您甚至可以观看它编译(如在 LaTeX 中)并出现在您的眼前在 SumatraPDF 中,因为它不锁定小型 PDF

d) 编写一个 1 行 cmd(或带有错误检查),以便允许拖放或其他批量自动化,将其称为 TXT2PDF.CMD 您可以在必要时添加第三个和第四个参数,但我喜欢保持简单,因此将 %2 设置为重定向的端口驱动程序。

%SystemRoot%\system32\notepad.exe /pt "%1" "My Print to PDF"
Copy C:\MyData\PrintOut.PDF "%~dpn1.pdf"
SumatraPDF "%~dpn1.pdf"

或者对于基于自定义格式图像的 PDF,使用最新的 SumatraPDF Pre-Release

SumatraPDF -print-to "My Print to PDF" -print-settings "paperkind=A4L" "%1"

输出将是 PAI 因此不可选择的文本, 并注意在 v3.2 或之前您必须设置

EbookUI [
...
    UseFixedPageUI = True

以便查看/打印句柄 TXT(即 v3.3 不需要

后记 :-)

我忘了提及你是否喜欢你的 TXT,例如有理由然后像这样在写字板rtf中对其进行格式化

加入Doc2PDF.cmd

它会像这样在 SumatraPDF 中自动打开

注意仔细观察,看看它是如何回流的!因为 PDF 输出在保存时可能与 RTF 的边距不完全相同。

【讨论】:

以上是关于如何修改从 1992 年开始的纯文本到 PDF 转换 PostScript 以实际指定页面大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Twig 中提取从 HTML 解析的纯文本?

pdf转音频的原理

怎么用java读取pdf文件内容

[pdf转txt格式]技能!如何将PDF转成TXT文本格式?

pdf文件必须转换成word文档才可以编辑吗?

如何将excel表格转成在线文档