Programmer's Reference Guide

Sauvegarder les changement dans un document PDF

Les pages d'un document

Création de page

Les pages d'un document PDF sont représentés par la classe Zend_Pdf_Page

Les pages d'un PDF proviennent d'un PDF existant, ou sont créées à partir de rien.

Une nouvelle page peut-être obtenu en créant un nouvel objet Zend_Pdf_Page ou en appelant la méthode Zend_Pdf::newPage()qui retourne un objet Zend_Pdf_Page. La différence est que la méthode Zend_Pdf::newPage() crée une page directement attachée au document. A la différence des pages non attachées à un document, elle ne peut-être utilisée dans plusieurs documents PDF, mais est un peu plus performante. [1] Zend_Pdf . C'est à vous de choisir quel approche doit-être utilisée.

Les méthodes Zend_Pdf::newPage() et Zend_Pdf_Page prennent le même paramètre. C'est la taille de la page ($x, $y) en point (1/72 inch soit 0,352778 mm), ou une constante prédéfinie, qui correspond au format du papier :

  • Zend_Pdf_Page::SIZE_A4

  • Zend_Pdf_Page::SIZE_A4_LANDSCAPE

  • Zend_Pdf_Page::SIZE_LETTER

  • Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE

Les pages du document sont stockées dans l'attribut public $pages de la classe Zend_Pdf. C'est un tableau d'objet Zend_Pdf_Page. Il définit l'ensemble des pages, ainsi que l'ordre de celle-ci et peut-être manipulé comme un tableau classique :

Exemple #1 Gestion des pages d'un document PDF

  1. ...
  2. // Inverse l'ordre des pages
  3. $pdf->pages = array_reverse($pdf->pages);
  4. ...
  5. // Ajoute une nouvelle page
  6. $pdf->pages[] = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
  7. // Ajoute une nouvelle page
  8. $pdf->pages[] = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  9.  
  10. // Retire la page spécifiée
  11. unset($pdf->pages[$id]);
  12. ...

Clonage de page

Les pages existantes d'un PDF peuvent être clonées en créant un nouvel objet Zend_Pdf_Page avec la page existante comme paramètre :

Exemple #2 Cloner une page existante

  1. ...
  2. // Stocke le modèle dans une variable séparée
  3. $template = $pdf->pages[$templatePageIndex];
  4. ...
  5. // Ajoute une nouvelle page
  6. $page1 = new Zend_Pdf_Page($template);
  7. $pdf->pages[] = $page1;
  8. ...
  9.  
  10. // Ajoute une autre page
  11. $page2 = new Zend_Pdf_Page($template);
  12. $pdf->pages[] = $page2;
  13. ...
  14.  
  15. // Enlève la page modèle du document
  16. unset($pdf->pages[$templatePageIndex]);
  17. ...

C'est pratique si plusieurs pages doivent être créées sur le même modèle.

Attention

Important ! La page clonée partage quelques ressources PDF avec la page modèle, donc ceci doit être utilisé seulement dans le même document qu'une page modèle. Le document modifié peut être sauvegardé comme nouveau document.

[1] C'est une limitation de la version courante du module . Ce sera corrigé dans une future version. Mais les pages non attachées à un document donneront toujours de meilleurs résultats pour partager une page entre plusieurs documents.

Sauvegarder les changement dans un document PDF

Comments

I've created a very usefull utilityclass. I've used some code from the forums.


<?php 

require_once 'Zend/Pdf.php';

class 
My_Pdf extends Zend_Pdf{
    
    
/**
     * The default encoding
     * 
     * @var string
     */
    
public static $encoding 'UTF-8';

    
/**
     * Align text at left of provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_LEFT 'left';
    
    
/**
     * Align text at right of provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_RIGHT 'right';
    
    
/**
     * Center-text horizontally within provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_CENTER 'center';
    
    
/**
     * Extension of basic draw-text function to allow it to vertically center text
     *
     * @param Zend_Pdf_Page $page
     * @param string $text
     * @param int $x1
     * @param int $y1
     * @param int $x2
     * @param int $position
     * @param string $encoding
     * @return Zend_Pdf_Page
     */
    
public static function drawText(Zend_Pdf_Page $page$text$x1$y1$x2 null$position self::TEXT_ALIGN_LEFT$encoding null){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$bottom $y1// could do the same for vertical-centering
        
switch ($position) {
            case 
self::TEXT_ALIGN_LEFT :
                
$left $x1;
                break;
            case 
self::TEXT_ALIGN_RIGHT :
            if (
null === $x2) {
                    throw new 
Exception "Cannot right-align text horizontally, x2 is not provided" );
                }
                
$textWidth self::getTextWidth $text$page );
                
$left $x2 $textWidth;
                break;
            case 
self::TEXT_ALIGN_CENTER :
                if (
null === $x2) {
                    throw new 
Exception "Cannot center text horizontally, x2 is not provided" );
                }
                
$textWidth self::getTextWidth $text$page );
                
$left $x1 $textWidth 2;
                break;
            default :
                throw new 
Exception "Invalid position value \"$position\"" );
        }
        
        
// display multi-line text
        
$page->drawText $text$left$y1$encoding );
        return 
$page;
    }
    
    
/**
     * Draw text inside a box using word wrap
     * 
     * @param Zend_Pdf_Page $page
     * @param string $text
     * @param int $x1
     * @param int $y1
     * @param int $x2
     * @param int $position
     * @param float $lineHeight
     * @param string $encoding
     * 
     * @return integer bottomPosition
     */
    
public static function drawTextBox(Zend_Pdf_Page $page$text$x1$y1$x2 null$position self::TEXT_ALIGN_LEFT$lineHeight 1.1$encoding null){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$lines explode(PHP_EOL$text);
        
        
$bottom $y1;
        
$lineHeight $page->getFontSize() * $lineHeight;
        foreach( 
$lines as $line ){
            
preg_match_all('/([^\s]*\s*)/i'$line$matches);
            
            
$words $matches[1];
            
            
$lineText '';
            
$lineWidth 0;
            foreach( 
$words as $word ){
                
$wordWidth self::getTextWidth($word$page);
                
                if( 
$lineWidth+$wordWidth $x2-$x1 ){
                    
$lineText .= $word;
                    
$lineWidth += $wordWidth;
                }else{
                    
self::drawText$page$lineText$x1$bottom$x2$position$encoding );
                    
$bottom -= $lineHeight;
                    
$lineText $word;
                    
$lineWidth $wordWidth;
                }
            }
            
            
self::drawText$page$lineText$x1$bottom$x2$position$encoding );
            
$bottom -= $lineHeight;
        }
        
        return 
$bottom;
    }
    
    
/**
     * Create pages from a text using wrapping
     * 
     * @param Zend_Pdf_Page $template    The template where all new pages are created on
     * @param string $text                The text
     * @param array $margins              array(top, right, bottom, left) Margins from the borders of the document
     * @param align $position            self::TEXT_ALIGN_LEFT
     * @param lineheight $lineHeight    The lineheight, by default 1.1 = 110% of text-height
     * @param string $encoding            If null the self::$encoding is used
     * @return array $pages                Array of created pages
     */
    
public static function createPagesZend_Pdf_Page $template$text$margins=array(40,28,40,28), $position self::TEXT_ALIGN_LEFT$lineHeight 1.1$encoding null ){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$pages = array();
        
$currentPage null;
        
        
$lines explode("\n"$text);
        
        
$lineHeight $template->getFontSize() * $lineHeight;
        
$x1 $margins[1];
        
$x2 $template->getWidth() - $margins[1];
        
$y1 $template->getHeight() - $margins[0] - $lineHeight;
        
$y2 $margins[2];
        
        
$bottom $y1;
        foreach( 
$lines as $line ){
            
            if( 
$currentPage == null || $bottom <= $y2 ){
                
$pages[] = $currentPage = new Zend_Pdf_Page$template );
                
$currentPage->setFont$template->getFont(), $template->getFontSize() );
                
$bottom $y1;
            }
            
            
preg_match_all('/([^\s+\-,.\\/]*[\s+\-,.\\/]*)/i'$line$matches);
            
            
$words $matches[1];
            
            
$lineText '';
            
$lineWidth 0;
            foreach( 
$words as $word ){
                
$wordWidth self::getTextWidth($word$currentPage);
                
                if( 
$lineWidth+$wordWidth $x2-$x1 ){
                    
$lineText .= $word;
                    
$lineWidth += $wordWidth;
                }else{
                    
self::drawText$currentPage$lineText$x1$bottom$x2$position$encoding );
                    
$bottom -= $lineHeight;
                    
$lineText $word;
                    
$lineWidth $wordWidth;
                }
            }
            
            
self::drawText$currentPage$lineText$x1$bottom$x2$position$encoding );
            
$bottom -= $lineHeight;
        }
        
        return 
$pages;
    }
    
    
/**
     * Return length of generated string in points
     *
     * @param string                     $text
     * @param Zend_Pdf_Resource_Font|Zend_Pdf_Page     $font
     * @param int                         $fontSize
     * @return double
     */
    
public static function getTextWidth($text$resource$fontSize null$encoding null) {
        if( 
$encoding == null $encoding self::$encoding;
        
        if( 
$resource instanceof Zend_Pdf_Page ){
            
$font $resource->getFont();
            
$fontSize $resource->getFontSize();
        }elseif( 
$resource instanceof Zend_Pdf_Resource_Font ){
            
$font $resource;
            if( 
$fontSize === null ) throw new Exception('The fontsize is unknown');
        }
        
        if( !
$font instanceof Zend_Pdf_Resource_Font ){
            throw new 
Exception('Invalid resource passed');
        }
        
        
$drawingText iconv ''$encoding$text );
        
$characters = array ();
        for(
$i 0$i strlen $drawingText ); $i ++) {
            
$characters [] = ord $drawingText [$i] );
        }
        
$glyphs $font->glyphNumbersForCharacters $characters );
        
$widths $font->widthsForGlyphs $glyphs );
        
$textWidth = (array_sum $widths ) / $font->getUnitsPerEm ()) * $fontSize;
        return 
$textWidth;
    }
    
}
I've created a very usefull utilityclass. I've used some code from the forums.


<?php 

require_once 'Zend/Pdf.php';

class 
My_Pdf extends Zend_Pdf{
    
    
/**
     * The default encoding
     * 
     * @var string
     */
    
public static $encoding 'UTF-8';

    
/**
     * Align text at left of provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_LEFT 'left';
    
    
/**
     * Align text at right of provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_RIGHT 'right';
    
    
/**
     * Center-text horizontally within provided coordinates
     * 
     * @var string
     */
    
const TEXT_ALIGN_CENTER 'center';
    
    
/**
     * Extension of basic draw-text function to allow it to vertically center text
     *
     * @param Zend_Pdf_Page $page
     * @param string $text
     * @param int $x1
     * @param int $y1
     * @param int $x2
     * @param int $position
     * @param string $encoding
     * @return Zend_Pdf_Page
     */
    
public static function drawText(Zend_Pdf_Page $page$text$x1$y1$x2 null$position self::TEXT_ALIGN_LEFT$encoding null){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$bottom $y1// could do the same for vertical-centering
        
switch ($position) {
            case 
self::TEXT_ALIGN_LEFT :
                
$left $x1;
                break;
            case 
self::TEXT_ALIGN_RIGHT :
            if (
null === $x2) {
                    throw new 
Exception "Cannot right-align text horizontally, x2 is not provided" );
                }
                
$textWidth self::getTextWidth $text$page );
                
$left $x2 $textWidth;
                break;
            case 
self::TEXT_ALIGN_CENTER :
                if (
null === $x2) {
                    throw new 
Exception "Cannot center text horizontally, x2 is not provided" );
                }
                
$textWidth self::getTextWidth $text$page );
                
$left $x1 $textWidth 2;
                break;
            default :
                throw new 
Exception "Invalid position value \"$position\"" );
        }
        
        
// display multi-line text
        
$page->drawText $text$left$y1$encoding );
        return 
$page;
    }
    
    
/**
     * Draw text inside a box using word wrap
     * 
     * @param Zend_Pdf_Page $page
     * @param string $text
     * @param int $x1
     * @param int $y1
     * @param int $x2
     * @param int $position
     * @param float $lineHeight
     * @param string $encoding
     * 
     * @return integer bottomPosition
     */
    
public static function drawTextBox(Zend_Pdf_Page $page$text$x1$y1$x2 null$position self::TEXT_ALIGN_LEFT$lineHeight 1.1$encoding null){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$lines explode(PHP_EOL$text);
        
        
$bottom $y1;
        
$lineHeight $page->getFontSize() * $lineHeight;
        foreach( 
$lines as $line ){
            
preg_match_all('/([^\s]*\s*)/i'$line$matches);
            
            
$words $matches[1];
            
            
$lineText '';
            
$lineWidth 0;
            foreach( 
$words as $word ){
                
$wordWidth self::getTextWidth($word$page);
                
                if( 
$lineWidth+$wordWidth $x2-$x1 ){
                    
$lineText .= $word;
                    
$lineWidth += $wordWidth;
                }else{
                    
self::drawText$page$lineText$x1$bottom$x2$position$encoding );
                    
$bottom -= $lineHeight;
                    
$lineText $word;
                    
$lineWidth $wordWidth;
                }
            }
            
            
self::drawText$page$lineText$x1$bottom$x2$position$encoding );
            
$bottom -= $lineHeight;
        }
        
        return 
$bottom;
    }
    
    
/**
     * Create pages from a text using wrapping
     * 
     * @param Zend_Pdf_Page $template    The template where all new pages are created on
     * @param string $text                The text
     * @param array $margins              array(top, right, bottom, left) Margins from the borders of the document
     * @param align $position            self::TEXT_ALIGN_LEFT
     * @param lineheight $lineHeight    The lineheight, by default 1.1 = 110% of text-height
     * @param string $encoding            If null the self::$encoding is used
     * @return array $pages                Array of created pages
     */
    
public static function createPagesZend_Pdf_Page $template$text$margins=array(40,28,40,28), $position self::TEXT_ALIGN_LEFT$lineHeight 1.1$encoding null ){
        if( 
$encoding == null $encoding self::$encoding;
        
        
$pages = array();
        
$currentPage null;
        
        
$lines explode("\n"$text);
        
        
$lineHeight $template->getFontSize() * $lineHeight;
        
$x1 $margins[1];
        
$x2 $template->getWidth() - $margins[1];
        
$y1 $template->getHeight() - $margins[0] - $lineHeight;
        
$y2 $margins[2];
        
        
$bottom $y1;
        foreach( 
$lines as $line ){
            
            if( 
$currentPage == null || $bottom <= $y2 ){
                
$pages[] = $currentPage = new Zend_Pdf_Page$template );
                
$currentPage->setFont$template->getFont(), $template->getFontSize() );
                
$bottom $y1;
            }
            
            
preg_match_all('/([^\s+\-,.\\/]*[\s+\-,.\\/]*)/i'$line$matches);
            
            
$words $matches[1];
            
            
$lineText '';
            
$lineWidth 0;
            foreach( 
$words as $word ){
                
$wordWidth self::getTextWidth($word$currentPage);
                
                if( 
$lineWidth+$wordWidth $x2-$x1 ){
                    
$lineText .= $word;
                    
$lineWidth += $wordWidth;
                }else{
                    
self::drawText$currentPage$lineText$x1$bottom$x2$position$encoding );
                    
$bottom -= $lineHeight;
                    
$lineText $word;
                    
$lineWidth $wordWidth;
                }
            }
            
            
self::drawText$currentPage$lineText$x1$bottom$x2$position$encoding );
            
$bottom -= $lineHeight;
        }
        
        return 
$pages;
    }
    
    
/**
     * Return length of generated string in points
     *
     * @param string                     $text
     * @param Zend_Pdf_Resource_Font|Zend_Pdf_Page     $font
     * @param int                         $fontSize
     * @return double
     */
    
public static function getTextWidth($text$resource$fontSize null$encoding null) {
        if( 
$encoding == null $encoding self::$encoding;
        
        if( 
$resource instanceof Zend_Pdf_Page ){
            
$font $resource->getFont();
            
$fontSize $resource->getFontSize();
        }elseif( 
$resource instanceof Zend_Pdf_Resource_Font ){
            
$font $resource;
            if( 
$fontSize === null ) throw new Exception('The fontsize is unknown');
        }
        
        if( !
$font instanceof Zend_Pdf_Resource_Font ){
            throw new 
Exception('Invalid resource passed');
        }
        
        
$drawingText iconv ''$encoding$text );
        
$characters = array ();
        for(
$i 0$i strlen $drawingText ); $i ++) {
            
$characters [] = ord $drawingText [$i] );
        }
        
$glyphs $font->glyphNumbersForCharacters $characters );
        
$widths $font->widthsForGlyphs $glyphs );
        
$textWidth = (array_sum $widths ) / $font->getUnitsPerEm ()) * $fontSize;
        return 
$textWidth;
    }
    
}
nice,
but where i can put this class ?
and how used it in Controller ?
@storeman: Nice class, but your center text align calculation is wrong.

Replace: $left = $x1 + $textWidth / 2;

With: $left = $x1 + ( ($x2 - $x1) - $textWidth ) /2;
Thank u veeeeeeeeeery much! it worked perfectly!

+ Add A Comment

Please do not report issues via comments; use the ZF Issue Tracker.

If you have a JIRA/Crowd account, we suggest you login first before commenting.

  • BBCode is allowed in the comment markup

  • Select a Version

    Languages Available

    Components

    Search the Manual