commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / vendor / phenx / php-font-lib / src / FontLib / Table / Type / cmap.php
1 <?php
2 /**
3 * @package php-font-lib
4 * @link https://github.com/PhenX/php-font-lib
5 * @author Fabien Ménager <fabien.menager@gmail.com>
6 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
7 */
8
9 namespace FontLib\Table\Type;
10 use FontLib\Table\Table;
11
12 /**
13 * `cmap` font table.
14 *
15 * @package php-font-lib
16 */
17 class cmap extends Table {
18 private static $header_format = array(
19 "version" => self::uint16,
20 "numberSubtables" => self::uint16,
21 );
22
23 private static $subtable_header_format = array(
24 "platformID" => self::uint16,
25 "platformSpecificID" => self::uint16,
26 "offset" => self::uint32,
27 );
28
29 private static $subtable_v4_format = array(
30 "length" => self::uint16,
31 "language" => self::uint16,
32 "segCountX2" => self::uint16,
33 "searchRange" => self::uint16,
34 "entrySelector" => self::uint16,
35 "rangeShift" => self::uint16,
36 );
37
38 protected function _parse() {
39 $font = $this->getFont();
40
41 $cmap_offset = $font->pos();
42
43 $data = $font->unpack(self::$header_format);
44
45 $subtables = array();
46 for ($i = 0; $i < $data["numberSubtables"]; $i++) {
47 $subtables[] = $font->unpack(self::$subtable_header_format);
48 }
49 $data["subtables"] = $subtables;
50
51 foreach ($data["subtables"] as $i => &$subtable) {
52 $font->seek($cmap_offset + $subtable["offset"]);
53
54 $subtable["format"] = $font->readUInt16();
55
56 // @todo Only CMAP version 4
57 if ($subtable["format"] != 4) {
58 unset($data["subtables"][$i]);
59 $data["numberSubtables"]--;
60 continue;
61 }
62
63 $subtable += $font->unpack(self::$subtable_v4_format);
64 $segCount = $subtable["segCountX2"] / 2;
65 $subtable["segCount"] = $segCount;
66
67 $endCode = $font->r(array(self::uint16, $segCount));
68
69 $font->readUInt16(); // reservedPad
70
71 $startCode = $font->r(array(self::uint16, $segCount));
72 $idDelta = $font->r(array(self::int16, $segCount));
73
74 $ro_start = $font->pos();
75 $idRangeOffset = $font->r(array(self::uint16, $segCount));
76
77 $glyphIndexArray = array();
78 for ($i = 0; $i < $segCount; $i++) {
79 $c1 = $startCode[$i];
80 $c2 = $endCode[$i];
81 $d = $idDelta[$i];
82 $ro = $idRangeOffset[$i];
83
84 if ($ro > 0) {
85 $font->seek($subtable["offset"] + 2 * $i + $ro);
86 }
87
88 for ($c = $c1; $c <= $c2; $c++) {
89 if ($ro == 0) {
90 $gid = ($c + $d) & 0xFFFF;
91 }
92 else {
93 $offset = ($c - $c1) * 2 + $ro;
94 $offset = $ro_start + 2 * $i + $offset;
95
96 $font->seek($offset);
97 $gid = $font->readUInt16();
98
99 if ($gid != 0) {
100 $gid = ($gid + $d) & 0xFFFF;
101 }
102 }
103
104 if ($gid > 0) {
105 $glyphIndexArray[$c] = $gid;
106 }
107 }
108 }
109
110 $subtable += array(
111 "endCode" => $endCode,
112 "startCode" => $startCode,
113 "idDelta" => $idDelta,
114 "idRangeOffset" => $idRangeOffset,
115 "glyphIndexArray" => $glyphIndexArray,
116 );
117 }
118
119 $this->data = $data;
120 }
121
122 function _encode() {
123 $font = $this->getFont();
124
125 $subset = $font->getSubset();
126 $glyphIndexArray = $font->getUnicodeCharMap();
127
128 $newGlyphIndexArray = array();
129 foreach ($glyphIndexArray as $code => $gid) {
130 $new_gid = array_search($gid, $subset);
131 if ($new_gid !== false) {
132 $newGlyphIndexArray[$code] = $new_gid;
133 }
134 }
135
136 ksort($newGlyphIndexArray); // Sort by char code
137
138 $segments = array();
139
140 $i = -1;
141 $prevCode = 0xFFFF;
142 $prevGid = 0xFFFF;
143
144 foreach ($newGlyphIndexArray as $code => $gid) {
145 if (
146 $prevCode + 1 != $code ||
147 $prevGid + 1 != $gid
148 ) {
149 $i++;
150 $segments[$i] = array();
151 }
152
153 $segments[$i][] = array($code, $gid);
154
155 $prevCode = $code;
156 $prevGid = $gid;
157 }
158
159 $segments[][] = array(0xFFFF, 0xFFFF);
160
161 $startCode = array();
162 $endCode = array();
163 $idDelta = array();
164
165 foreach ($segments as $codes) {
166 $start = reset($codes);
167 $end = end($codes);
168
169 $startCode[] = $start[0];
170 $endCode[] = $end[0];
171 $idDelta[] = $start[1] - $start[0];
172 }
173
174 $segCount = count($startCode);
175 $idRangeOffset = array_fill(0, $segCount, 0);
176
177 $searchRange = 1;
178 $entrySelector = 0;
179 while ($searchRange * 2 <= $segCount) {
180 $searchRange *= 2;
181 $entrySelector++;
182 }
183 $searchRange *= 2;
184 $rangeShift = $segCount * 2 - $searchRange;
185
186 $subtables = array(
187 array(
188 // header
189 "platformID" => 3, // Unicode
190 "platformSpecificID" => 1,
191 "offset" => null,
192
193 // subtable
194 "format" => 4,
195 "length" => null,
196 "language" => 0,
197 "segCount" => $segCount,
198 "segCountX2" => $segCount * 2,
199 "searchRange" => $searchRange,
200 "entrySelector" => $entrySelector,
201 "rangeShift" => $rangeShift,
202 "startCode" => $startCode,
203 "endCode" => $endCode,
204 "idDelta" => $idDelta,
205 "idRangeOffset" => $idRangeOffset,
206 "glyphIndexArray" => $newGlyphIndexArray,
207 )
208 );
209
210 $data = array(
211 "version" => 0,
212 "numberSubtables" => count($subtables),
213 "subtables" => $subtables,
214 );
215
216 $length = $font->pack(self::$header_format, $data);
217
218 $subtable_headers_size = $data["numberSubtables"] * 8; // size of self::$subtable_header_format
219 $subtable_headers_offset = $font->pos();
220
221 $length += $font->write(str_repeat("\0", $subtable_headers_size), $subtable_headers_size);
222
223 // write subtables data
224 foreach ($data["subtables"] as $i => $subtable) {
225 $length_before = $length;
226 $data["subtables"][$i]["offset"] = $length;
227
228 $length += $font->writeUInt16($subtable["format"]);
229
230 $before_subheader = $font->pos();
231 $length += $font->pack(self::$subtable_v4_format, $subtable);
232
233 $segCount = $subtable["segCount"];
234 $length += $font->w(array(self::uint16, $segCount), $subtable["endCode"]);
235 $length += $font->writeUInt16(0); // reservedPad
236 $length += $font->w(array(self::uint16, $segCount), $subtable["startCode"]);
237 $length += $font->w(array(self::int16, $segCount), $subtable["idDelta"]);
238 $length += $font->w(array(self::uint16, $segCount), $subtable["idRangeOffset"]);
239 $length += $font->w(array(self::uint16, $segCount), array_values($subtable["glyphIndexArray"]));
240
241 $after_subtable = $font->pos();
242
243 $subtable["length"] = $length - $length_before;
244 $font->seek($before_subheader);
245 $length += $font->pack(self::$subtable_v4_format, $subtable);
246
247 $font->seek($after_subtable);
248 }
249
250 // write subtables headers
251 $font->seek($subtable_headers_offset);
252 foreach ($data["subtables"] as $subtable) {
253 $font->pack(self::$subtable_header_format, $subtable);
254 }
255
256 return $length;
257 }
258 }