Редактировать (каждую страницу) файла Postscript вручную

Я хочу (вручную) вставить дополнительные команды postscript в файл postscript, который был преобразован из файла PDF с помощью файла ghostscript pdf2ps. В целях тестирования я создал файл PDF из следующего файла, используя pdflatex:

\documentclass[a4paper]{article}
\begin{document}
Mostly empty.
\end{document}

В преобразованном файле постскриптума я делаю следующее редактирование:

...
%%Page: 1 1
%%PageBoundingBox: 0 0 595 841
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595.28 841.89]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
/Font 8 0 R
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
% BEGIN MANUAL EDIT
0 setgray 0 0 moveto 595 841 lineto stroke
% END MANUAL EDIT
5 0 obj
<</Length 257>>stream
q 0.1 0 0 0.1 0 0 cm
0 G
0 g
q
10 0 0 10 0 0 cm BT
/R6 9.9626 Tf
1 0 0 1 139.746 706.129 Tm
[(M)-0.699638(os)-0.399443(t)-0.900585(l)-0.798886(y)-333.819(e)-0.400668(m)-0.300195(p)-0.599165(t)26.0974(y)83.192(.)-0.800112]TJ
154.421 -615.691 Td
(1)Tj
ET
Q
Q

endstream
endobj
pagesave restore
%%PageTrailer
%%Trailer
end
%%EOF

Вместо создания диагональной линии файл postcipt/PDF остается (по-видимому) неизменным. Однако, если я изменяю размеры страницы с A4 на размер Letter, отображается строка:

%%Page: 1 1
%%PageBoundingBox: 0 0 612 792
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 612 792]
...

Я явно что-то здесь упускаю (что неудивительно, учитывая мои элементарные знания постскриптума). Мой вопрос: как я могу сделать так, чтобы линия отображалась, сохраняя при этом размеры страницы неизменными?

P.S.: В комментарии, на который я наткнулся, упоминалось, что pdftops (от poppler-utils) в каком-то смысле превосходит pdf2ps. Действительно, вставка команд в преобразованный файл постскриптума непосредственно перед командой showpage (которой при использовании pdf2ps вообще нет) работала нормально. Так что, наверное, я уже нашел решение своей проблемы. Однако я хотел бы узнать, какое отношение к этому имеют размеры страницы при использовании pdf2ps.


Решение

Благодаря совету KenS и ссылке на его ответ на этот вопрос Я смог добиться желаемого эффекта, добавив процедуру EndPage в файл postscript:

<<
/EndPage
{
  exch pop 2 lt
  {
    gsave
    0 0 translate
    0 setgray 0 0 moveto 596 842 lineto stroke
    grestore
    true
  }{false} ifelse
} bind
>> setpagedevice

(Предполагается, что размер страницы равен a4.)


person spirossi    schedule 24.02.2019    source источник


Ответы (1)


PostScript - это язык только для записи :-)

Серьезно, это язык программирования. Чтобы понять, что происходит, вам нужно понять программу, которая в случае вывода с устройства ps2write Ghostscript явно нетривиальна.

Синтаксис в основном такой же, как в формате PDF, с программой-прологом, которая интерпретирует его в терминах PostScript.

Программа будет использовать showpage, она делает это, когда выполняется процедура EndStream, что (в основном) происходит, когда ключевое слово endobj обнаруживается в потоке страниц. Вы увидите, что это выглядит так:

ET
Q
Q
Q

endstream
endobj
%%Page: 2 2

Между endstream и endobj можно поместить все, что угодно, но вы должны знать, что состояние графики в этой точке определяется любыми уже выполненными операциями. Это может включать в себя масштабирование, ораторское искусство, скайпинг, переворачивание вертикальной оси и т. д. Так что просто вставить туда какой-нибудь постскриптум вряд ли получится. Вы можете сделать initgraphics, который, по крайней мере, сбросит состояние графики до известной настройки.

В качестве теста я запустил устройство Ghostscript ps2write следующим образом:

gs -sDEVICE=pdfwrite -o out.ps -c "показать страницу" -f

который создает программу PostScript, в которой (действующее) содержимое:

%%EndResource
%%EndProlog
%%Page: 1 1
%%PageBoundingBox: 0 0 595 842
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 595 842]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
>>
/Contents 5 0 R
>>
endobj
%%EndPageSetup
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q

endstream
endobj
%%Trailer
end
%%EOF

Затем я изменил это более или менее так, как вы предложили:

%%EndPageSetup
0 setgray 0 0 moveto 595 842 lineto stroke
5 0 obj
<</Length 23>>stream
q 0.1 0 0 0.1 0 0 cm
Q

endstream
endobj
%%Trailer

Для меня это произвело ожидаемый штрих снизу слева вверх справа. Очевидно, что без файла PostScript, который вы изначально создали, я не могу сказать вам, почему ваш опыт отличается. (нет, я не в состоянии запустить латекс для создания такой вещи, и даже если бы я это сделал, у меня нет возможности узнать, какую версию Ghostscript и другие инструменты вы использовали).

Я предполагаю, что «что-то» в вашем PDF-файле перезаписало всю страницу, что не так уж редко.

person KenS    schedule 24.02.2019
comment
Спасибо! Я попытался понять, что происходит, посмотрев, как определяются команды (q, Q, g, G, Td, ...) в описаниях страниц (я также добавил это в свой исходный пост). По крайней мере, один из них (/Td{translate 0 0 moveto}bind def) действительно переводит систему координат. Я также заметил, что при комментировании объекта (от 5 0 obj до endobj) линия рисуется, но эффективный размер страницы, похоже, соответствует размеру буквы, а не а4. Так что кажется, что ваше предположение верно, и если я не могу понять, где подключиться к нетривиальному коду, мне не повезло (то есть с использованием pdf2ps). :-/ - person spirossi; 25.02.2019
comment
Как я уже сказал, вы можете вставить «initgraphics» в код после endstream перед endobj. Но есть больше способов изменить вывод, чем просто редактирование файла, в зависимости от того, чего вы пытаетесь достичь. Например, вы можете указать процедуру BeginPage или EndPage. Если это работает для вас, вам не нужно редактировать файл, и он будет работать на любом принтере PostScript уровня 2 или выше (в основном на любом, кроме музейного экспоната). - person KenS; 25.02.2019
comment
initgraphics ничего не изменил. Но указатель на процедуру BeginPage/EndPage — это именно то, что я искал: в конце концов я хотел бы поместить штрих-код на каждую страницу PDF-файла (поставляемого извне); Я попытался свести это к более простой проблеме в своем первоначальном вопросе. Я, вероятно, должен был упомянуть мою конечную цель ... Большое спасибо за то, что привели меня к решению! (Я отмечу ваш ответ как решение и добавлю его в свой пост.) - person spirossi; 25.02.2019