Font_Table_cmap

`cmap` font table.

Defined (1)

The class is defined in the following location(s).

/lib/dompdf/lib/php-font-lib/classes/Font_Table_cmap.php  
  1. class Font_Table_cmap extends Font_Table { 
  2. private static $header_format = array( 
  3. "version" => self::uint16,  
  4. "numberSubtables" => self::uint16,  
  5. ); 
  6.  
  7. private static $subtable_header_format = array( 
  8. "platformID" => self::uint16,  
  9. "platformSpecificID" => self::uint16,  
  10. "offset" => self::uint32,  
  11. ); 
  12.  
  13. private static $subtable_v4_format = array( 
  14. "length" => self::uint16,  
  15. "language" => self::uint16,  
  16. "segCountX2" => self::uint16,  
  17. "searchRange" => self::uint16,  
  18. "entrySelector" => self::uint16,  
  19. "rangeShift" => self::uint16,  
  20. ); 
  21.  
  22. protected function _parse() { 
  23. $font = $this->getFont(); 
  24.  
  25. $cmap_offset = $font->pos(); 
  26.  
  27. $data = $font->unpack(self::$header_format); 
  28.  
  29. $subtables = array(); 
  30. for($i = 0; $i < $data["numberSubtables"]; $i++) { 
  31. $subtables[] = $font->unpack(self::$subtable_header_format); 
  32. $data["subtables"] = $subtables; 
  33.  
  34. foreach($data["subtables"] as $i => &$subtable) { 
  35. $font->seek($cmap_offset + $subtable["offset"]); 
  36.  
  37. $subtable["format"] = $font->readUInt16(); 
  38.  
  39. // @todo Only CMAP version 4 
  40. if($subtable["format"] != 4) { 
  41. unset($data["subtables"][$i]); 
  42. $data["numberSubtables"]--; 
  43. continue; 
  44.  
  45. $subtable += $font->unpack(self::$subtable_v4_format); 
  46. $segCount = $subtable["segCountX2"] / 2; 
  47. $subtable["segCount"] = $segCount; 
  48.  
  49. $endCode = $font->r(array(self::uint16, $segCount)); 
  50.  
  51. $font->readUInt16(); // reservedPad 
  52.  
  53. $startCode = $font->r(array(self::uint16, $segCount)); 
  54. $idDelta = $font->r(array(self::int16, $segCount)); 
  55.  
  56. $ro_start = $font->pos(); 
  57. $idRangeOffset = $font->r(array(self::uint16, $segCount)); 
  58.  
  59. $glyphIndexArray = array(); 
  60. for($i = 0; $i < $segCount; $i++) { 
  61. $c1 = $startCode[$i]; 
  62. $c2 = $endCode[$i]; 
  63. $d = $idDelta[$i]; 
  64. $ro = $idRangeOffset[$i]; 
  65.  
  66. if($ro > 0) 
  67. $font->seek($subtable["offset"] + 2 * $i + $ro); 
  68.  
  69. for($c = $c1; $c <= $c2; $c++) { 
  70. if ($ro == 0) 
  71. $gid = ($c + $d) & 0xFFFF; 
  72. else { 
  73. $offset = ($c - $c1) * 2 + $ro; 
  74. $offset = $ro_start + 2 * $i + $offset; 
  75.  
  76. $font->seek($offset); 
  77. $gid = $font->readUInt16(); 
  78.  
  79. if ($gid != 0) 
  80. $gid = ($gid + $d) & 0xFFFF; 
  81.  
  82. if($gid > 0) { 
  83. $glyphIndexArray[$c] = $gid; 
  84.  
  85. $subtable += array( 
  86. "endCode" => $endCode,  
  87. "startCode" => $startCode,  
  88. "idDelta" => $idDelta,  
  89. "idRangeOffset" => $idRangeOffset,  
  90. "glyphIndexArray" => $glyphIndexArray,  
  91. ); 
  92.  
  93. $this->data = $data; 
  94.  
  95. function _encode() { 
  96. $font = $this->getFont(); 
  97.  
  98. $subset = $font->getSubset(); 
  99. $glyphIndexArray = $font->getUnicodeCharMap(); 
  100.  
  101. $newGlyphIndexArray = array(); 
  102. foreach ($glyphIndexArray as $code => $gid) { 
  103. $new_gid = array_search($gid, $subset); 
  104. if ($new_gid !== false) { 
  105. $newGlyphIndexArray[$code] = $new_gid; 
  106.  
  107. ksort($newGlyphIndexArray); // Sort by char code 
  108.  
  109. $segments = array(); 
  110.  
  111. $i = -1; 
  112. $prevCode = 0xFFFF; 
  113. $prevGid = 0xFFFF; 
  114.  
  115. foreach($newGlyphIndexArray as $code => $gid) { 
  116. if ( 
  117. $prevCode + 1 != $code || 
  118. $prevGid + 1 != $gid 
  119. ) { 
  120. $i++; 
  121. $segments[$i] = array(); 
  122.  
  123. $segments[$i][] = array($code, $gid); 
  124.  
  125. $prevCode = $code; 
  126. $prevGid = $gid; 
  127.  
  128. $segments[][] = array(0xFFFF, 0xFFFF); 
  129.  
  130. $startCode = array(); 
  131. $endCode = array(); 
  132. $idDelta = array(); 
  133.  
  134. foreach($segments as $codes) { 
  135. $start = reset($codes); 
  136. $end = end($codes); 
  137.  
  138. $startCode[] = $start[0]; 
  139. $endCode[] = $end[0]; 
  140. $idDelta[] = $start[1] - $start[0]; 
  141.  
  142. $segCount = count($startCode); 
  143. $idRangeOffset = array_fill(0, $segCount, 0); 
  144.  
  145. $searchRange = 1; 
  146. $entrySelector = 0; 
  147. while ($searchRange * 2 <= $segCount) { 
  148. $searchRange *= 2; 
  149. $entrySelector++; 
  150. $searchRange *= 2; 
  151. $rangeShift = $segCount * 2 - $searchRange; 
  152.  
  153. $subtables = array( 
  154. array( 
  155. // header 
  156. "platformID" => 3, // Unicode 
  157. "platformSpecificID" => 1,  
  158. "offset" => null,  
  159.  
  160. // subtable 
  161. "format" => 4,  
  162. "length" => null,  
  163. "language" => 0,  
  164. "segCount" => $segCount,  
  165. "segCountX2" => $segCount * 2,  
  166. "searchRange" => $searchRange,  
  167. "entrySelector" => $entrySelector,  
  168. "rangeShift" => $rangeShift,  
  169. "startCode" => $startCode,  
  170. "endCode" => $endCode,  
  171. "idDelta" => $idDelta,  
  172. "idRangeOffset" => $idRangeOffset,  
  173. "glyphIndexArray" => $newGlyphIndexArray,  
  174. ); 
  175.  
  176. $data = array( 
  177. "version" => 0,  
  178. "numberSubtables" => count($subtables),  
  179. "subtables" => $subtables,  
  180. ); 
  181.  
  182. $length = $font->pack(self::$header_format, $data); 
  183.  
  184. $subtable_headers_size = $data["numberSubtables"] * 8; // size of self::$subtable_header_format 
  185. $subtable_headers_offset = $font->pos(); 
  186.  
  187. $length += $font->write(str_repeat("\0", $subtable_headers_size), $subtable_headers_size); 
  188.  
  189. // write subtables data 
  190. foreach($data["subtables"] as $i => $subtable) { 
  191. $length_before = $length; 
  192. $data["subtables"][$i]["offset"] = $length; 
  193.  
  194. $length += $font->writeUInt16($subtable["format"]); 
  195.  
  196. $before_subheader = $font->pos(); 
  197. $length += $font->pack(self::$subtable_v4_format, $subtable); 
  198.  
  199. $segCount = $subtable["segCount"]; 
  200. $length += $font->w(array(self::uint16, $segCount), $subtable["endCode"]); 
  201. $length += $font->writeUInt16(0); // reservedPad 
  202. $length += $font->w(array(self::uint16, $segCount), $subtable["startCode"]); 
  203. $length += $font->w(array(self::int16, $segCount), $subtable["idDelta"]); 
  204. $length += $font->w(array(self::uint16, $segCount), $subtable["idRangeOffset"]); 
  205. $length += $font->w(array(self::uint16, $segCount), array_values($subtable["glyphIndexArray"])); 
  206.  
  207. $after_subtable = $font->pos(); 
  208.  
  209. $subtable["length"] = $length - $length_before; 
  210. $font->seek($before_subheader); 
  211. $length += $font->pack(self::$subtable_v4_format, $subtable); 
  212.  
  213. $font->seek($after_subtable); 
  214.  
  215. // write subtables headers 
  216. $font->seek($subtable_headers_offset); 
  217. foreach($data["subtables"] as $subtable) { 
  218. $font->pack(self::$subtable_header_format, $subtable); 
  219.  
  220. return $length;