Подтвердить что ты не робот

Zend_Pdf вычисляет длину текстовой строки в текущем шрифте для переноса строки

Есть ли у кого-нибудь простой способ рассчитать, сколько точек на странице кусок текста будет потребляться в определенном шрифте и размере? (легко = минимальные строки кода + вычислительно дешево). Zend_Pdf не имеет функции, которая делает это, за исключением некоторых очень дорогих вызовов для каждого символа getGlyphForCharacter(), getUnitsPerEm() и getWidthsForGlyph().

Я создаю многостраничный PDF файл с несколькими таблицами на каждой странице и должен обернуть текст внутри столбцов. Это уже занимает несколько секунд, чтобы создать его, и я не хочу, чтобы он занимал слишком много времени, или мне придется начать возиться с фоновые задачи или индикаторы выполнения и т.д.

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

Я что-то упустил? Или у вас есть что-то более простое?

спасибо!

4b9b3361

Ответ 1

Здесь можно точно рассчитать ширину, а не использовать алгоритм наихудшего случая Gorilla3D.

Попробуйте этот код из http://devzone.zend.com/article/2525-Zend_Pdf-tutorial#comments-2535

Я использовал его в своем приложении для вычисления смещений для выравнивания по правому краю текста и работает

/**
* 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;
 }

Что касается производительности, я не использовал это интенсивно в script, но я могу представить, что он медленный. Я бы посоветовал писать PDF файлы на диск, если это возможно, так что повторение представлений происходит очень быстро, и, где это возможно, кэшировать/записывать жесткие данные.

Ответ 2

Размышление над этим немного больше. Возьмите самые широкие шрифты шрифта, который вы используете, и основываетесь на этом как ширина для каждого символа. Он не будет точным, но это предотвратит нажатие текста за меткой.

$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);