source-class-Com.Tecnick.Pdf.Font.Import.TrueTypeFormat

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
  1: <?php
  2: /**
  3:  * TrueType.php
  4:  *
  5:  * @since       2011-05-23
  6:  * @category    Library
  7:  * @package     PdfFont
  8:  * @author      Nicola Asuni <info@tecnick.com>
  9:  * @copyright   2011-2015 Nicola Asuni - Tecnick.com LTD
 10:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 11:  * @link        https://github.com/tecnickcom/tc-lib-pdf-font
 12:  *
 13:  * This file is part of tc-lib-pdf-font software library.
 14:  */
 15: 
 16: namespace Com\Tecnick\Pdf\Font\Import;
 17: 
 18: use \Com\Tecnick\File\File;
 19: use \Com\Tecnick\Unicode\Data\Encoding;
 20: use \Com\Tecnick\Pdf\Font\Exception as FontException;
 21: 
 22: /**
 23:  * Com\Tecnick\Pdf\Font\Import\TrueTypeFormat
 24:  *
 25:  * @since       2011-05-23
 26:  * @category    Library
 27:  * @package     PdfFont
 28:  * @author      Nicola Asuni <info@tecnick.com>
 29:  * @copyright   2011-2015 Nicola Asuni - Tecnick.com LTD
 30:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 31:  * @link        https://github.com/tecnickcom/tc-lib-pdf-font
 32:  */
 33: abstract class TrueTypeFormat
 34: {
 35:     /**
 36:      * Array containing subset chars
 37:      *
 38:      * @var array
 39:      */
 40:     protected $subchars = array();
 41: 
 42:     /**
 43:      * Array containing subset glyphs indexes of chars from cmap table
 44:      *
 45:      * @var array
 46:      */
 47:     protected $subglyphs = array();
 48: 
 49:     /**
 50:      * Add CTG entry
 51:      *
 52:      * @param int $cid
 53:      * @param int $gid
 54:      */
 55:     protected function addCtgItem($cid, $gid)
 56:     {
 57:         $this->fdt['ctgdata'][$cid] = $gid;
 58:         if (isset($this->subchars[$cid])) {
 59:             $this->subglyphs[$gid] = true;
 60:         }
 61:     }
 62: 
 63:     /**
 64:      * Get CIDToGIDMap
 65:      */
 66:     protected function getCIDToGIDMap()
 67:     {
 68:         $valid_format = array(0,2,4,6,8,10,12,13,14);
 69:         $this->fdt['ctgdata'] = array();
 70:         foreach ($this->fdt['encodingTables'] as $enctable) {
 71:             // get only specified Platform ID and Encoding ID
 72:             if (($enctable['platformID'] == $this->fdt['platform_id'])
 73:                 && ($enctable['encodingID'] == $this->fdt['encoding_id'])
 74:             ) {
 75:                 $this->offset = ($this->fdt['table']['cmap']['offset'] + $enctable['offset']);
 76:                 $format = $this->fbyte->getUShort($this->offset);
 77:                 $this->offset += 2;
 78:                 if (in_array($format, $valid_format)) {
 79:                     $method = 'processFormat'.$format;
 80:                     $this->$method();
 81:                 }
 82:             }
 83:         }
 84:         if (!isset($this->fdt['ctgdata'][0])) {
 85:             $this->fdt['ctgdata'][0] = 0;
 86:         } elseif (($this->fdt['type'] == 'TrueTypeUnicode') && (count($this->fdt['ctgdata']) == 256)) {
 87:             $this->fdt['type'] = 'TrueType';
 88:         }
 89:     }
 90: 
 91:     /**
 92:      * Process Format 0: Byte encoding table
 93:      */
 94:     protected function processFormat0()
 95:     {
 96:         $this->offset += 4; // skip length and version/language
 97:         for ($chr = 0; $chr < 256; ++$chr) {
 98:             $gid = $this->fbyte->getByte($this->offset);
 99:             $this->addCtgItem($chr, $gid);
100:             ++$this->offset;
101:         }
102:     }
103: 
104:     /**
105:      * Process Format 2: High-byte mapping through table
106:      */
107:     protected function processFormat2()
108:     {
109:         $this->offset += 4; // skip length and version/language
110:         $numSubHeaders = 0;
111:         for ($chr = 0; $chr < 256; ++$chr) {
112:             // Array that maps high bytes to subHeaders: value is subHeader index * 8.
113:             $subHeaderKeys[$chr] = ($this->fbyte->getUShort($this->offset) / 8);
114:             $this->offset += 2;
115:             if ($numSubHeaders < $subHeaderKeys[$chr]) {
116:                 $numSubHeaders = $subHeaderKeys[$chr];
117:             }
118:         }
119:         // the number of subHeaders is equal to the max of subHeaderKeys + 1
120:         ++$numSubHeaders;
121:         // read subHeader structures
122:         $subHeaders = array();
123:         $numGlyphIndexArray = 0;
124:         for ($ish = 0; $ish < $numSubHeaders; ++$ish) {
125:             $subHeaders[$ish]['firstCode'] = $this->fbyte->getUShort($this->offset);
126:             $this->offset += 2;
127:             $subHeaders[$ish]['entryCount'] = $this->fbyte->getUShort($this->offset);
128:             $this->offset += 2;
129:             $subHeaders[$ish]['idDelta'] = $this->fbyte->getUShort($this->offset);
130:             $this->offset += 2;
131:             $subHeaders[$ish]['idRangeOffset'] = $this->fbyte->getUShort($this->offset);
132:             $this->offset += 2;
133:             $subHeaders[$ish]['idRangeOffset'] -= (2 + (($numSubHeaders - $ish - 1) * 8));
134:             $subHeaders[$ish]['idRangeOffset'] /= 2;
135:             $numGlyphIndexArray += $subHeaders[$ish]['entryCount'];
136:         }
137:         for ($gid = 0; $gid < $numGlyphIndexArray; ++$gid) {
138:             $glyphIndexArray[$gid] = $this->fbyte->getUShort($this->offset);
139:             $this->offset += 2;
140:         }
141:         for ($chr = 0; $chr < 256; ++$chr) {
142:             $shk = $subHeaderKeys[$chr];
143:             if ($shk == 0) {
144:                 // one byte code
145:                 $cdx = $chr;
146:                 $gid = $glyphIndexArray[0];
147:                 $this->addCtgItem($cdx, $gid);
148:             } else {
149:                 // two bytes code
150:                 $start_byte = $subHeaders[$shk]['firstCode'];
151:                 $end_byte = $start_byte + $subHeaders[$shk]['entryCount'];
152:                 for ($jdx = $start_byte; $jdx < $end_byte; ++$jdx) {
153:                     // combine high and low bytes
154:                     $cdx = (($chr << 8) + $jdx);
155:                     $idRangeOffset = ($subHeaders[$shk]['idRangeOffset'] + $jdx - $subHeaders[$shk]['firstCode']);
156:                     $gid = max(0, (($glyphIndexArray[$idRangeOffset] + $subHeaders[$shk]['idDelta']) % 65536));
157:                     $this->addCtgItem($cdx, $gid);
158:                 }
159:             }
160:         }
161:     }
162: 
163:     /**
164:      * Process Format 4: Segment mapping to delta values
165:      */
166:     protected function processFormat4()
167:     {
168:         $length = $this->fbyte->getUShort($this->offset);
169:         $this->offset += 2;
170:         $this->offset += 2; // skip version/language
171:         $segCount = floor($this->fbyte->getUShort($this->offset) / 2);
172:         $this->offset += 2;
173:         $this->offset += 6; // skip searchRange, entrySelector, rangeShift
174:         $endCount = array(); // array of end character codes for each segment
175:         for ($kdx = 0; $kdx < $segCount; ++$kdx) {
176:             $endCount[$kdx] = $this->fbyte->getUShort($this->offset);
177:             $this->offset += 2;
178:         }
179:         $this->offset += 2; // skip reservedPad
180:         $startCount = array(); // array of start character codes for each segment
181:         for ($kdx = 0; $kdx < $segCount; ++$kdx) {
182:             $startCount[$kdx] = $this->fbyte->getUShort($this->offset);
183:             $this->offset += 2;
184:         }
185:         $idDelta = array(); // delta for all character codes in segment
186:         for ($kdx = 0; $kdx < $segCount; ++$kdx) {
187:             $idDelta[$kdx] = $this->fbyte->getUShort($this->offset);
188:             $this->offset += 2;
189:         }
190:         $idRangeOffset = array(); // Offsets into glyphIdArray or 0
191:         for ($kdx = 0; $kdx < $segCount; ++$kdx) {
192:             $idRangeOffset[$kdx] = $this->fbyte->getUShort($this->offset);
193:             $this->offset += 2;
194:         }
195:         $gidlen = (floor($length / 2) - 8 - (4 * $segCount));
196:         $glyphIdArray = array(); // glyph index array
197:         for ($kdx = 0; $kdx < $gidlen; ++$kdx) {
198:             $glyphIdArray[$kdx] = $this->fbyte->getUShort($this->offset);
199:             $this->offset += 2;
200:         }
201:         for ($kdx = 0; $kdx < $segCount; ++$kdx) {
202:             for ($chr = $startCount[$kdx]; $chr <= $endCount[$kdx]; ++$chr) {
203:                 if ($idRangeOffset[$kdx] == 0) {
204:                     $gid = max(0, (($idDelta[$kdx] + $chr) % 65536));
205:                 } else {
206:                     $gid = (floor($idRangeOffset[$kdx] / 2) + ($chr - $startCount[$kdx]) - ($segCount - $kdx));
207:                     $gid = max(0, (($glyphIdArray[$gid] + $idDelta[$kdx]) % 65536));
208:                 }
209:                 $this->addCtgItem($chr, $gid);
210:             }
211:         }
212:     }
213: 
214:     /**
215:      * Process Format 6: Trimmed table mapping
216:      */
217:     protected function processFormat6()
218:     {
219:         $this->offset += 4; // skip length and version/language
220:         $firstCode = $this->fbyte->getUShort($this->offset);
221:         $this->offset += 2;
222:         $entryCount = $this->fbyte->getUShort($this->offset);
223:         $this->offset += 2;
224:         for ($kdx = 0; $kdx < $entryCount; ++$kdx) {
225:             $chr = ($kdx + $firstCode);
226:             $gid = $this->fbyte->getUShort($this->offset);
227:             $this->offset += 2;
228:             $this->addCtgItem($chr, $gid);
229:         }
230:     }
231: 
232:     /**
233:      * Process Format 8: Mixed 16-bit and 32-bit coverage
234:      */
235:     protected function processFormat8()
236:     {
237:         $this->offset += 10; // skip reserved, length and version/language
238:         for ($kdx = 0; $kdx < 8192; ++$kdx) {
239:             $is32[$kdx] = $this->fbyte->getByte($this->offset);
240:             ++$this->offset;
241:         }
242:         $nGroups = $this->fbyte->getULong($this->offset);
243:         $this->offset += 4;
244:         for ($idx = 0; $idx < $nGroups; ++$idx) {
245:             $startCharCode = $this->fbyte->getULong($this->offset);
246:             $this->offset += 4;
247:             $endCharCode = $this->fbyte->getULong($this->offset);
248:             $this->offset += 4;
249:             $startGlyphID = $this->fbyte->getULong($this->offset);
250:             $this->offset += 4;
251:             for ($cpw = $startCharCode; $cpw <= $endCharCode; ++$cpw) {
252:                 $is32idx = floor($cpw / 8);
253:                 if ((isset($is32[$is32idx])) && (($is32[$is32idx] & (1 << (7 - ($cpw % 8)))) == 0)) {
254:                     $chr = $cpw;
255:                 } else {
256:                     // 32 bit format
257:                     // convert to decimal (http://www.unicode.org/faq//utf_bom.html#utf16-4)
258:                     //LEAD_OFFSET = (0xD800 - (0x10000 >> 10)) = 55232
259:                     //SURROGATE_OFFSET = (0x10000 - (0xD800 << 10) - 0xDC00) = -56613888
260:                     $chr = (((55232 + ($cpw >> 10)) << 10) + (0xDC00 + ($cpw & 0x3FF)) - 56613888);
261:                 }
262:                 $this->addCtgItem($chr, $startGlyphID);
263:                 $this->fdt['ctgdata'][$chr] = 0; // overwrite
264:                 ++$startGlyphID;
265:             }
266:         }
267:     }
268: 
269:     /**
270:      * Process Format 10: Trimmed array
271:      */
272:     protected function processFormat10()
273:     {
274:         $this->offset += 10; // skip reserved, length and version/language
275:         $startCharCode = $this->fbyte->getULong($this->offset);
276:         $this->offset += 4;
277:         $numChars = $this->fbyte->getULong($this->offset);
278:         $this->offset += 4;
279:         for ($kdx = 0; $kdx < $numChars; ++$kdx) {
280:             $chr = ($kdx + $startCharCode);
281:             $gid = $this->fbyte->getUShort($this->offset);
282:             $this->addCtgItem($chr, $gid);
283:             $this->offset += 2;
284:         }
285:     }
286: 
287:     /**
288:      * Process Format 12: Segmented coverage
289:      */
290:     protected function processFormat12()
291:     {
292:         $this->offset += 10; // skip length and version/language
293:         $nGroups = $this->fbyte->getULong($this->offset);
294:         $this->offset += 4;
295:         for ($kdx = 0; $kdx < $nGroups; ++$kdx) {
296:             $startCharCode = $this->fbyte->getULong($this->offset);
297:             $this->offset += 4;
298:             $endCharCode = $this->fbyte->getULong($this->offset);
299:             $this->offset += 4;
300:             $startGlyphCode = $this->fbyte->getULong($this->offset);
301:             $this->offset += 4;
302:             for ($chr = $startCharCode; $chr <= $endCharCode; ++$chr) {
303:                 $this->addCtgItem($chr, $startGlyphCode);
304:                 ++$startGlyphCode;
305:             }
306:         }
307:     }
308: 
309:     /**
310:      * Process Format 13: Many-to-one range mappings
311:      * @TODO: TO BE IMPLEMENTED
312:      */
313:     protected function processFormat13()
314:     {
315:         return;
316:     }
317: 
318:     /**
319:      * Process Format 14: Unicode Variation Sequences
320:      * @TODO: TO BE IMPLEMENTED
321:      */
322:     protected function processFormat14()
323:     {
324:         return;
325:     }
326: }
327: 
 

© 2004-2017 – Nicola Asuni - Tecnick.com - All rights reserved.
about - disclaimer - privacy