text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Jpeg.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Name.php';
require_once 'Zend/Pdf/Element/Numeric.php';

/** Zend_Pdf_Resource_Image */
require_once 'Zend/Pdf/Resource/Image.php';

/**
 * JPEG image
 *
 * @package    Zend_Pdf
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Image_Jpeg extends Zend_Pdf_Resource_Image
{

    protected $_width;
    protected $_height;
    protected $_imageProperties;

    /**
     * Object constructor
     *
     * @param string $imageFileName
     * @throws Zend_Pdf_Exception
     */
    public function __construct($imageFileName)
    {
        if (!function_exists('gd_info')) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception('Image extension is not installed.');
        }

        $gd_options = gd_info();
        if ( (!isset($gd_options['JPG Support'])  || $gd_options['JPG Support']  != true)  &&
             (!isset($gd_options['JPEG Support']) || $gd_options['JPEG Support'] != true)  ) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception('JPG support is not configured properly.');
        }

        if (($imageInfo = getimagesize($imageFileName)) === false) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception('Corrupted image or image doesn\'t exist.');
        }
        if ($imageInfo[2] != IMAGETYPE_JPEG && $imageInfo[2] != IMAGETYPE_JPEG2000) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception('ImageType is not JPG');
        }

        parent::__construct();

        switch ($imageInfo['channels']) {
            case 3:
                $colorSpace = 'DeviceRGB';
                break;
            case 4:
                $colorSpace = 'DeviceCMYK';
                break;
            default:
                $colorSpace = 'DeviceGray';
                break;
        }

        $imageDictionary = $this->_resource->dictionary;
        $imageDictionary->Width            = new Zend_Pdf_Element_Numeric($imageInfo[0]);
        $imageDictionary->Height           = new Zend_Pdf_Element_Numeric($imageInfo[1]);
        $imageDictionary->ColorSpace       = new Zend_Pdf_Element_Name($colorSpace);
        $imageDictionary->BitsPerComponent = new Zend_Pdf_Element_Numeric($imageInfo['bits']);
        if ($imageInfo[2] == IMAGETYPE_JPEG) {
            $imageDictionary->Filter       = new Zend_Pdf_Element_Name('DCTDecode');
        } else if ($imageInfo[2] == IMAGETYPE_JPEG2000){
            $imageDictionary->Filter       = new Zend_Pdf_Element_Name('JPXDecode');
        }

        if (($imageFile = @fopen($imageFileName, 'rb')) === false ) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception( "Can not open '$imageFileName' file for reading." );
        }
        $byteCount = filesize($imageFileName);
        $this->_resource->value = '';

        while ($byteCount > 0 && !feof($imageFile)) {
            $nextBlock = fread($imageFile, $byteCount);
            if ($nextBlock === false) {
                require_once 'Zend/Pdf/Exception.php';
                throw new Zend_Pdf_Exception( "Error occured while '$imageFileName' file reading." );
            }

            $this->_resource->value .= $nextBlock;
            $byteCount -= strlen($nextBlock);
        }
        if ($byteCount != 0) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception( "Error occured while '$imageFileName' file reading." );
        }
        fclose($imageFile);
        $this->_resource->skipFilters();

        $this->_width  = $imageInfo[0];
        $this->_height = $imageInfo[1];
        $this->_imageProperties = array();
        $this->_imageProperties['bitDepth'] = $imageInfo['bits'];
        $this->_imageProperties['jpegImageType'] = $imageInfo[2];
        $this->_imageProperties['jpegColorType'] = $imageInfo['channels'];
    }

    /**
     * Image width
     */
    public function getPixelWidth() {
        return $this->_width;
    }

    /**
     * Image height
     */
    public function getPixelHeight() {
        return $this->_height;
    }

    /**
     * Image properties
     */
    public function getProperties() {
        return $this->_imageProperties;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Tiff.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Array.php';
require_once 'Zend/Pdf/Element/Name.php';
require_once 'Zend/Pdf/Element/Numeric.php';

/** Zend_Pdf_Resource_Image */
require_once 'Zend/Pdf/Resource/Image.php';

/**
 * TIFF image
 *
 * @package    Zend_Pdf
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Image_Tiff extends Zend_Pdf_Resource_Image
{
    const TIFF_FIELD_TYPE_BYTE=1;
    const TIFF_FIELD_TYPE_ASCII=2;
    const TIFF_FIELD_TYPE_SHORT=3;
    const TIFF_FIELD_TYPE_LONG=4;
    const TIFF_FIELD_TYPE_RATIONAL=5;

    const TIFF_TAG_IMAGE_WIDTH=256;
    const TIFF_TAG_IMAGE_LENGTH=257; //Height
    const TIFF_TAG_BITS_PER_SAMPLE=258;
    const TIFF_TAG_COMPRESSION=259;
    const TIFF_TAG_PHOTOMETRIC_INTERPRETATION=262;
    const TIFF_TAG_STRIP_OFFSETS=273;
    const TIFF_TAG_SAMPLES_PER_PIXEL=277;
    const TIFF_TAG_STRIP_BYTE_COUNTS=279;

    const TIFF_COMPRESSION_UNCOMPRESSED = 1;
    const TIFF_COMPRESSION_CCITT1D = 2;
    const TIFF_COMPRESSION_GROUP_3_FAX = 3;
    const TIFF_COMPRESSION_GROUP_4_FAX  = 4;
    const TIFF_COMPRESSION_LZW = 5;
    const TIFF_COMPRESSION_JPEG = 6;
    const TIFF_COMPRESSION_FLATE = 8;
    const TIFF_COMPRESSION_FLATE_OBSOLETE_CODE = 32946;
    const TIFF_COMPRESSION_PACKBITS = 32773;

    const TIFF_PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO=0;
    const TIFF_PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO=1;
    const TIFF_PHOTOMETRIC_INTERPRETATION_RGB=2;
    const TIFF_PHOTOMETRIC_INTERPRETATION_RGB_INDEXED=3;
    const TIFF_PHOTOMETRIC_INTERPRETATION_CMYK=5;
    const TIFF_PHOTOMETRIC_INTERPRETATION_YCBCR=6;
    const TIFF_PHOTOMETRIC_INTERPRETATION_CIELAB=8;

    protected $_width;
    protected $_height;
    protected $_imageProperties;
    protected $_endianType;
    protected $_fileSize;
    protected $_bitsPerSample;
    protected $_compression;
    protected $_filter;
    protected $_colorCode;
    protected $_whiteIsZero;
    protected $_blackIsZero;
    protected $_colorSpace;
    protected $_imageDataOffset;
    protected $_imageDataLength;

    const TIFF_ENDIAN_BIG=0;
    const TIFF_ENDIAN_LITTLE=1;

    const UNPACK_TYPE_BYTE=0;
    const UNPACK_TYPE_SHORT=1;
    const UNPACK_TYPE_LONG=2;
    const UNPACK_TYPE_RATIONAL=3;

    /**
     * Byte unpacking function
     *
     * Makes it possible to unpack bytes in one statement for enhanced logic readability.
     *
     * @param int $type
     * @param string $bytes
     * @throws Zend_Pdf_Exception
     */
    protected function unpackBytes($type, $bytes) {
        if(!isset($this->_endianType)) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception("The unpackBytes function can only be used after the endianness of the file is known");
        }
        switch($type) {
            case Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_BYTE:
                $format = 'C';
                $unpacked = unpack($format, $bytes);
                return $unpacked[1];
                break;
            case Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT:
                $format = ($this->_endianType == Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE)?'v':'n';
                $unpacked = unpack($format, $bytes);
                return $unpacked[1];
                break;
            case Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG:
                $format = ($this->_endianType == Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE)?'V':'N';
                $unpacked = unpack($format, $bytes);
                return $unpacked[1];
                break;
            case Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_RATIONAL:
                $format = ($this->_endianType == Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE)?'V2':'N2';
                $unpacked = unpack($format, $bytes);
                return ($unpacked[1]/$unpacked[2]);
                break;
        }
    }

    /**
     * Object constructor
     *
     * @param string $imageFileName
     * @throws Zend_Pdf_Exception
     */
    public function __construct($imageFileName)
    {
        if (($imageFile = @fopen($imageFileName, 'rb')) === false ) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception( "Can not open '$imageFileName' file for reading." );
        }

        $byteOrderIndicator = fread($imageFile, 2);
        if($byteOrderIndicator == 'II') {
            $this->_endianType = Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE;
        } else if($byteOrderIndicator == 'MM') {
            $this->_endianType = Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_BIG;
        } else {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception( "Not a tiff file or Tiff corrupt. No byte order indication found" );
        }

        $version = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, fread($imageFile, 2));

        if($version != 42) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception( "Not a tiff file or Tiff corrupt. Incorrect version number." );
        }
        $ifdOffset = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG, fread($imageFile, 4));

        $fileStats = fstat($imageFile);
        $this->_fileSize = $fileStats['size'];

        /*
         * Tiff files are stored as a series of Image File Directories (IFD) each direcctory
         * has a specific number of entries each 12 bytes in length. At the end of the directories
         * is four bytes pointing to the offset of the next IFD.
         */

        while($ifdOffset > 0) {
            if(fseek($imageFile, $ifdOffset, SEEK_SET) == -1 || $ifdOffset+2 >= $this->_fileSize) {
                require_once 'Zend/Pdf/Exception.php';
                throw new Zend_Pdf_Exception("Could not seek to the image file directory as indexed by the file. Likely cause is TIFF corruption. Offset: ". $ifdOffset);
            }

            $numDirEntries = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, fread($imageFile, 2));

            /*
             * Since we now know how many entries are in this (IFD) we can extract the data.
             * The format of a TIFF directory entry is:
             *
             * 2 bytes (short) tag code; See TIFF_TAG constants at the top for supported values. (There are many more in the spec)
             * 2 bytes (short) field type
             * 4 bytes (long) number of values, or value count.
             * 4 bytes (mixed) data if the data will fit into 4 bytes or an offset if the data is too large.
             */
            for($dirEntryIdx = 1; $dirEntryIdx <= $numDirEntries; $dirEntryIdx++) {
                $tag         = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, fread($imageFile, 2));
                $fieldType   = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, fread($imageFile, 2));
                $valueCount  = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG, fread($imageFile, 4));

                switch($fieldType) {
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_BYTE:
                        $fieldLength = $valueCount;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_ASCII:
                        $fieldLength = $valueCount;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_SHORT:
                        $fieldLength = $valueCount * 2;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_LONG:
                        $fieldLength = $valueCount * 4;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_RATIONAL:
                        $fieldLength = $valueCount * 8;
                        break;
                    default:
                        $fieldLength = $valueCount;
                }

                $offsetBytes = fread($imageFile, 4);

                if($fieldLength <= 4) {
                    switch($fieldType) {
                        case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_BYTE:
                            $value = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_BYTE, $offsetBytes);
                            break;
                        case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_ASCII:
                            //Fall through to next case
                        case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_LONG:
                            $value = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG, $offsetBytes);
                            break;
                        case Zend_Pdf_Resource_Image_Tiff::TIFF_FIELD_TYPE_SHORT:
                            //Fall through to next case
                        default:
                            $value = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, $offsetBytes);
                    }
                } else {
                    $refOffset = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG, $offsetBytes);
                }
                /*
                 * Linear tag processing is probably not the best way to do this. I've processed the tags according to the
                 * Tiff 6 specification and make some assumptions about when tags will be < 4 bytes and fit into $value and when
                 * they will be > 4 bytes and require seek/extraction of the offset. Same goes for extracting arrays of data, like
                 * the data offsets and length. This should be fixed in the future.
                 */
                switch($tag) {
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_IMAGE_WIDTH:
                        $this->_width = $value;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_IMAGE_LENGTH:
                        $this->_height = $value;
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_BITS_PER_SAMPLE:
                        if($valueCount>1) {
                            $fp = ftell($imageFile);
                            fseek($imageFile, $refOffset, SEEK_SET);
                            $this->_bitsPerSample = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_SHORT, fread($imageFile, 2));
                            fseek($imageFile, $fp, SEEK_SET);
                        } else {
                            $this->_bitsPerSample = $value;
                        }
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_COMPRESSION:
                        $this->_compression = $value;
                        switch($value) {
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_UNCOMPRESSED:
                                $this->_filter = 'None';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_CCITT1D:
                                //Fall through to next case
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_GROUP_3_FAX:
                                //Fall through to next case
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_GROUP_4_FAX:
                                $this->_filter = 'CCITTFaxDecode';
                                require_once 'Zend/Pdf/Exception.php';
                                throw new Zend_Pdf_Exception("CCITTFaxDecode Compression Mode Not Currently Supported");
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_LZW:
                                $this->_filter = 'LZWDecode';
                                require_once 'Zend/Pdf/Exception.php';
                                throw new Zend_Pdf_Exception("LZWDecode Compression Mode Not Currently Supported");
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_JPEG:
                                $this->_filter = 'DCTDecode'; //Should work, doesnt...
                                require_once 'Zend/Pdf/Exception.php';
                                throw new Zend_Pdf_Exception("JPEG Compression Mode Not Currently Supported");
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_FLATE:
                                //fall through to next case
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_FLATE_OBSOLETE_CODE:
                                $this->_filter = 'FlateDecode';
                                require_once 'Zend/Pdf/Exception.php';
                                throw new Zend_Pdf_Exception("ZIP/Flate Compression Mode Not Currently Supported");
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_COMPRESSION_PACKBITS:
                                $this->_filter = 'RunLengthDecode';
                                break;
                        }
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_PHOTOMETRIC_INTERPRETATION:
                        $this->_colorCode = $value;
                        $this->_whiteIsZero = false;
                        $this->_blackIsZero = false;
                        switch($value) {
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO:
                                $this->_whiteIsZero = true;
                                $this->_colorSpace = 'DeviceGray';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO:
                                $this->_blackIsZero = true;
                                $this->_colorSpace = 'DeviceGray';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_YCBCR:
                                //fall through to next case
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_RGB:
                                $this->_colorSpace = 'DeviceRGB';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_RGB_INDEXED:
                                $this->_colorSpace = 'Indexed';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_CMYK:
                                $this->_colorSpace = 'DeviceCMYK';
                                break;
                            case Zend_Pdf_Resource_Image_Tiff::TIFF_PHOTOMETRIC_INTERPRETATION_CIELAB:
                                $this->_colorSpace = 'Lab';
                                break;
                            default:
                                require_once 'Zend/Pdf/Exception.php';
                                throw new Zend_Pdf_Exception('TIFF: Unknown or Unsupported Color Type: '. $value);
                        }
                        break;
                    case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_STRIP_OFFSETS:
                        if($valueCount>1) {
                            $format = ($this->_endianType == Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE)?'V*':'N*';
                            $fp = ftell($imageFile);
                            fseek($imageFile, $refOffset, SEEK_SET);
                            $stripOffsetsBytes = fread($imageFile, $fieldLength);
                            $this->_imageDataOffset = unpack($format, $stripOffsetsBytes);
                            fseek($imageFile, $fp, SEEK_SET);
                        } else {
                            $this->_imageDataOffset = $value;
                        }
                        break;
                   case Zend_Pdf_Resource_Image_Tiff::TIFF_TAG_STRIP_BYTE_COUNTS:
                        if($valueCount>1) {
                            $format = ($this->_endianType == Zend_Pdf_Resource_Image_Tiff::TIFF_ENDIAN_LITTLE)?'V*':'N*';
                            $fp = ftell($imageFile);
                            fseek($imageFile, $refOffset, SEEK_SET);
                            $stripByteCountsBytes = fread($imageFile, $fieldLength);
                            $this->_imageDataLength = unpack($format, $stripByteCountsBytes);
                            fseek($imageFile, $fp, SEEK_SET);
                        } else {
                            $this->_imageDataLength = $value;
                        }
                        break;
                    default:
                        //For debugging. It should be harmless to ignore unknown tags, though there is some good info in them.
                        //echo "Unknown tag detected: ". $tag . " value: ". $value;
                }
            }
            $ifdOffset = $this->unpackBytes(Zend_Pdf_Resource_Image_Tiff::UNPACK_TYPE_LONG, fread($imageFile, 4));
        }

        if(!isset($this->_imageDataOffset) || !isset($this->_imageDataLength)) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception("TIFF: The image processed did not contain image data as expected.");
        }

        $imageDataBytes = '';
        if(is_array($this->_imageDataOffset)) {
            if(!is_array($this->_imageDataLength)) {
                require_once 'Zend/Pdf/Exception.php';
                throw new Zend_Pdf_Exception("TIFF: The image contained multiple data offsets but not multiple data lengths. Tiff may be corrupt.");
            }
            foreach($this->_imageDataOffset as $idx => $offset) {
                fseek($imageFile, $this->_imageDataOffset[$idx], SEEK_SET);
                $imageDataBytes .= fread($imageFile, $this->_imageDataLength[$idx]);
            }
        } else {
            fseek($imageFile, $this->_imageDataOffset, SEEK_SET);
            $imageDataBytes = fread($imageFile, $this->_imageDataLength);
        }
        if($imageDataBytes === '') {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception("TIFF: No data. Image Corruption");
        }

        fclose($imageFile);

        parent::__construct();

        $imageDictionary = $this->_resource->dictionary;
        if(!isset($this->_width) || !isset($this->_width)) {
            require_once 'Zend/Pdf/Exception.php';
            throw new Zend_Pdf_Exception("Problem reading tiff file. Tiff is probably corrupt.");
        }

        $this->_imageProperties = array();
        $this->_imageProperties['bitDepth'] = $this->_bitsPerSample;
        $this->_imageProperties['fileSize'] = $this->_fileSize;
        $this->_imageProperties['TIFFendianType'] = $this->_endianType;
        $this->_imageProperties['TIFFcompressionType'] = $this->_compression;
        $this->_imageProperties['TIFFwhiteIsZero'] = $this->_whiteIsZero;
        $this->_imageProperties['TIFFblackIsZero'] = $this->_blackIsZero;
        $this->_imageProperties['TIFFcolorCode'] = $this->_colorCode;
        $this->_imageProperties['TIFFimageDataOffset'] = $this->_imageDataOffset;
        $this->_imageProperties['TIFFimageDataLength'] = $this->_imageDataLength;
        $this->_imageProperties['PDFfilter'] = $this->_filter;
        $this->_imageProperties['PDFcolorSpace'] = $this->_colorSpace;

        $imageDictionary->Width            = new Zend_Pdf_Element_Numeric($this->_width);
        if($this->_whiteIsZero === true) {
            $imageDictionary->Decode       = new Zend_Pdf_Element_Array(array(new Zend_Pdf_Element_Numeric(1), new Zend_Pdf_Element_Numeric(0)));
        }
        $imageDictionary->Height           = new Zend_Pdf_Element_Numeric($this->_height);
        $imageDictionary->ColorSpace       = new Zend_Pdf_Element_Name($this->_colorSpace);
        $imageDictionary->BitsPerComponent = new Zend_Pdf_Element_Numeric($this->_bitsPerSample);
        if(isset($this->_filter) && $this->_filter != 'None') {
            $imageDictionary->Filter = new Zend_Pdf_Element_Name($this->_filter);
        }

        $this->_resource->value = $imageDataBytes;
        $this->_resource->skipFilters();
    }
    /**
     * Image width (defined in Zend_Pdf_Resource_Image_Interface)
     */
    public function getPixelWidth() {
        return $this->_width;
    }

    /**
     * Image height (defined in Zend_Pdf_Resource_Image_Interface)
     */
    public function getPixelHeight() {
        return $this->_height;
    }

    /**
     * Image properties (defined in Zend_Pdf_Resource_Image_Interface)
     */
    public function getProperties() {
        return $this->_imageProperties;
    }
}

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Type0.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Array.php';
require_once 'Zend/Pdf/Element/Name.php';

/** Zend_Pdf_Resource_Font */
require_once 'Zend/Pdf/Resource/Font.php';

/**
 * Adobe PDF composite fonts implementation
 *
 * A composite font is one whose glyphs are obtained from other fonts or from fontlike
 * objects called CIDFonts ({@link Zend_Pdf_Resource_Font_CidFont}), organized hierarchically.
 * In PDF, a composite font is represented by a font dictionary whose Subtype value is Type0;
 * this is also called a Type 0 font (the Type 0 font at the top level of the hierarchy is the
 * root font).
 *
 * In PDF, a Type 0 font is a CID-keyed font.
 *
 * CID-keyed fonts provide effective method to operate with multi-byte character encodings.
 *
 * The CID-keyed font architecture specifies the external representation of certain font programs,
 * called CMap and CIDFont files, along with some conventions for combining and using those files.
 *
 * A CID-keyed font is the combination of a CMap with one or more CIDFonts, simple fonts,
 * or composite fonts containing glyph descriptions.
 *
 * The term 'CID-keyed font' reflects the fact that CID (character identifier) numbers
 * are used to index and access the glyph descriptions in the font.
 *
 *
 * Font objects should be normally be obtained from the factory methods
 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Font_Type0 extends Zend_Pdf_Resource_Font
{
    /**
     * Descendant CIDFont
     *
     * @var Zend_Pdf_Resource_Font_CidFont
     */
    private $_descendantFont;

    /**
     * Generate ToUnicode character map data
     *
     * @return string
     */
    static private function getToUnicodeCMapData()
    {
        return '/CIDInit /ProcSet findresource begin '              . "\n"
             . '12 dict begin '                                     . "\n"
             . 'begincmap '                                         . "\n"
             . '/CIDSystemInfo '                                    . "\n"
             . '<</Registry (Adobe) '                               . "\n"
             . '/Ordering (UCS) '                                   . "\n"
             . '/Supplement 0'                                      . "\n"
             . '>> def'                                             . "\n"
             . '/CMapName /Adobe-Identity-UCS def '                 . "\n"
             . '/CMapType 2 def '                                   . "\n"
             . '1 begincodespacerange'                              . "\n"
             . '<0000> <FFFF> '                                     . "\n"
             . 'endcodespacerange '                                 . "\n"
             . '1 beginbfrange '                                    . "\n"
             . '<0000> <FFFF> <0000> '                              . "\n"
             . 'endbfrange '                                        . "\n"
             . 'endcmap '                                           . "\n"
             . 'CMapName currentdict /CMap defineresource pop '     . "\n"
             . 'end '
             . 'end ';
            }

    /**
     * Object constructor
     *
     */
    public function __construct(Zend_Pdf_Resource_Font_CidFont $descendantFont)
    {
        parent::__construct();

        $this->_objectFactory->attach($descendantFont->getFactory());

        $this->_fontType       = Zend_Pdf_Font::TYPE_TYPE_0;
        $this->_descendantFont = $descendantFont;

        $this->_fontNames    = $descendantFont->getFontNames();

        $this->_isBold       = $descendantFont->isBold();
        $this->_isItalic     = $descendantFont->isItalic();
        $this->_isMonospaced = $descendantFont->isMonospace();

        $this->_underlinePosition  = $descendantFont->getUnderlinePosition();
        $this->_underlineThickness = $descendantFont->getUnderlineThickness();
        $this->_strikePosition     = $descendantFont->getStrikePosition();
        $this->_strikeThickness    = $descendantFont->getStrikeThickness();

        $this->_unitsPerEm = $descendantFont->getUnitsPerEm();

        $this->_ascent  = $descendantFont->getAscent();
        $this->_descent = $descendantFont->getDescent();
        $this->_lineGap = $descendantFont->getLineGap();

        $this->_resource->Subtype         = new Zend_Pdf_Element_Name('Type0');
        $this->_resource->BaseFont        = new Zend_Pdf_Element_Name($descendantFont->getResource()->BaseFont->value);
        $this->_resource->DescendantFonts = new Zend_Pdf_Element_Array(array( $descendantFont->getResource() ));
        $this->_resource->Encoding        = new Zend_Pdf_Element_Name('Identity-H');

        $toUnicode = $this->_objectFactory->newStreamObject(self::getToUnicodeCMapData());
        $this->_resource->ToUnicode = $toUnicode;

    }

    /**
     * Returns an array of glyph numbers corresponding to the Unicode characters.
     *
     * Zend_Pdf uses 'Identity-H' encoding for Type 0 fonts.
     * So we don't need to perform any conversion
     *
     * See also {@link glyphNumberForCharacter()}.
     *
     * @param array $characterCodes Array of Unicode character codes (code points).
     * @return array Array of glyph numbers.
     */
    public function glyphNumbersForCharacters($characterCodes)
    {
        return $characterCodes;
    }

    /**
     * Returns the glyph number corresponding to the Unicode character.
     *
     * Zend_Pdf uses 'Identity-H' encoding for Type 0 fonts.
     * So we don't need to perform any conversion
     *
     * @param integer $characterCode Unicode character code (code point).
     * @return integer Glyph number.
     */
    public function glyphNumberForCharacter($characterCode)
    {
        return $characterCode;
    }

    /**
     * Returns a number between 0 and 1 inclusive that indicates the percentage
     * of characters in the string which are covered by glyphs in this font.
     *
     * Since no one font will contain glyphs for the entire Unicode character
     * range, this method can be used to help locate a suitable font when the
     * actual contents of the string are not known.
     *
     * Note that some fonts lie about the characters they support. Additionally,
     * fonts don't usually contain glyphs for control characters such as tabs
     * and line breaks, so it is rare that you will get back a full 1.0 score.
     * The resulting value should be considered informational only.
     *
     * @param string $string
     * @param string $charEncoding (optional) Character encoding of source text.
     *   If omitted, uses 'current locale'.
     * @return float
     */
    public function getCoveredPercentage($string, $charEncoding = '')
    {
        return $this->_descendantFont->getCoveredPercentage($string, $charEncoding);
    }

    /**
     * Returns the widths of the glyphs.
     *
     * The widths are expressed in the font's glyph space. You are responsible
     * for converting to user space as necessary. See {@link unitsPerEm()}.
     *
     * Throws an exception if the glyph number is out of range.
     *
     * See also {@link widthForGlyph()}.
     *
     * @param array &$glyphNumbers Array of glyph numbers.
     * @return array Array of glyph widths (integers).
     * @throws Zend_Pdf_Exception
     */
    public function widthsForGlyphs($glyphNumbers)
    {
        return $this->_descendantFont->widthsForChars($glyphNumbers);
    }

    /**
     * Returns the width of the glyph.
     *
     * Like {@link widthsForGlyphs()} but used for one glyph at a time.
     *
     * @param integer $glyphNumber
     * @return integer
     * @throws Zend_Pdf_Exception
     */
    public function widthForGlyph($glyphNumber)
    {
        return $this->_descendantFont->widthForChar($glyphNumber);
    }

    /**
     * Convert string to the font encoding.
     *
     * The method is used to prepare string for text drawing operators
     *
     * @param string $string
     * @param string $charEncoding Character encoding of source text.
     * @return string
     */
    public function encodeString($string, $charEncoding)
    {
        return iconv($charEncoding, 'UTF-16BE', $string);
    }

    /**
     * Convert string from the font encoding.
     *
     * The method is used to convert strings retrieved from existing content streams
     *
     * @param string $string
     * @param string $charEncoding Character encoding of resulting text.
     * @return string
     */
        public function decodeString($string, $charEncoding)
    {
        return iconv('UTF-16BE', $charEncoding, $string);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: CidFont.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Array.php';
require_once 'Zend/Pdf/Element/Dictionary.php';
require_once 'Zend/Pdf/Element/Name.php';
require_once 'Zend/Pdf/Element/Numeric.php';
require_once 'Zend/Pdf/Element/String.php';

/** Zend_Pdf_Resource_Font */
require_once 'Zend/Pdf/Resource/Font.php';

/**
 * Adobe PDF CIDFont font object implementation
 *
 * A CIDFont program contains glyph descriptions that are accessed using a CID as
 * the character selector. There are two types of CIDFont. A Type 0 CIDFont contains
 * glyph descriptions based on Adobe’s Type 1 font format, whereas those in a
 * Type 2 CIDFont are based on the TrueType font format.
 *
 * A CIDFont dictionary is a PDF object that contains information about a CIDFont program.
 * Although its Type value is Font, a CIDFont is not actually a font. It does not have an Encoding
 * entry, it cannot be listed in the Font subdictionary of a resource dictionary, and it cannot be
 * used as the operand of the Tf operator. It is used only as a descendant of a Type 0 font.
 * The CMap in the Type 0 font is what defines the encoding that maps character codes to CIDs
 * in the CIDFont.
 *
 * Font objects should be normally be obtained from the factory methods
 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Pdf_Resource_Font_CidFont extends Zend_Pdf_Resource_Font
{
    /**
     * Object representing the font's cmap (character to glyph map).
     * @var Zend_Pdf_Cmap
     */
    protected $_cmap = null;

    /**
     * Array containing the widths of each character that have entries in used character map.
     *
     * @var array
     */
    protected $_charWidths = null;

    /**
     * Width for characters missed in the font
     *
     * @var integer
     */
    protected $_missingCharWidth = 0;

    /**
     * Object constructor
     *
     * @param Zend_Pdf_FileParser_Font_OpenType $fontParser Font parser object
     *   containing OpenType file.
     * @param integer $embeddingOptions Options for font embedding.
     * @throws Zend_Pdf_Exception
     */
    public function __construct(Zend_Pdf_FileParser_Font_OpenType $fontParser)
    {
        parent::__construct();

        $fontParser->parse();

        /* Object properties */

        $this->_fontNames = $fontParser->names;

        $this->_isBold       = $fontParser->isBold;
        $this->_isItalic     = $fontParser->isItalic;
        $this->_isMonospaced = $fontParser->isMonospaced;

        $this->_underlinePosition  = $fontParser->underlinePosition;
        $this->_underlineThickness = $fontParser->underlineThickness;
        $this->_strikePosition     = $fontParser->strikePosition;
        $this->_strikeThickness    = $fontParser->strikeThickness;

        $this->_unitsPerEm = $fontParser->unitsPerEm;

        $this->_ascent  = $fontParser->ascent;
        $this->_descent = $fontParser->descent;
        $this->_lineGap = $fontParser->lineGap;

        $this->_cmap = $fontParser->cmap;

        /* Resource dictionary */

        $baseFont = $this->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT, 'en', 'UTF-8');
        $this->_resource->BaseFont = new Zend_Pdf_Element_Name($baseFont);

        /**
         * Prepare widths array.
         */
        /* Constract characters widths array using font CMap and glyphs widths array */
        $glyphWidths = $fontParser->glyphWidths;
        $charGlyphs  = $this->_cmap->getCoveredCharactersGlyphs();
        $charWidths  = array();
        foreach ($charGlyphs as $charCode => $glyph) {
            $charWidths[$charCode] = $glyphWidths[$glyph];
        }
        $this->_charWidths       = $charWidths;
        $this->_missingCharWidth = $glyphWidths[0];

        /* Width array optimization. Step1: extract default value */
        $widthFrequencies = array_count_values($charWidths);
        $defaultWidth          = null;
        $defaultWidthFrequency = -1;
        foreach ($widthFrequencies as $width => $frequency) {
            if ($frequency > $defaultWidthFrequency) {
                $defaultWidth          = $width;
                $defaultWidthFrequency = $frequency;
            }
        }

        // Store default value in the font dictionary
        $this->_resource->DW = new Zend_Pdf_Element_Numeric($this->toEmSpace($defaultWidth));

        // Remove characters which corresponds to default width from the widths array
        $defWidthChars = array_keys($charWidths, $defaultWidth);
        foreach ($defWidthChars as $charCode) {
            unset($charWidths[$charCode]);
        }

        // Order cheracter widths aray by character codes
        ksort($charWidths, SORT_NUMERIC);

        /* Width array optimization. Step2: Compact character codes sequences */
        $lastCharCode = -1;
        $widthsSequences = array();
        foreach ($charWidths as $charCode => $width) {
            if ($lastCharCode == -1) {
                $charCodesSequense = array();
                $sequenceStartCode = $charCode;
            } else if ($charCode != $lastCharCode + 1) {
                // New chracters sequence detected
                $widthsSequences[$sequenceStartCode] = $charCodesSequense;
                $charCodesSequense = array();
                $sequenceStartCode = $charCode;
            }
            $charCodesSequense[] = $width;
            $lastCharCode = $charCode;
        }
        // Save last sequence, if widths array is not empty (it may happens for monospaced fonts)
        if (count($charWidths) != 0) {
            $widthsSequences[$sequenceStartCode] = $charCodesSequense;
        }

        $pdfCharsWidths = array();
        foreach ($widthsSequences as $startCode => $widthsSequence) {
            /* Width array optimization. Step3: Compact widths sequences */
            $pdfWidths        = array();
            $lastWidth        = -1;
            $widthsInSequence = 0;
            foreach ($widthsSequence as $width) {
                if ($lastWidth != $width) {
                    // New width is detected
                    if ($widthsInSequence != 0) {
                        // Previous width value was a part of the widths sequence. Save it as 'c_1st c_last w'.
                        $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode);                         // First character code
                        $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode + $widthsInSequence - 1); // Last character code
                        $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($this->toEmSpace($lastWidth));       // Width

                        // Reset widths sequence
                        $startCode = $startCode + $widthsInSequence;
                        $widthsInSequence = 0;
                    }

                    // Collect new width
                    $pdfWidths[] = new Zend_Pdf_Element_Numeric($this->toEmSpace($width));

                    $lastWidth = $width;
                } else {
                    // Width is equal to previous
                    if (count($pdfWidths) != 0) {
                        // We already have some widths collected
                        // So, we've just detected new widths sequence

                        // Remove last element from widths list, since it's a part of widths sequence
                        array_pop($pdfWidths);

                        // and write the rest if it's not empty
                        if (count($pdfWidths) != 0) {
                            // Save it as 'c_1st [w1 w2 ... wn]'.
                            $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode); // First character code
                            $pdfCharsWidths[] = new Zend_Pdf_Element_Array($pdfWidths);   // Widths array

                            // Reset widths collection
                            $startCode += count($pdfWidths);
                            $pdfWidths = array();
                        }

                        $widthsInSequence = 2;
                    } else {
                        // Continue widths sequence
                        $widthsInSequence++;
                    }
                }
            }

            // Check if we have widths collection or widths sequence to wite it down
            if (count($pdfWidths) != 0) {
                // We have some widths collected
                // Save it as 'c_1st [w1 w2 ... wn]'.
                $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode); // First character code
                $pdfCharsWidths[] = new Zend_Pdf_Element_Array($pdfWidths);   // Widths array
            } else if ($widthsInSequence != 0){
                // We have widths sequence
                // Save it as 'c_1st c_last w'.
                $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode);                         // First character code
                $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($startCode + $widthsInSequence - 1); // Last character code
                $pdfCharsWidths[] = new Zend_Pdf_Element_Numeric($this->toEmSpace($lastWidth));       // Width
            }
        }

        /* Create the Zend_Pdf_Element_Array object and add it to the font's
         * object factory and resource dictionary.
         */
        $widthsArrayElement = new Zend_Pdf_Element_Array($pdfCharsWidths);
        $widthsObject = $this->_objectFactory->newObject($widthsArrayElement);
        $this->_resource->W = $widthsObject;

        /* CIDSystemInfo dictionary */
        $cidSystemInfo = new Zend_Pdf_Element_Dictionary();
        $cidSystemInfo->Registry   = new Zend_Pdf_Element_String('Adobe');
        $cidSystemInfo->Ordering   = new Zend_Pdf_Element_String('UCS');
        $cidSystemInfo->Supplement = new Zend_Pdf_Element_Numeric(0);
        $cidSystemInfoObject            = $this->_objectFactory->newObject($cidSystemInfo);
        $this->_resource->CIDSystemInfo = $cidSystemInfoObject;
    }

    /**
     * Returns an array of glyph numbers corresponding to the Unicode characters.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumberForCharacter()}.
     *
     * @param array $characterCodes Array of Unicode character codes (code points).
     * @return array Array of glyph numbers.
     */
    public function glyphNumbersForCharacters($characterCodes)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }

    /**
     * Returns the glyph number corresponding to the Unicode character.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
     * operations.
     *
     * @param integer $characterCode Unicode character code (code point).
     * @return integer Glyph number.
     */
    public function glyphNumberForCharacter($characterCode)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }

    /**
     * Returns a number between 0 and 1 inclusive that indicates the percentage
     * of characters in the string which are covered by glyphs in this font.
     *
     * Since no one font will contain glyphs for the entire Unicode character
     * range, this method can be used to help locate a suitable font when the
     * actual contents of the string are not known.
     *
     * Note that some fonts lie about the characters they support. Additionally,
     * fonts don't usually contain glyphs for control characters such as tabs
     * and line breaks, so it is rare that you will get back a full 1.0 score.
     * The resulting value should be considered informational only.
     *
     * @param string $string
     * @param string $charEncoding (optional) Character encoding of source text.
     *   If omitted, uses 'current locale'.
     * @return float
     */
    public function getCoveredPercentage($string, $charEncoding = '')
    {
        /* Convert the string to UTF-16BE encoding so we can match the string's
         * character codes to those found in the cmap.
         */
        if ($charEncoding != 'UTF-16BE') {
            $string = iconv($charEncoding, 'UTF-16BE', $string);
        }

        $charCount = iconv_strlen($string, 'UTF-16BE');
        if ($charCount == 0) {
            return 0;
        }

        /* Calculate the score by doing a lookup for each character.
         */
        $score = 0;
        $maxIndex = strlen($string);
        for ($i = 0; $i < $maxIndex; $i++) {
            /**
             * @todo Properly handle characters encoded as surrogate pairs.
             */
            $charCode = (ord($string[$i]) << 8) | ord($string[++$i]);
            /* This could probably be optimized a bit with a binary search...
             */
            if (isset($this->_charWidths[$charCode])) {
                $score++;
            }
        }
        return $score / $charCount;
    }

    /**
     * Returns the widths of the Chars.
     *
     * The widths are expressed in the font's glyph space. You are responsible
     * for converting to user space as necessary. See {@link unitsPerEm()}.
     *
     * See also {@link widthForChar()}.
     *
     * @param array &$glyphNumbers Array of glyph numbers.
     * @return array Array of glyph widths (integers).
     */
    public function widthsForChars($charCodes)
    {
        $widths = array();
        foreach ($charCodes as $key => $charCode) {
            if (!isset($this->_charWidths[$charCode])) {
                $widths[$key] = $this->_missingCharWidth;
            } else {
                $widths[$key] = $this->_charWidths[$charCode];
            }
        }
        return $widths;
    }

    /**
     * Returns the width of the character.
     *
     * Like {@link widthsForChars()} but used for one char at a time.
     *
     * @param integer $charCode
     * @return integer
     */
    public function widthForChar($charCode)
    {
        if (!isset($this->_charWidths[$charCode])) {
            return $this->_missingCharWidth;
        }
        return $this->_charWidths[$charCode];
    }

    /**
     * Returns the widths of the glyphs.
     *
     * @param array &$glyphNumbers Array of glyph numbers.
     * @return array Array of glyph widths (integers).
     * @throws Zend_Pdf_Exception
     */
    public function widthsForGlyphs($glyphNumbers)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }

    /**
     * Returns the width of the glyph.
     *
     * Like {@link widthsForGlyphs()} but used for one glyph at a time.
     *
     * @param integer $glyphNumber
     * @return integer
     * @throws Zend_Pdf_Exception
     */
    public function widthForGlyph($glyphNumber)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }

    /**
     * Convert string to the font encoding.
     *
     * @param string $string
     * @param string $charEncoding Character encoding of source text.
     * @return string
     * @throws Zend_Pdf_Exception
     *      */
    public function encodeString($string, $charEncoding)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }

    /**
     * Convert string from the font encoding.
     *
     * @param string $string
     * @param string $charEncoding Character encoding of resulting text.
     * @return string
     * @throws Zend_Pdf_Exception
     */
    public function decodeString($string, $charEncoding)
    {
        /**
         * CIDFont object is not actually a font. It does not have an Encoding entry,
         * it cannot be listed in the Font subdictionary of a resource dictionary, and
         * it cannot be used as the operand of the Tf operator.
         *
         * Throw an exception.
         */
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('CIDFont PDF objects could not be used as the operand of the text drawing operators');
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Extracted.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** @see Zend_Pdf_Resource_Font */
require_once 'Zend/Pdf/Resource/Font.php';

/**
 * Extracted fonts implementation
 *
 * Thes class allows to extract fonts already mentioned within PDF document and use them
 * for text drawing.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Font_Extracted extends Zend_Pdf_Resource_Font
{
    /**
     * Messages
     */
    const TYPE_NOT_SUPPORTED = 'Unsupported font type.';
    const ENCODING_NOT_SUPPORTED  = 'Font encoding is not supported';
    const OPERATION_NOT_SUPPORTED = 'Operation is not supported for extracted fonts';

    /**
     * Extracted font encoding
     *
     * Only 'Identity-H' and 'WinAnsiEncoding' encodings are supported now
     *
     * @var string
     */
    protected $_encoding = null;

    /**
     * Object constructor
     *
     * $fontDictionary is a Zend_Pdf_Element_Reference or Zend_Pdf_Element_Object object
     *
     * @param mixed $fontDictionary
     * @throws Zend_Pdf_Exception
     */
    public function __construct($fontDictionary)
    {
        // Extract object factory and resource object from font dirctionary object
        $this->_objectFactory = $fontDictionary->getFactory();
        $this->_resource      = $fontDictionary;

        if ($fontDictionary->Encoding !== null) {
            $this->_encoding = $fontDictionary->Encoding->value;
        }

        switch ($fontDictionary->Subtype->value) {
            case 'Type0':
                // Composite type 0 font
                if (count($fontDictionary->DescendantFonts->items) != 1) {
                    // Multiple descendant fonts are not supported
                    require_once 'Zend/Pdf/Exception.php';
                    throw new Zend_Pdf_Exception(self::TYPE_NOT_SUPPORTED);
                }

                $fontDictionaryIterator = $fontDictionary->DescendantFonts->items->getIterator();
                $fontDictionaryIterator->rewind();
                $descendantFont = $fontDictionaryIterator->current();
                $fontDescriptor = $descendantFont->FontDescriptor;
                break;

            case 'Type1':
                if ($fontDictionary->FontDescriptor === null) {
                    // That's one of the standard fonts
                    $standardFont = Zend_Pdf_Font::fontWithName($fontDictionary->BaseFont->value);

                    $this->_fontNames          = $standardFont->getFontNames();
                    $this->_isBold             = $standardFont->isBold();
                    $this->_isItalic           = $standardFont->isItalic();
                    $this->_isMonospace        = $standardFont->isMonospace();
                    $this->_underlinePosition  = $standardFont->getUnderlinePosition();
                    $this->_underlineThickness = $standardFont->getUnderlineThickness();
                    $this->_strikePosition     = $standardFont->getStrikePosition();
                    $this->_strikeThickness    = $standardFont->getStrikeThickness();
                    $this->_unitsPerEm         = $standardFont->getUnitsPerEm();
                    $this->_ascent             = $standardFont->getAscent();
                    $this->_descent            = $standardFont->getDescent();
                    $this->_lineGap            = $standardFont->getLineGap();

                    return;
                }

                $fontDescriptor = $fontDictionary->FontDescriptor;
                break;

            case 'TrueType':
                $fontDescriptor = $fontDictionary->FontDescriptor;
                break;

            default:
                require_once 'Zend/Pdf/Exception.php';
                throw new Zend_Pdf_Exception(self::TYPE_NOT_SUPPORTED);
        }

        $this->_fontNames[Zend_Pdf_Font::NAME_POSTSCRIPT]['en'] = iconv('UTF-8', 'UTF-16BE', $fontDictionary->BaseFont->value);

        $this->_isBold             = false; // this property is actually not used anywhere
        $this->_isItalic           = ( ($fontDescriptor->Flags->value & (1 << 6)) != 0 ); // Bit-7 is set
        $this->_isMonospace        = ( ($fontDescriptor->Flags->value & (1 << 0)) != 0 ); // Bit-1 is set
        $this->_underlinePosition  = null; // Can't be extracted
        $this->_underlineThickness = null; // Can't be extracted
        $this->_strikePosition     = null; // Can't be extracted
        $this->_strikeThickness    = null; // Can't be extracted
        $this->_unitsPerEm         = null; // Can't be extracted
        $this->_ascent             = $fontDescriptor->Ascent->value;
        $this->_descent            = $fontDescriptor->Descent->value;
        $this->_lineGap            = null; // Can't be extracted
    }

    /**
     * Returns an array of glyph numbers corresponding to the Unicode characters.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumberForCharacter()}.
     *
     * @param array $characterCodes Array of Unicode character codes (code points).
     * @return array Array of glyph numbers.
     */
    public function glyphNumbersForCharacters($characterCodes)
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::OPERATION_NOT_SUPPORTED);
    }

    /**
     * Returns the glyph number corresponding to the Unicode character.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
     * operations.
     *
     * @param integer $characterCode Unicode character code (code point).
     * @return integer Glyph number.
     */
    public function glyphNumberForCharacter($characterCode)
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::OPERATION_NOT_SUPPORTED);
    }

    /**
     * Returns a number between 0 and 1 inclusive that indicates the percentage
     * of characters in the string which are covered by glyphs in this font.
     *
     * Since no one font will contain glyphs for the entire Unicode character
     * range, this method can be used to help locate a suitable font when the
     * actual contents of the string are not known.
     *
     * Note that some fonts lie about the characters they support. Additionally,
     * fonts don't usually contain glyphs for control characters such as tabs
     * and line breaks, so it is rare that you will get back a full 1.0 score.
     * The resulting value should be considered informational only.
     *
     * @param string $string
     * @param string $charEncoding (optional) Character encoding of source text.
     *   If omitted, uses 'current locale'.
     * @return float
     */
    public function getCoveredPercentage($string, $charEncoding = '')
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::OPERATION_NOT_SUPPORTED);
    }

    /**
     * Returns the widths of the glyphs.
     *
     * The widths are expressed in the font's glyph space. You are responsible
     * for converting to user space as necessary. See {@link unitsPerEm()}.
     *
     * See also {@link widthForGlyph()}.
     *
     * @param array $glyphNumbers Array of glyph numbers.
     * @return array Array of glyph widths (integers).
     * @throws Zend_Pdf_Exception
     */
    public function widthsForGlyphs($glyphNumbers)
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::OPERATION_NOT_SUPPORTED);
    }

    /**
     * Returns the width of the glyph.
     *
     * Like {@link widthsForGlyphs()} but used for one glyph at a time.
     *
     * @param integer $glyphNumber
     * @return integer
     * @throws Zend_Pdf_Exception
     */
    public function widthForGlyph($glyphNumber)
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::OPERATION_NOT_SUPPORTED);
    }

    /**
     * Convert string to the font encoding.
     *
     * The method is used to prepare string for text drawing operators
     *
     * @param string $string
     * @param string $charEncoding Character encoding of source text.
     * @return string
     */
    public function encodeString($string, $charEncoding)
    {
        if ($this->_encoding == 'Identity-H') {
            return iconv($charEncoding, 'UTF-16BE', $string);
        }

        if ($this->_encoding == 'WinAnsiEncoding') {
            return iconv($charEncoding, 'CP1252//IGNORE', $string);
        }

        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::ENCODING_NOT_SUPPORTED);
    }

    /**
     * Convert string from the font encoding.
     *
     * The method is used to convert strings retrieved from existing content streams
     *
     * @param string $string
     * @param string $charEncoding Character encoding of resulting text.
     * @return string
     */
    public function decodeString($string, $charEncoding)
    {
        if ($this->_encoding == 'Identity-H') {
            return iconv('UTF-16BE', $charEncoding, $string);
        }

        if ($this->_encoding == 'WinAnsiEncoding') {
            return iconv('CP1252', $charEncoding, $string);
        }

        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception(self::ENCODING_NOT_SUPPORTED);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Simple.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Name.php';

/** Zend_Pdf_Resource_Font */
require_once 'Zend/Pdf/Resource/Font.php';

/**
 * Adobe PDF Simple fonts implementation
 *
 * PDF simple fonts functionality is presented by Adobe Type 1
 * (including standard PDF Type1 built-in fonts) and TrueType fonts support.
 *
 * Both fonts have the following properties:
 * - Glyphs in the font are selected by single-byte character codes obtained from a
 *   string that is shown by the text-showing operators. Logically, these codes index
 *   into a table of 256 glyphs; the mapping from codes to glyphs is called the font’s
 *   encoding.
 *   PDF specification provides a possibility to specify any user defined encoding in addition
 *   to the standard built-in encodings: Standard-Encoding, MacRomanEncoding, WinAnsiEncoding,
 *   and PDFDocEncoding, but Zend_Pdf simple fonts implementation operates only with
 *   Windows ANSI encoding (except Symbol and ZapfDingbats built-in fonts).
 *
 * - Each glyph has a single set of metrics, including a horizontal displacement or
 *   width. That is, simple fonts support only horizontal writing mode.
 *
 *
 * The code in this class is common to both types. However, you will only deal
 * directly with subclasses.
 *
 * Font objects should be normally be obtained from the factory methods
 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Pdf_Resource_Font_Simple extends Zend_Pdf_Resource_Font
{
    /**
     * Object representing the font's cmap (character to glyph map).
     * @var Zend_Pdf_Cmap
     */
    protected $_cmap = null;

    /**
     * Array containing the widths of each of the glyphs contained in the font.
     *
     * Keys are integers starting from 0, which coresponds to Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH.
     *
     * Font character map may contain gaps for actually used glyphs, nevertheless glyphWidths array
     * contains widths for all glyphs even they are unused.
     *
     * @var array
     */
    protected $_glyphWidths = null;

    /**
     * Width for glyphs missed in the font
     *
     * Note: Adobe PDF specfication (V1.4 - V1.6) doesn't define behavior for rendering
     * characters missed in the standard PDF fonts (such us 0x7F (DEL) Windows ANSI code)
     * Adobe Font Metrics files doesn't also define metrics for "missed glyph".
     * We provide character width as "0" for this case, but actually it depends on PDF viewer
     * implementation.
     *
     * @var integer
     */
    protected $_missingGlyphWidth = 0;

    /**** Public Interface ****/

  /* Object Lifecycle */

    /**
     * Object constructor
     *
     */
    public function __construct()
    {
        parent::__construct();

        /**
         * @todo
         * It's easy to add other encodings support now (Standard-Encoding, MacRomanEncoding,
         * PDFDocEncoding, MacExpertEncoding, Symbol, and ZapfDingbats).
         * Steps for the implementation:
         * - completely describe all PDF single byte encodings in the documentation
         * - implement non-WinAnsi encodings processing into encodeString()/decodeString() methods
         *
         * These encodings will be automatically supported for standard builtin PDF fonts as well
         * as for external fonts.
         */
        $this->_resource->Encoding = new Zend_Pdf_Element_Name('WinAnsiEncoding');
    }

    /**
     * Returns an array of glyph numbers corresponding to the Unicode characters.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumberForCharacter()}.
     *
     * @param array $characterCodes Array of Unicode character codes (code points).
     * @return array Array of glyph numbers.
     */
    public function glyphNumbersForCharacters($characterCodes)
    {
        return $this->_cmap->glyphNumbersForCharacters($characterCodes);
    }

    /**
     * Returns the glyph number corresponding to the Unicode character.
     *
     * If a particular character doesn't exist in this font, the special 'missing
     * character glyph' will be substituted.
     *
     * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
     * operations.
     *
     * @param integer $characterCode Unicode character code (code point).
     * @return integer Glyph number.
     */
    public function glyphNumberForCharacter($characterCode)
    {
        return $this->_cmap->glyphNumberForCharacter($characterCode);
    }

    /**
     * Returns a number between 0 and 1 inclusive that indicates the percentage
     * of characters in the string which are covered by glyphs in this font.
     *
     * Since no one font will contain glyphs for the entire Unicode character
     * range, this method can be used to help locate a suitable font when the
     * actual contents of the string are not known.
     *
     * Note that some fonts lie about the characters they support. Additionally,
     * fonts don't usually contain glyphs for control characters such as tabs
     * and line breaks, so it is rare that you will get back a full 1.0 score.
     * The resulting value should be considered informational only.
     *
     * @param string $string
     * @param string $charEncoding (optional) Character encoding of source text.
     *   If omitted, uses 'current locale'.
     * @return float
     */
    public function getCoveredPercentage($string, $charEncoding = '')
    {
        /* Convert the string to UTF-16BE encoding so we can match the string's
         * character codes to those found in the cmap.
         */
        if ($charEncoding != 'UTF-16BE') {
            if (PHP_OS != 'AIX') { // AIX doesnt know what UTF-16BE is
                $string = iconv($charEncoding, 'UTF-16BE', $string);
            }
        }

        $charCount = (PHP_OS != 'AIX') ? iconv_strlen($string, 'UTF-16BE') : strlen($string);
        if ($charCount == 0) {
            return 0;
        }

        /* Fetch the covered character code list from the font's cmap.
         */
        $coveredCharacters = $this->_cmap->getCoveredCharacters();

        /* Calculate the score by doing a lookup for each character.
         */
        $score = 0;
        $maxIndex = strlen($string);
        for ($i = 0; $i < $maxIndex; $i++) {
            /**
             * @todo Properly handle characters encoded as surrogate pairs.
             */
            $charCode = (ord($string[$i]) << 8) | ord($string[++$i]);
            /* This could probably be optimized a bit with a binary search...
             */
            if (in_array($charCode, $coveredCharacters)) {
                $score++;
            }
        }
        return $score / $charCount;
    }

    /**
     * Returns the widths of the glyphs.
     *
     * The widths are expressed in the font's glyph space. You are responsible
     * for converting to user space as necessary. See {@link unitsPerEm()}.
     *
     * See also {@link widthForGlyph()}.
     *
     * @param array &$glyphNumbers Array of glyph numbers.
     * @return array Array of glyph widths (integers).
     */
    public function widthsForGlyphs($glyphNumbers)
    {
        $widths = array();
        foreach ($glyphNumbers as $key => $glyphNumber) {
            if (!isset($this->_glyphWidths[$glyphNumber])) {
                $widths[$key] = $this->_missingGlyphWidth;
            } else {
                $widths[$key] = $this->_glyphWidths[$glyphNumber];
            }
        }
        return $widths;
    }

    /**
     * Returns the width of the glyph.
     *
     * Like {@link widthsForGlyphs()} but used for one glyph at a time.
     *
     * @param integer $glyphNumber
     * @return integer
     */
    public function widthForGlyph($glyphNumber)
    {
        if (!isset($this->_glyphWidths[$glyphNumber])) {
            return $this->_missingGlyphWidth;
        }
        return $this->_glyphWidths[$glyphNumber];
    }

    /**
     * Convert string to the font encoding.
     *
     * The method is used to prepare string for text drawing operators
     *
     * @param string $string
     * @param string $charEncoding Character encoding of source text.
     * @return string
     */
    public function encodeString($string, $charEncoding)
    {
        if (PHP_OS == 'AIX') {
            return $string; // returning here b/c AIX doesnt know what CP1252 is
        }

        return iconv($charEncoding, 'CP1252//IGNORE', $string);
    }

    /**
     * Convert string from the font encoding.
     *
     * The method is used to convert strings retrieved from existing content streams
     *
     * @param string $string
     * @param string $charEncoding Character encoding of resulting text.
     * @return string
     */
    public function decodeString($string, $charEncoding)
    {
        return iconv('CP1252', $charEncoding, $string);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: FontDescriptor.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Array.php';
require_once 'Zend/Pdf/Element/Dictionary.php';
require_once 'Zend/Pdf/Element/Name.php';
require_once 'Zend/Pdf/Element/Numeric.php';

/** Zend_Pdf_Font */
require_once 'Zend/Pdf/Font.php';

/**
 * FontDescriptor implementation
 *
 * A font descriptor specifies metrics and other attributes of a simple font or a
 * CIDFont as a whole, as distinct from the metrics of individual glyphs. These font
 * metrics provide information that enables a viewer application to synthesize a
 * substitute font or select a similar font when the font program is unavailable. The
 * font descriptor may also be used to embed the font program in the PDF file.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Font_FontDescriptor
{
    /**
     * Object constructor
     * @throws Zend_Pdf_Exception
     */
    public function __construct()
    {
        require_once 'Zend/Pdf/Exception.php';
        throw new Zend_Pdf_Exception('Zend_Pdf_Resource_Font_FontDescriptor is not intended to be instantiated');
    }

    /**
     * Object constructor
     *
     * The $embeddingOptions parameter allows you to set certain flags related
     * to font embedding. You may combine options by OR-ing them together. See
     * the EMBED_ constants defined in {@link Zend_Pdf_Font} for the list of
     * available options and their descriptions.
     *
     * Note that it is not requried that fonts be embedded within the PDF file
     * to use them. If the recipient of the PDF has the font installed on their
     * computer, they will see the correct fonts in the document. If they don't,
     * the PDF viewer will substitute or synthesize a replacement.
     *
     *
     * @param Zend_Pdf_Resource_Font $font Font
     * @param Zend_Pdf_FileParser_Font_OpenType $fontParser Font parser object containing parsed TrueType file.
     * @param integer $embeddingOptions Options for font embedding.
     * @return Zend_Pdf_Element_Dictionary
     * @throws Zend_Pdf_Exception
     */
    static public function factory(Zend_Pdf_Resource_Font $font, Zend_Pdf_FileParser_Font_OpenType $fontParser, $embeddingOptions)
    {
        /* The font descriptor object contains the rest of the font metrics and
         * the information about the embedded font program (if applicible).
         */
        $fontDescriptor = new Zend_Pdf_Element_Dictionary();

        $fontDescriptor->Type     = new Zend_Pdf_Element_Name('FontDescriptor');
        $fontDescriptor->FontName = new Zend_Pdf_Element_Name($font->getResource()->BaseFont->value);

        /* The font flags value is a bitfield that describes the stylistic
         * attributes of the font. We will set as many of the bits as can be
         * determined from the font parser.
         */
        $flags = 0;
        if ($fontParser->isMonospaced) {    // bit 1: FixedPitch
            $flags |= 1 << 0;
        }
        if ($fontParser->isSerifFont) {    // bit 2: Serif
            $flags |= 1 << 1;
        }
        if (! $fontParser->isAdobeLatinSubset) {    // bit 3: Symbolic
            $flags |= 1 << 2;
        }
        if ($fontParser->isScriptFont) {    // bit 4: Script
            $flags |= 1 << 3;
        }
        if ($fontParser->isAdobeLatinSubset) {    // bit 6: Nonsymbolic
            $flags |= 1 << 5;
        }
        if ($fontParser->isItalic) {    // bit 7: Italic
            $flags |= 1 << 6;
        }
        // bits 17-19: AllCap, SmallCap, ForceBold; not available
        $fontDescriptor->Flags = new Zend_Pdf_Element_Numeric($flags);

        $fontBBox = array(new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->xMin)),
                          new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->yMin)),
                          new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->xMax)),
                          new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->yMax)));
        $fontDescriptor->FontBBox     = new Zend_Pdf_Element_Array($fontBBox);

        $fontDescriptor->ItalicAngle  = new Zend_Pdf_Element_Numeric($fontParser->italicAngle);

        $fontDescriptor->Ascent       = new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->ascent));
        $fontDescriptor->Descent      = new Zend_Pdf_Element_Numeric($font->toEmSpace($fontParser->descent));

        $fontDescriptor->CapHeight    = new Zend_Pdf_Element_Numeric($fontParser->capitalHeight);
        /**
         * The vertical stem width is not yet extracted from the OpenType font
         * file. For now, record zero which is interpreted as 'unknown'.
         * @todo Calculate value for StemV.
         */
        $fontDescriptor->StemV        = new Zend_Pdf_Element_Numeric(0);

        $fontDescriptor->MissingWidth = new Zend_Pdf_Element_Numeric($fontParser->glyphWidths[0]);

        /* Set up font embedding. This is where the actual font program itself
         * is embedded within the PDF document.
         *
         * Note that it is not requried that fonts be embedded within the PDF
         * document to use them. If the recipient of the PDF has the font
         * installed on their computer, they will see the correct fonts in the
         * document. If they don't, the PDF viewer will substitute or synthesize
         * a replacement.
         *
         * There are several guidelines for font embedding:
         *
         * First, the developer might specifically request not to embed the font.
         */
        if (!($embeddingOptions & Zend_Pdf_Font::EMBED_DONT_EMBED)) {

            /* Second, the font author may have set copyright bits that prohibit
             * the font program from being embedded. Yes this is controversial,
             * but it's the rules:
             *   http://partners.adobe.com/public/developer/en/acrobat/sdk/FontPolicies.pdf
             *
             * To keep the developer in the loop, and to prevent surprising bug
             * reports of "your PDF doesn't have the right fonts," throw an
             * exception if the font cannot be embedded.
             */
            if (! $fontParser->isEmbeddable) {
                /* This exception may be suppressed if the developer decides that
                 * it's not a big deal that the font program can't be embedded.
                 */
                if (!($embeddingOptions & Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION)) {
                    $message = 'This font cannot be embedded in the PDF document. If you would like to use '
                             . 'it anyway, you must pass Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION '
                             . 'in the $options parameter of the font constructor.';
                    require_once 'Zend/Pdf/Exception.php';
                    throw new Zend_Pdf_Exception($message, Zend_Pdf_Exception::FONT_CANT_BE_EMBEDDED);
                }

            } else {
                /* Otherwise, the default behavior is to embed all custom fonts.
                 */
                /* This section will change soon to a stream object data
                 * provider model so that we don't have to keep a copy of the
                 * entire font in memory.
                 *
                 * We also cannot build font subsetting until the data provider
                 * model is in place.
                 */
                $fontFile = $fontParser->getDataSource()->readAllBytes();
                $fontFileObject = $font->getFactory()->newStreamObject($fontFile);
                $fontFileObject->dictionary->Length1 = new Zend_Pdf_Element_Numeric(strlen($fontFile));
                if (!($embeddingOptions & Zend_Pdf_Font::EMBED_DONT_COMPRESS)) {
                    /* Compress the font file using Flate. This generally cuts file
                     * sizes by about half!
                     */
                    $fontFileObject->dictionary->Filter = new Zend_Pdf_Element_Name('FlateDecode');
                }
                if ($fontParser instanceof Zend_Pdf_FileParser_Font_OpenType_Type1 /* not implemented now */) {
                    $fontDescriptor->FontFile  = $fontFileObject;
                } else if ($fontParser instanceof Zend_Pdf_FileParser_Font_OpenType_TrueType) {
                    $fontDescriptor->FontFile2 = $fontFileObject;
                } else {
                    $fontDescriptor->FontFile3 = $fontFileObject;
                }
            }
        }

        return $fontDescriptor;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: TrueType.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */

require_once 'Zend/Pdf/Element/Name.php';

/** Zend_Pdf_Resource_Font_FontDescriptor */
require_once 'Zend/Pdf/Resource/Font/FontDescriptor.php';

/** Zend_Pdf_Resource_Font_CidFont */
require_once 'Zend/Pdf/Resource/Font/CidFont.php';

/**
 * Type 2 CIDFonts implementation
 *
 * For Type 2, the CIDFont program is actually a TrueType font program, which has
 * no native notion of CIDs. In a TrueType font program, glyph descriptions are
 * identified by glyph index values. Glyph indices are internal to the font and are not
 * defined consistently from one font to another. Instead, a TrueType font program
 * contains a 'cmap' table that provides mappings directly from character codes to
 * glyph indices for one or more predefined encodings.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Pdf_Resource_Font_CidFont_TrueType extends Zend_Pdf_Resource_Font_CidFont
{
    /**
     * Object constructor
     *
     * @todo Joing this class with Zend_Pdf_Resource_Font_Simple_Parsed_TrueType
     *
     * @param Zend_Pdf_FileParser_Font_OpenType_TrueType $fontParser Font parser
     *   object containing parsed TrueType file.
     * @param integer $embeddingOptions Options for font embedding.
     * @throws Zend_Pdf_Exception
     */
    public function __construct(Zend_Pdf_FileParser_Font_OpenType_TrueType $fontParser, $embeddingOptions)
    {
        parent::__construct($fontParser, $embeddingOptions);

        $this->_fontType = Zend_Pdf_Font::TYPE_CIDFONT_TYPE_2;

        $this->_resource->Subtype  = new Zend_Pdf_Element_Name('CIDFontType2');

        $fontDescriptor = Zend_Pdf_Resource_Font_FontDescriptor::factory($this, $fontParser, $embeddingOptions);
        $this->_resource->FontDescriptor = $this->_objectFactory->newObject($fontDescriptor);

        /* Prepare CIDToGIDMap */
        // Initialize 128K string of null characters (65536 2 byte integers)
        $cidToGidMapData = str_repeat("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 8192);
        // Fill the index
        $charGlyphs = $this->_cmap->getCoveredCharactersGlyphs();
        foreach ($charGlyphs as $charCode => $glyph) {
            $cidToGidMapData[$charCode*2    ] = chr($glyph >> 8);
            $cidToGidMapData[$charCode*2 + 1] = chr($glyph & 0xFF);
        }
        // Store CIDToGIDMap within compressed stream object
        $cidToGidMap = $this->_objectFactory->newStreamObject($cidToGidMapData);
        $cidToGidMap->dictionary->Filter = new Zend_Pdf_Element_Name('FlateDecode');
        $this->_resource->CIDToGIDMap = $cidToGidMap;
    }

}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Standard.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Name.php';

/** Zend_Pdf_Resource_Font_Simple */
require_once 'Zend/Pdf/Resource/Font/Simple.php';

/**
 * Abstract class definition for the standard 14 Type 1 PDF fonts.
 *
 * The standard 14 PDF fonts are guaranteed to be availble in any PDF viewer
 * implementation. As such, they do not require much data for the font's
 * resource dictionary. The majority of the data provided by subclasses is for
 * the benefit of our own layout code.
 *
 * The standard fonts and the corresponding subclasses that manage them:
 *

 *
Courier - {@link Zend_Pdf_Resource_Font_Simple_Standard_Courier}
 *
Courier-Bold - {@link Zend_Pdf_Resource_Font_Simple_Standard_CourierBold}
 *
Courier-Oblique - {@link Zend_Pdf_Resource_Font_Simple_Standard_CourierOblique}
 *
Courier-BoldOblique - {@link Zend_Pdf_Resource_Font_Simple_Standard_CourierBoldOblique}
 *
Helvetica - {@link Zend_Pdf_Resource_Font_Simple_Standard_Helvetica}
 *
Helvetica-Bold - {@link Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBold}
 *
Helvetica-Oblique - {@link Zend_Pdf_Resource_Font_Simple_Standard_HelveticaOblique}
 *
Helvetica-BoldOblique - {@link Zend_Pdf_Resource_Font_Simple_Standard_HelveticaBoldOblique}
 *
Symbol - {@link Zend_Pdf_Resource_Font_Simple_Standard_Symbol}
 *
Times - {@link Zend_Pdf_Resource_Font_Simple_Standard_Times}
 *
Times-Bold - {@link Zend_Pdf_Resource_Font_Simple_Standard_TimesBold}
 *
Times-Italic - {@link Zend_Pdf_Resource_Font_Simple_Standard_TimesItalic}
 *
Times-BoldItalic - {@link Zend_Pdf_Resource_Font_Simple_Standard_TimesBoldItalic}
 *
ZapfDingbats - {@link Zend_Pdf_Resource_Font_Simple_Standard_ZapfDingbats}
 *

 *
 * Font objects should be normally be obtained from the factory methods
 * {@link Zend_Pdf_Font::fontWithName} and {@link Zend_Pdf_Font::fontWithPath}.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Pdf_Resource_Font_Simple_Standard extends Zend_Pdf_Resource_Font_Simple
{
  /**** Public Interface ****/

  /* Object Lifecycle */

    /**
     * Object constructor
     */
    public function __construct()
    {
        $this->_fontType = Zend_Pdf_Font::TYPE_STANDARD;

        parent::__construct();
        $this->_resource->Subtype  = new Zend_Pdf_Element_Name('Type1');
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Parsed.php 23775 2011-03-01 17:25:24Z ralph $
 */

/** Internally used classes */
require_once 'Zend/Pdf/Element/Array.php';
require_once 'Zend/Pdf/Element/Name.php';
require_once 'Zend/Pdf/Element/Numeric.php';

/** Zend_Pdf_Resource_Font_Simple */
require_once 'Zend/Pdf/Resource/Font/Simple.php';

/**
 * Parsed and (optionaly) embedded fonts implementation
 *
 * OpenType fonts can contain either TrueType or PostScript Type 1 outlines.
 *
 * @package    Zend_Pdf
 * @subpackage Fonts
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Pdf_Resource_Font_Simple_Parsed extends Zend_Pdf_Resource_Font_Simple
{
    /**
     * Object constructor
     *
     * @param Zend_Pdf_FileParser_Font_OpenType $fontParser Font parser object containing OpenType file.
     * @throws Zend_Pdf_Exception
     */
    public function __construct(Zend_Pdf_FileParser_Font_OpenType $fontParser)
    {
        parent::__construct();

        $fontParser->parse();

        /* Object properties */

        $this->_fontNames = $fontParser->names;

        $this->_isBold       = $fontParser->isBold;
        $this->_isItalic     = $fontParser->isItalic;
        $this->_isMonospaced = $fontParser->isMonospaced;

        $this->_underlinePosition  = $fontParser->underlinePosition;
        $this->_underlineThickness = $fontParser->underlineThickness;
        $this->_strikePosition     = $fontParser->strikePosition;
        $this->_strikeThickness    = $fontParser->strikeThickness;

        $this->_unitsPerEm = $fontParser->unitsPerEm;

        $this->_ascent  = $fontParser->ascent;
        $this->_descent = $fontParser->descent;
        $this->_lineGap = $fontParser->lineGap;

        $this->_glyphWidths       = $fontParser->glyphWidths;
        $this->_missingGlyphWidth = $this->_glyphWidths[0];

        $this->_cmap = $fontParser->cmap;

        /* Resource dictionary */

        $baseFont = $this->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT, 'en', 'UTF-8');
        $this->_resource->BaseFont = new Zend_Pdf_Element_Name($baseFont);

        $this->_resource->FirstChar = new Zend_Pdf_Element_Numeric(0);
        $this->_resource->LastChar  = new Zend_Pdf_Element_Numeric(count($this->_glyphWidths) - 1);

        /* Now convert the scalar glyph widths to Zend_Pdf_Element_Numeric objects.
         */
        $pdfWidths = array();
        foreach ($this->_glyphWidths as $width) {
            $pdfWidths[] = new Zend_Pdf_Element_Numeric($this->toEmSpace($width));
        }
        /* Create the Zend_Pdf_Element_Array object and add it to the font's
         * object factory and resource dictionary.
         */
        $widthsArrayElement = new Zend_Pdf_Element_Array($pdfWidths);
        $widthsObject = $this->_objectFactory->newObject($widthsArrayElement);
        $this->_resource->Widths = $widthsObject;
    }
}