12

有没有人有一种简单的方法来计算一段文本以特定字体和大小在页面上消耗的点数?(简单 = 最少的代码行 + 计算成本低)。Zend_Pdf 似乎没有执行此操作的函数,除了对每个字符的一些非常昂贵的调用 getGlyphForCharacter()、getUnitsPerEm() 和 getWidthsForGlyph()。

我正在生成一个多页 PDF,每页上有几个表格,并且需要将文本包装在列中。创建它已经花费了几秒钟,我不希望它花费太长时间,否则我将不得不开始处理后台任务或进度条等。

我想出的唯一解决方案是预先计算使用的每种字体大小中每个字符的宽度(以磅为单位),然后将它们添加到每个字符串上。还是蛮费钱的。

我错过了什么吗?或者你有什么更简单的吗?

谢谢!

4

2 回答 2

29

有一种方法可以精确计算宽度,而不是使用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;
 }

With regard to performance, I haven't used this intensively in a script but I can imagine it's slow. I'd suggest writing the PDFs to disk, if possible, so repeat views are very fast, and caching/hard coding data where possible.

于 2009-08-16T22:49:56.487 回答
0

多想这件事。取您使用的字体的最宽字形,并将其作为每个字符的宽度。它不会是准确的,但它会防止将文本推过标记。

$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, "@newline@");
$text = explode('@newline@', $text);
于 2009-08-16T06:12:40.253 回答