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

パフォーマンスに関しては、これをスクリプトで集中的に使用したことはありませんが、遅いことは想像できます。可能であれば、PDFをディスクに書き込むことをお勧めします。これにより、繰り返しビューが非常に高速になり、可能な場合はデータをキャッシュ/ハードコーディングできます。

于 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 に答える