web/lib/Zend/Pdf/Cmap/TrimmedTable.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Pdf
       
    17  * @subpackage Fonts
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: TrimmedTable.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 /** Zend_Pdf_Cmap */
       
    24 require_once 'Zend/Pdf/Cmap.php';
       
    25 
       
    26 
       
    27 /**
       
    28  * Implements the "trimmed table mapping" character map (type 6).
       
    29  *
       
    30  * This table type is preferred over the {@link Zend_Pdf_Cmap_SegmentToDelta}
       
    31  * table when the Unicode characters covered by the font fall into a single
       
    32  * contiguous range.
       
    33  *
       
    34  * @package    Zend_Pdf
       
    35  * @subpackage Fonts
       
    36  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    37  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    38  */
       
    39 class Zend_Pdf_Cmap_TrimmedTable extends Zend_Pdf_Cmap
       
    40 {
       
    41   /**** Instance Variables ****/
       
    42 
       
    43 
       
    44     /**
       
    45      * The starting character code covered by this table.
       
    46      * @var integer
       
    47      */
       
    48     protected $_startCode = 0;
       
    49 
       
    50     /**
       
    51      * The ending character code covered by this table.
       
    52      * @var integer
       
    53      */
       
    54     protected $_endCode = 0;
       
    55 
       
    56     /**
       
    57      * Glyph index array. Stores the actual glyph numbers.
       
    58      * @var array
       
    59      */
       
    60     protected $_glyphIndexArray = array();
       
    61 
       
    62 
       
    63 
       
    64   /**** Public Interface ****/
       
    65 
       
    66 
       
    67   /* Concrete Class Implementation */
       
    68 
       
    69     /**
       
    70      * Returns an array of glyph numbers corresponding to the Unicode characters.
       
    71      *
       
    72      * If a particular character doesn't exist in this font, the special 'missing
       
    73      * character glyph' will be substituted.
       
    74      *
       
    75      * See also {@link glyphNumberForCharacter()}.
       
    76      *
       
    77      * @param array $characterCodes Array of Unicode character codes (code points).
       
    78      * @return array Array of glyph numbers.
       
    79      */
       
    80     public function glyphNumbersForCharacters($characterCodes)
       
    81     {
       
    82         $glyphNumbers = array();
       
    83         foreach ($characterCodes as $key => $characterCode) {
       
    84 
       
    85             if (($characterCode < $this->_startCode) || ($characterCode > $this->_endCode)) {
       
    86                 $glyphNumbers[$key] = Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH;
       
    87                 continue;
       
    88             }
       
    89 
       
    90             $glyphIndex = $characterCode - $this->_startCode;
       
    91             $glyphNumbers[$key] = $this->_glyphIndexArray[$glyphIndex];
       
    92 
       
    93         }
       
    94         return $glyphNumbers;
       
    95     }
       
    96 
       
    97     /**
       
    98      * Returns the glyph number corresponding to the Unicode character.
       
    99      *
       
   100      * If a particular character doesn't exist in this font, the special 'missing
       
   101      * character glyph' will be substituted.
       
   102      *
       
   103      * See also {@link glyphNumbersForCharacters()} which is optimized for bulk
       
   104      * operations.
       
   105      *
       
   106      * @param integer $characterCode Unicode character code (code point).
       
   107      * @return integer Glyph number.
       
   108      */
       
   109     public function glyphNumberForCharacter($characterCode)
       
   110     {
       
   111         if (($characterCode < $this->_startCode) || ($characterCode > $this->_endCode)) {
       
   112             return Zend_Pdf_Cmap::MISSING_CHARACTER_GLYPH;
       
   113         }
       
   114         $glyphIndex = $characterCode - $this->_startCode;
       
   115         return $this->_glyphIndexArray[$glyphIndex];
       
   116     }
       
   117 
       
   118     /**
       
   119      * Returns an array containing the Unicode characters that have entries in
       
   120      * this character map.
       
   121      *
       
   122      * @return array Unicode character codes.
       
   123      */
       
   124     public function getCoveredCharacters()
       
   125     {
       
   126         $characterCodes = array();
       
   127         for ($code = $this->_startCode; $code <= $this->_endCode; $code++) {
       
   128             $characterCodes[] = $code;
       
   129         }
       
   130         return $characterCodes;
       
   131     }
       
   132 
       
   133 
       
   134     /**
       
   135      * Returns an array containing the glyphs numbers that have entries in this character map.
       
   136      * Keys are Unicode character codes (integers)
       
   137      *
       
   138      * This functionality is partially covered by glyphNumbersForCharacters(getCoveredCharacters())
       
   139      * call, but this method do it in more effective way (prepare complete list instead of searching
       
   140      * glyph for each character code).
       
   141      *
       
   142      * @internal
       
   143      * @return array Array representing <Unicode character code> => <glyph number> pairs.
       
   144      */
       
   145     public function getCoveredCharactersGlyphs()
       
   146     {
       
   147         $glyphNumbers = array();
       
   148         for ($code = $this->_startCode; $code <= $this->_endCode; $code++) {
       
   149             $glyphNumbers[$code] = $this->_glyphIndexArray[$code - $this->_startCode];
       
   150         }
       
   151 
       
   152         return $glyphNumbers;
       
   153     }
       
   154 
       
   155 
       
   156   /* Object Lifecycle */
       
   157 
       
   158     /**
       
   159      * Object constructor
       
   160      *
       
   161      * Parses the raw binary table data. Throws an exception if the table is
       
   162      * malformed.
       
   163      *
       
   164      * @param string $cmapData Raw binary cmap table data.
       
   165      * @throws Zend_Pdf_Exception
       
   166      */
       
   167     public function __construct($cmapData)
       
   168     {
       
   169         /* Sanity check: The table should be at least 9 bytes in size.
       
   170          */
       
   171         $actualLength = strlen($cmapData);
       
   172         if ($actualLength < 9) {
       
   173             require_once 'Zend/Pdf/Exception.php';
       
   174             throw new Zend_Pdf_Exception('Insufficient table data',
       
   175                                          Zend_Pdf_Exception::CMAP_TABLE_DATA_TOO_SMALL);
       
   176         }
       
   177 
       
   178         /* Sanity check: Make sure this is right data for this table type.
       
   179          */
       
   180         $type = $this->_extractUInt2($cmapData, 0);
       
   181         if ($type != Zend_Pdf_Cmap::TYPE_TRIMMED_TABLE) {
       
   182             require_once 'Zend/Pdf/Exception.php';
       
   183             throw new Zend_Pdf_Exception('Wrong cmap table type',
       
   184                                          Zend_Pdf_Exception::CMAP_WRONG_TABLE_TYPE);
       
   185         }
       
   186 
       
   187         $length = $this->_extractUInt2($cmapData, 2);
       
   188         if ($length != $actualLength) {
       
   189             require_once 'Zend/Pdf/Exception.php';
       
   190             throw new Zend_Pdf_Exception("Table length ($length) does not match actual length ($actualLength)",
       
   191                                          Zend_Pdf_Exception::CMAP_WRONG_TABLE_LENGTH);
       
   192         }
       
   193 
       
   194         /* Mapping tables should be language-independent. The font may not work
       
   195          * as expected if they are not. Unfortunately, many font files in the
       
   196          * wild incorrectly record a language ID in this field, so we can't
       
   197          * call this a failure.
       
   198          */
       
   199         $language = $this->_extractUInt2($cmapData, 4);
       
   200         if ($language != 0) {
       
   201             // Record a warning here somehow?
       
   202         }
       
   203 
       
   204         $this->_startCode = $this->_extractUInt2($cmapData, 6);
       
   205 
       
   206         $entryCount = $this->_extractUInt2($cmapData, 8);
       
   207         $expectedCount = ($length - 10) >> 1;
       
   208         if ($entryCount != $expectedCount) {
       
   209             require_once 'Zend/Pdf/Exception.php';
       
   210             throw new Zend_Pdf_Exception("Entry count is wrong; expected: $expectedCount; actual: $entryCount",
       
   211                                          Zend_Pdf_Exception::CMAP_WRONG_ENTRY_COUNT);
       
   212         }
       
   213 
       
   214         $this->_endCode = $this->_startCode + $entryCount - 1;
       
   215 
       
   216         $offset = 10;
       
   217         for ($i = 0; $i < $entryCount; $i++, $offset += 2) {
       
   218             $this->_glyphIndexArray[] = $this->_extractUInt2($cmapData, $offset);
       
   219         }
       
   220 
       
   221         /* Sanity check: After reading all of the data, we should be at the end
       
   222          * of the table.
       
   223          */
       
   224         if ($offset != $length) {
       
   225             require_once 'Zend/Pdf/Exception.php';
       
   226             throw new Zend_Pdf_Exception("Ending offset ($offset) does not match length ($length)",
       
   227                                          Zend_Pdf_Exception::CMAP_FINAL_OFFSET_NOT_LENGTH);
       
   228         }
       
   229     }
       
   230 
       
   231 }