2009-08-16 12 views
12

¿Alguien tiene una manera fácil de calcular cuántos puntos en una página consumirá un texto en una fuente y tamaño en particular? (fácil = líneas mínimas de código + computacionalmente económicas). Zend_Pdf no parece tener una función que lo haga, excepto algunas llamadas muy costosas para cada personaje a getGlyphForCharacter(), getUnitsPerEm() y getWidthsForGlyph().Zend_Pdf calcular la longitud de la cadena de texto en la fuente actual para el ajuste de línea

Estoy generando un PDF de varias páginas con varias tablas en cada página, y necesito ajustar el texto dentro de las columnas. Ya está tardando unos segundos en crearlo, y no quiero que tarde demasiado o tendré que empezar a jugar con las tareas en segundo plano o barras de progreso, etc.

La única solución que se me ocurrió está calculando previamente el ancho (en puntos) de cada carácter en cada tamaño de fuente utilizado, y luego suma esto sobre cada cadena. Aún bastante costoso.

¿Echo de menos algo? ¿O tienes algo más simple?

gracias!

Respuesta

27

Hay una manera de calcular el ancho exactamente, en lugar de usar Gorilla3D's worst case algorithm.

Prueba este código de http://devzone.zend.com/article/2525-Zend_Pdf-tutorial#comments-2535

Lo he utilizado en mi aplicación para el cálculo de las compensaciones para el texto alineado a la derecha y funciona

/** 
* Returns the total width in points of the string using the specified font and 
* size. 
* 
* This is not the most efficient way to perform this calculation. I'm 
* concentrating optimization efforts on the upcoming layout manager class. 
* Similar calculations exist inside the layout manager class, but widths are 
* generally calculated only after determining line fragments. 
* 
* @link http://devzone.zend.com/article/2525-Zend_Pdf-tutorial#comments-2535 
* @param string $string 
* @param Zend_Pdf_Resource_Font $font 
* @param float $fontSize Font size in points 
* @return float 
*/ 
function widthForStringUsingFontSize($string, $font, $fontSize) 
{ 
    $drawingString = iconv('UTF-8', 'UTF-16BE//IGNORE', $string); 
    $characters = array(); 
    for ($i = 0; $i < strlen($drawingString); $i++) { 
     $characters[] = (ord($drawingString[$i++]) << 8) | ord($drawingString[$i]); 
    } 
    $glyphs = $font->glyphNumbersForCharacters($characters); 
    $widths = $font->widthsForGlyphs($glyphs); 
    $stringWidth = (array_sum($widths)/$font->getUnitsPerEm()) * $fontSize; 
    return $stringWidth; 
} 

Con respecto al rendimiento, no he utilizado este intensivamente en un guión, pero me puedo imaginar que es lento. Sugiero que escribas los archivos PDF en el disco, si es posible, para que las vistas repetidas sean muy rápidas y los datos de la codificación en caché/disco duro siempre que sea posible.

+0

Lo he usado también. Funciona como se anuncia. – jason

+0

que se ve bien. Tengo un vocabulario fijo de aproximadamente 200 frases, por lo que podría usar el código anterior (ligeramente adaptado) para calcular previamente y almacenar en caché las cadenas envolventes de la palabra. El pdf se genera solo una vez (a primera vista) y luego se almacena en caché también. Esto debería dar como resultado casi ninguna penalización de rendimiento y un formato mucho más agradable. ¡Gracias por tu ayuda! – Steve

0

Pensando en esto un poco más. Tome los glifos más anchos de la fuente que usa y basándolos en el ancho de cada carácter. No será preciso, pero evitará que el texto pase la marca.

$pdf = new Zend_Pdf(); 
$font  = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_COURIER); 
$font_size = $pdf->getFontSize(); 


$letters = array(); 
foreach(range(0, 127) as $idx) 
{ 
    array_push($letters, chr($idx)); 
} 
$max_width = max($font->widthsForGlyphs($letters)); 

// Text wrapping settings 
$text_font_size = $max_width; // widest possible glyph 
$text_max_width = 238;  // 238px 

// Text wrapping calcs 
$posible_character_limit = round($text_max_width/$text_font_size); 
$text = wordwrap($text, $posible_character_limit, "@[email protected]"); 
$text = explode('@[email protected]', $text); 
Cuestiones relacionadas