2009-08-16 4 views
12

누구나 특정 글꼴과 크기로 텍스트 조각이 얼마나 많은 페이지를 소비하는지 계산하는 쉬운 방법이 있습니까? (쉬운 = 최소한의 코드 행 + 계산적으로 저렴한). Zend_Pdf에는 getGlyphForCharacter(), getUnitsPerEm() 및 getWidthsForGlyph()에 대한 각 문자에 대한 매우 비싼 호출을 제외하고는이 작업을 수행하는 함수가 없습니다.Zend_Pdf 줄 바꿈을 위해 현재 글꼴로 된 텍스트 문자열의 길이를 계산합니다.

각 페이지마다 여러 개의 표가있는 다중 페이지 PDF를 생성 중이며 해당 열을 텍스트로 묶어야합니다. 이미 몇 초가 걸리므로 시간이 너무 오래 걸리거나 배경 작업이나 진행률 막대 등으로 어지럽히 지 않아야합니다.

유일한 해결책은 사용 된 각 글꼴 크기에서 각 문자의 너비 (포인트)를 미리 계산 한 다음 각 문자열에 대해 추가합니다. 여전히 상당히 비쌉니다.

내가 누락 된 항목이 있습니까? 아니면 더 간단한 것이 있습니까?

감사합니다.

답변

27

Gorilla3D's worst case algorithm을 사용하는 대신 너비를 정확하게 계산하는 방법이 있습니다.

나는 오른쪽 정렬 텍스트에 대한 오프셋을 계산하는 내 응용 프로그램에서 사용했습니다 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를 작성하고 가능하면 데이터를 캐싱/하드 코딩하는 것이 좋습니다.

+0

나는 이것도 사용했습니다. 광고 된대로 작동합니다. – jason

+0

좋아 보인다. 나는 약 200 개의 어구로 된 고정 어휘를 가지고 있으므로 위의 코드를 사용하여 줄 바꿈 문자열을 사전 계산하고 캐시 할 수있다. pdf는 한 번만 (첫 번째보기에서) 생성 된 다음 캐시됩니다. 이렇게하면 성능상의 불이익을 거의 느끼지 않게되고 형식을 훨씬 잘 정의 할 수 있습니다. 당신의 도움을 주셔서 감사합니다! – Steve

0

조금 더 생각해보십시오. 사용하는 글꼴의 가장 큰 Glyph를 가져와 각 문자의 너비로 사용하십시오. 정확하지는 않지만 마크를지나 텍스트가 밀리는 것을 막을 것입니다.

$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); 
관련 문제