Как определить высоту строки в PostScript?
Мне нужно определить высоту строки (в заданном масштабе и шрифте) в postscript.
/Helvetic-Oblique findfont
10 scalefont
setfont
10 10 1 0 360 arc fill
10 10 moveto (test) dup stringwidth pop 2 div neg 0 rmoveto show
напечатает тест по центру по горизонтали (но еще не по вертикали) в точке (10,10). (чтобы увидеть это, я также показываю маленький кружок на 10,10). Мне также нужно определить высоту строки, чтобы центрировать текст по вертикали, но я не могу найти функцию для нее.
4 ответа
Вы знакомы с кодом PostScript, который вы используете? Или это просто слепо скопировано и вставлено откуда-то? Если вы хотите понять это, вам следует поискать в "Справочнике по языку PostScript", "Красной книге" или "PLRM". Эти ресурсы доступны в формате PDF от Adobe.
Ваш фрагмент PostScript использует следующие шаги:
(test)
помещает строку "тест" на вершину стека.dup
дублирует самый верхний элемент в стеке. (Теперь у вас будет строка в стеке дважды.)stringwidth
, После выполнения этого оператора будет использована самая верхняя "тестовая" строка, и вместо этого в стек будут добавлены два значения: высота строки (самая верхняя) и ширина строки (вторая сверху). [Обновление: На самом деле, "высота строки" не совсем корректна - это скорее вертикальное смещение текущей точки после окончания рисования строки...]- Далее вы используете
pop
, Это просто удаляет самое верхнее значение в стеке. Теперь только ширина строки остается на вершине стека. 2 div
делит это значение на 2 и оставляет результат (половину ширины строки).neg
отменяет самое верхнее значение в стеке. Теперь это отрицательное значение является самым верхним в стеке.0
помещает значение "0" на вершину стека.rmoveto
затем использует два верхних значения в стеке и перемещает текущую точку на это расстояние (половину ширины строки) влево.show
потребляет первую "тестовую" строку, которая все время остается в нижней части стека, и "показывает" ее.
Итак, что будет работать, чтобы принять во внимание высоту строки? Попробуйте в качестве последней строки:
200 700 moveto (test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"
Чтобы понять мои изменения, посмотрите значение charpath
, div
, exch
, pathbbox
, roll
а также sub
операторы в Красной книге.
Эта команда использует Ghostscript для создания PDF-файла в Windows из кода (проще просматривать и проверять результаты):
gswin32c.exe ^
-o my.pdf ^
-sDEVICE=pdfwrite ^
-c "/Helvetic-Oblique findfont 10 scalefont setfont 200 700 1 0 360 arc fill 0 0 moveto (test test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"
В Linux используйте:
gs \
-o my.pdf \
-sDEVICE=pdfwrite \
-c "/Helvetic-Oblique findfont 10 scalefont setfont 200 700 1 0 360 arc fill 0 0 moveto (test test) dup true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll sub 2 div exch 200 700 moveto rmoveto show"
Лучше читаемые формы:
gswin32c ^
-o my.pdf ^
-sDEVICE=pdfwrite ^
-c "/Helvetic-Oblique findfont 10 scalefont setfont" ^
-c "200 700 1 0 360 arc fill 0 0 moveto (test test) dup" ^
-c "true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll" ^
-c "sub 2 div exch 200 700 moveto rmoveto show"
а также
gs \
-o my.pdf \
-sDEVICE=pdfwrite \
-c "/Helvetic-Oblique findfont 10 scalefont setfont" \
-c "200 700 1 0 360 arc fill 0 0 moveto (test test) dup" \
-c "true charpath pathbbox 3 -1 roll sub 2 div neg 3 1 roll" \
-c "sub 2 div exch 200 700 moveto rmoveto show"
Просто добавив к ответу pipitas:
/textheight {
gsave % save graphic context
{
100 100 moveto % move to some point
(HÍpg) true charpath pathbbox % gets text path bounding box (LLx LLy URx URy)
exch pop 3 -1 roll pop % keeps LLy and URy
exch sub % URy - LLy
}
stopped % did the last block fail?
{
pop pop % get rid of "stopped" junk
currentfont /FontMatrix get 3 get % gets alternative text height
}
if
grestore % restore graphic context
} bind def
/jumpTextLine {
textheight 1.25 mul % gets textheight and adds 1/4
0 exch neg rmoveto % move down only in Y axis
} bind def
Метод ожидает, что какой-то шрифт уже установлен. Работает над выбранным шрифтом (setfont
) и его размер (scalefont
).
Я использую (HÍpg), чтобы получить максимально возможную ограничивающую рамку, используя выделенные заглавные буквы и символы "под строкой". Результат достаточно хорош.
Альтернативный подход основан на ответе Dreamlax - некоторые шрифты не поддерживают charpath
оператор. (См. Как вы можете получить метрику высоты строки в PostScript?)
Сохранение и восстановление графического контекста сохраняет текущую точку на месте, поэтому она не влияет на "поток" вашего документа.
Надеюсь, я помог.
Вот краткий ответ, чтобы дополнить подробное объяснение Пипитаса.
Эта процедура позиционирует и показывает строку с центром в указанной точке.
/ceshow { % (string) fontsize fontname x y
gsave
moveto findfont exch scalefont setfont % s
gsave
dup false charpath flattenpath pathbbox % s x0 y0 x1 y1
grestore
3 -1 roll sub % s x0 x1 dy
3 1 roll sub % s dy -dx
2 div exch % s -dx/2 dy
-2 div % s -dx/2 -dy/2
rmoveto show
grestore
} bind def
У меня были ужасные результаты при использовании описанных выше процедур со шрифтом дингбата, затем я понял, что они предполагают, что текст действительно начинается в текущей точке, что в некоторых случаях является крайне неточным.
Мое решение также опирается на pathbbox
чтобы вычислить ширину и высоту, но затем он также использует X0 и Y0, чтобы добраться до начала координат в первую очередь.
%-- to make things nicer
/hmoveto { 0 rmoveto } def
/vmoveto { 0 exch rmoveto } def
%-- cshow means something else...
/ccshow {
dup %-- charpath consumes the string
gsave
newpath %-- else there's a strange line somewhere
0 0 moveto
true charpath flattenpath pathbbox
grestore
2 index sub -2 div vmoveto
2 index sub -2 div hmoveto
neg vmoveto
neg hmoveto
show
} def