2010-09-01 10 views
11

Necesito determinar la altura de una cadena (en una escala y tipo de letra dada) en postscript.¿Cómo se determina la altura de la cadena en 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 

imprimirá la prueba centrada horizontalmente (pero aún no verticalmente) en (10,10). (para ver esto, también muestro un pequeño círculo a las 10,10). También necesito determinar la altura de la cadena para centrar el texto verticalmente, pero no puedo encontrar una función para él.

Respuesta

9

¿Está familiarizado con el código PostScript que está utilizando? ¿O es simplemente copiado y pegado a ciegas desde algún lugar? Si quieres entenderlo, debes buscar en Google "Referencia del lenguaje PostScript" o "Libro rojo" o "PLRM". Estos recursos están disponibles en formato PDF de Adobe.

que el fragmento del PostScript utiliza los siguientes pasos:

  1. (test) lugares la "prueba" cadena en la parte superior de la pila.
  2. dup duplica el elemento superior de la pila. (Ahora tendrá la cadena dos veces en la pila.)
  3. stringwidth. Después de que se ejecuta este operador, se habrá consumido la cadena de "prueba" más alta y se habrán agregado dos valores a la pila en su lugar: la altura de la cuerda (más alta) y la anchura de la cuerda (la segunda desde arriba). [Actualización:En realidad, "la altura de cadena" no es del todo correcto - es más bien el desplazamiento vertical del punto actual después de terminar de dibujar la cadena ...]
  4. A continuación, se utiliza pop. Esto simplemente elimina el valor superior en la pila. Ahora, solo el ancho de la cadena permanece en la parte superior de la pila.
  5. 2 div divide ese valor por 2 y deja el resultado (la mitad del ancho de la cuerda).
  6. neg niega el valor más alto en la pila. Ahora ese valor negativo está arriba en la pila.
  7. 0 coloca el valor "0" en la parte superior de la pila.
  8. rmoveto consume los dos valores más altos en la pila y mueve el punto actual por esa distancia (la mitad del ancho de la cuerda) a la izquierda.
  9. show consume la primera cadena de "prueba" que permaneció todo el tiempo en la parte inferior de la pila y la "muestra".

¿Qué debería tener en cuenta la altura de la cuerda? Por mucho que su última línea:

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" 

Para comprender mis cambios de buscar el significado de charpath, div, exch, pathbbox, roll y sub operadores en el Libro Rojo.

Este comando utiliza Ghostscript para crear un archivo PDF en Windows a partir del código (más fácil de ver y comprobar los resultados):

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" 

El uso de 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" 

formas Mejor legibles son:

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" 

y

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" 
+1

+1 para su agradable explicación del PostScript. – DaveB

6

Simplemente añadiendo a pipitas respuesta:

/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 

El método espera que algunas de fuente ya está establecido. Funciona sobre la fuente seleccionada (setfont) y su tamaño (scalefont).

Uso (HÍpg) para obtener el cuadro delimitador más grande posible, usando caracteres en mayúscula acentuados y caracteres "debajo de la línea". El resultado es lo suficientemente bueno.

El enfoque alternativo roba de la respuesta de dreamlax - algunas fuentes no son compatibles con el operador charpath. (Consulte How can you get the height metric of a string in PostScript?)

Guardar y restaurar el contexto gráfico mantiene el punto actual en su lugar, por lo que no tiene ningún impacto sobre el "flujo" de su documento.

Espero que haya ayudado.

+0

Además, puede usar 'currentfont/FontBBox get' para el cuadro delimitador, en lugar de usar' charpath pathbbox' para obtenerlo ... en mi caso, funcionó perfectamente bajo GhostScript; sin embargo, el resultado no fue bueno cuando lo interpretó la impresora. –

3

Aquí hay una respuesta directa a la persecución, para complementar la explicación en profundidad de pipitas.

Este procedimiento posiciona y muestra una cadena centrada en el punto especificado.

/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 
1

que estaba teniendo terribles resultados utilizando los procedimientos anteriores con una fuente dingbat, entonces me di cuenta de que asumen el texto realmente se iniciará en el momento actual, que en algunos casos es muy impreciso.

Mi solución también se basa en pathbbox para calcular el ancho y la altura, pero luego también usa X0 e Y0 para llegar al origen en primer lugar.

%-- 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 
Cuestiones relacionadas