PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 2.4.6
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v2.4.6
trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 All 71 releases
pdf-print / mpdf / classes / sea.php

sea.php in PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin 2.4.6, at mpdf/classes/sea.php

384 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class SEA
4 {
5 // South East Asian shaper
6 // sea_category
7 const OT_X = 0;
8
9 const OT_C = 1;
10
11 const OT_IV = 2; # Independent Vowel
12
13 const OT_T = 3; # Tone Marks
14
15 const OT_H = 4; # Halant
16
17 const OT_A = 10; # Anusvara
18
19 const OT_GB = 12; # Generic Base (OT_DOTTEDCIRCLE in Indic)
20
21 const OT_CM = 17; # Consonant Medial
22
23 const OT_MR = 22; # Medial Ra
24
25 const OT_VAbv = 26;
26
27 const OT_VBlw = 27;
28
29 const OT_VPre = 28;
30
31 const OT_VPst = 29;
32
33 // ? From Indic categories
34 const OT_ZWNJ = 5;
35
36 const OT_ZWJ = 6;
37
38 const OT_M = 7;
39
40 const OT_SM = 8;
41
42 const OT_VD = 9;
43
44 const OT_NBSP = 11;
45
46 const OT_RS = 13;
47
48 const OT_Coeng = 14;
49
50 const OT_Repha = 15;
51
52 const OT_Ra = 16;
53
54 // Based on sea_category used to make string to find syllables
55 // OT_ to string character (using e.g. OT_C from INDIC) hb-ot-shape-complex-sea-private.hh
56 public static $sea_category_char = array(
57 'x',
58 'C',
59 'V',
60 'T',
61 'H',
62 'x',
63 'x',
64 'x',
65 'x',
66 'x',
67 'A',
68 'x',
69 'G',
70 'x',
71 'x',
72 'x',
73 'x',
74 'M',
75 'x',
76 'x',
77 'x',
78 'x',
79 'R',
80 'x',
81 'x',
82 'x',
83 'a',
84 'b',
85 'p',
86 't',
87 );
88
89 /* Visual positions in a syllable from left to right. */
90 // sea_position
91 const POS_START = 0;
92
93 const POS_RA_TO_BECOME_REPH = 1;
94
95 const POS_PRE_M = 2;
96
97 const POS_PRE_C = 3;
98
99 const POS_BASE_C = 4;
100
101 const POS_AFTER_MAIN = 5;
102
103 const POS_ABOVE_C = 6;
104
105 const POS_BEFORE_SUB = 7;
106
107 const POS_BELOW_C = 8;
108
109 const POS_AFTER_SUB = 9;
110
111 const POS_BEFORE_POST = 10;
112
113 const POS_POST_C = 11;
114
115 const POS_AFTER_POST = 12;
116
117 const POS_FINAL_C = 13;
118
119 const POS_SMVD = 14;
120
121 const POS_END = 15;
122
123 public static function set_sea_properties(&$info, $scriptblock)
124 {
125 $u = $info['uni'];
126 $type = self::sea_get_categories($u);
127 $cat = ($type & 0x7F);
128 $pos = ($type >> 8);
129
130 /*
131 * Re-assign category
132 */
133 // Medial Ra
134 if ($u == 0x1A55 || $u == 0xAA34) {
135 $cat = self::OT_MR;
136 }
137
138 /*
139 * Re-assign position.
140 */
141 if ($cat == self::OT_M) { // definitely "OT_M" in HarfBuzz - although this does not seem to have been defined ? should be OT_MR
142 switch ($pos) {
143 case self::POS_PRE_C: $cat = self::OT_VPre;
144 break;
145 case self::POS_ABOVE_C: $cat = self::OT_VAbv;
146 break;
147 case self::POS_BELOW_C: $cat = self::OT_VBlw;
148 break;
149 case self::POS_POST_C: $cat = self::OT_VPst;
150 break;
151 }
152 }
153
154 $info['sea_category'] = $cat;
155 $info['sea_position'] = $pos;
156 }
157
158 // syllable_type
159 const CONSONANT_SYLLABLE = 0;
160
161 const BROKEN_CLUSTER = 1;
162
163 const NON_SEA_CLUSTER = 2;
164
165 public static function set_syllables(&$o, $s, &$broken_syllables)
166 {
167 $ptr = 0;
168 $syllable_serial = 1;
169 $broken_syllables = false;
170 while ($ptr < strlen($s)) {
171 $match = '';
172 $syllable_length = 1;
173 $syllable_type = self::NON_SEA_CLUSTER;
174
175 // CONSONANT_SYLLABLE Consonant syllable
176 if (preg_match('/^(C|V|G)(p|a|b|t|HC|M|R|T|A)*/', substr($s, $ptr), $ma)) {
177 $syllable_length = strlen($ma[0]);
178 $syllable_type = self::CONSONANT_SYLLABLE;
179 }
180 // BROKEN_CLUSTER syllable
181 else if (preg_match('/^(p|a|b|t|HC|M|R|T|A)+/', substr($s, $ptr), $ma)) {
182 $syllable_length = strlen($ma[0]);
183 $syllable_type = self::BROKEN_CLUSTER;
184 $broken_syllables = true;
185 }
186
187 for ($i = $ptr; $i < $ptr + $syllable_length; $i++) {
188 $o[$i]['syllable'] = ($syllable_serial << 4) | $syllable_type;
189 }
190 $ptr += $syllable_length;
191 $syllable_serial++;
192 if ($syllable_serial == 16)
193 $syllable_serial = 1;
194 }
195 }
196
197 public static function initial_reordering(&$info, $GSUBdata, $broken_syllables, $scriptblock, $dottedcircle)
198 {
199
200 if ($broken_syllables && $dottedcircle) {
201 self::insert_dotted_circles($info, $dottedcircle);
202 }
203
204 $count = count($info);
205 if (!$count)
206 return;
207 $last = 0;
208 $last_syllable = $info[0]['syllable'];
209 for ($i = 1; $i < $count; $i++) {
210 if ($last_syllable != $info[$i]['syllable']) {
211 self::initial_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $i);
212 $last = $i;
213 $last_syllable = $info[$last]['syllable'];
214 }
215 }
216 self::initial_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $count);
217 }
218
219 public static function insert_dotted_circles(&$info, $dottedcircle)
220 {
221 $idx = 0;
222 $last_syllable = 0;
223 while ($idx < count($info)) {
224 $syllable = $info[$idx]['syllable'];
225 $syllable_type = ($syllable & 0x0F);
226 if ($last_syllable != $syllable && $syllable_type == self::BROKEN_CLUSTER) {
227 $last_syllable = $syllable;
228 $dottedcircle[0]['syllable'] = $info[$idx]['syllable'];
229 array_splice($info, $idx, 0, $dottedcircle);
230 } else
231 $idx++;
232 }
233 }
234
235 public static function initial_reordering_syllable(&$info, $GSUBdata, $scriptblock, $start, $end)
236 {
237 /* broken_cluster: We already inserted dotted-circles, so just call the standalone_cluster. */
238
239 $syllable_type = ($info[$start]['syllable'] & 0x0F);
240 if ($syllable_type == self::NON_SEA_CLUSTER) {
241 return;
242 }
243 if ($syllable_type == self::BROKEN_CLUSTER) {
244 /* For dotted-circle, this is what Uniscribe does:
245 * If dotted-circle is the last glyph, it just does nothing. */
246 if ($info[$end - 1]['sea_category'] == self::OT_GB) {
247 return;
248 }
249 }
250
251 $base = $start;
252 $i = $start;
253 for (; $i < $base; $i++)
254 $info[$i]['sea_position'] = self::POS_PRE_C;
255 if ($i < $end) {
256 $info[$i]['sea_position'] = self::POS_BASE_C;
257 $i++;
258 }
259 for (; $i < $end; $i++) {
260 if (isset($info[$i]['sea_category']) && $info[$i]['sea_category'] == self::OT_MR) { /* Pre-base reordering */
261 $info[$i]['sea_position'] = self::POS_PRE_C;
262 continue;
263 }
264 if (isset($info[$i]['sea_category']) && $info[$i]['sea_category'] == self::OT_VPre) { /* Left matra */
265 $info[$i]['sea_position'] = self::POS_PRE_M;
266 continue;
267 }
268 $info[$i]['sea_position'] = self::POS_AFTER_MAIN;
269 }
270
271 /* Sit tight, rock 'n roll! */
272 self::bubble_sort($info, $start, $end - $start);
273 }
274
275 public static function final_reordering(&$info, $GSUBdata, $scriptblock)
276 {
277 $count = count($info);
278 if (!$count)
279 return;
280 $last = 0;
281 $last_syllable = $info[0]['syllable'];
282 for ($i = 1; $i < $count; $i++) {
283 if ($last_syllable != $info[$i]['syllable']) {
284 self::final_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $i);
285 $last = $i;
286 $last_syllable = $info[$last]['syllable'];
287 }
288 }
289 self::final_reordering_syllable($info, $GSUBdata, $scriptblock, $last, $count);
290 }
291
292 public static function final_reordering_syllable(&$info, $GSUBdata, $scriptblock, $start, $end)
293 {
294 /*
295 * Nothing to do here at present!
296 */
297 }
298
299 public static $sea_table = array(
300 /* New Tai Lue (1980..19DF) */
301
302 /* 1980 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
303 /* 1988 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
304 /* 1990 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
305 /* 1998 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
306 /* 19A0 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
307 /* 19A8 */ 3841, 3841, 3841, 3841, 3840, 3840, 3840, 3840,
308 /* 19B0 */ 2823, 2823, 2823, 2823, 2823, 775, 775, 775,
309 /* 19B8 */ 2823, 2823, 775, 2823, 2823, 2823, 2823, 2823,
310 /* 19C0 */ 2823, 3857, 3857, 3857, 3857, 3857, 3857, 3857,
311 /* 19C8 */ 3843, 3843, 3840, 3840, 3840, 3840, 3840, 3840,
312 /* 19D0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
313 /* 19D8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
314 /* Tai Tham (1A20..1AAF) */
315
316 /* 1A20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
317 /* 1A28 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
318 /* 1A30 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
319 /* 1A38 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
320 /* 1A40 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
321 /* 1A48 */ 3841, 3841, 3841, 3841, 3841, 3842, 3842, 3842,
322 /* 1A50 */ 3842, 3842, 3842, 3841, 3841, 3857, 3857, 3857,
323 /* 1A58 */ 3857, 3857, 3857, 3857, 3857, 3857, 3857, 3840,
324 /* 1A60 */ 3844, 2823, 1543, 2823, 2823, 1543, 1543, 1543,
325 /* 1A68 */ 1543, 2055, 2055, 1543, 2055, 2823, 775, 775,
326 /* 1A70 */ 775, 775, 775, 1543, 1543, 3843, 3843, 3843,
327 /* 1A78 */ 3843, 3843, 3840, 3840, 3840, 3840, 3840, 3840,
328 /* 1A80 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
329 /* 1A88 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
330 /* 1A90 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
331 /* 1A98 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
332 /* 1AA0 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
333 /* 1AA8 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
334 /* Cham (AA00..AA5F) */
335
336 /* AA00 */ 3842, 3842, 3842, 3842, 3842, 3842, 3841, 3841,
337 /* AA08 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
338 /* AA10 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
339 /* AA18 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
340 /* AA20 */ 3841, 3841, 3841, 3841, 3841, 3841, 3841, 3841,
341 /* AA28 */ 3841, 1543, 1543, 1543, 1543, 2055, 1543, 775,
342 /* AA30 */ 775, 1543, 2055, 3857, 3857, 3857, 3857, 3840,
343 /* AA38 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
344 /* AA40 */ 3857, 3857, 3857, 3857, 3857, 3857, 3857, 3857,
345 /* AA48 */ 3857, 3857, 3857, 3857, 3857, 3857, 3840, 3840,
346 /* AA50 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
347 /* AA58 */ 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840,
348 );
349
350 public static function sea_get_categories($u)
351 {
352 if (0x1980 <= $u && $u <= 0x19DF)
353 return self::$sea_table[$u - 0x1980]; // offset 0 for New Tai Lue
354 if (0x1A20 <= $u && $u <= 0x1AAF)
355 return self::$sea_table[$u - 0x1A20 + 96]; // offset for Tai Tham
356 if (0xAA00 <= $u && $u <= 0xAA5F)
357 return self::$sea_table[$u - 0xAA00 + 96 + 144]; // Cham
358 if ($u == 0x00A0)
359 return 3851; // (ISC_CP | (IMC_x << 8))
360 if ($u == 0x25CC)
361 return 3851; // (ISC_CP | (IMC_x << 8))
362 return 3840; // (ISC_x | (IMC_x << 8))
363 }
364
365 public static function bubble_sort(&$arr, $start, $len)
366 {
367 if ($len < 2) {
368 return;
369 }
370 $k = $start + $len - 2;
371 while ($k >= $start) {
372 for ($j = $start; $j <= $k; $j++) {
373 if ($arr[$j]['sea_position'] > $arr[$j + 1]['sea_position']) {
374 $t = $arr[$j];
375 $arr[$j] = $arr[$j + 1];
376 $arr[$j + 1] = $t;
377 }
378 }
379 $k--;
380 }
381 }
382
383 }
384