1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** Utility (Utility) */
19 /** */
20 /**************************************************************************/
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_utility.h"
28 #include "gx_system.h"
29
30 #if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
31 #if defined(GX_DYNAMIC_ARABIC_SHAPING_SUPPORT)
32 /* Define joining types. */
33 #define JOINING_TYPE_NONE 0x01
34 #define JOINING_TYPE_RIGHT 0x02
35 #define JOINING_TYPE_LEFT 0x03
36 #define JOINING_TYPE_DUAL 0x04
37 #define JOINING_TYPE_CAUSING 0x05
38 #define JOINING_TYPE_TRANSPARENT 0x06
39
40 #define ARABIC_FORM_ISOLATED 0x01
41 #define ARABIC_FORM_INITIAL 0x02
42 #define ARABIC_FORM_FINAL 0x03
43 #define ARABIC_FORM_MEDIAL 0x04
44
45 typedef struct ARABIC_SHAPING_STRUCT
46 {
47 ULONG range_start;
48 ULONG range_end;
49 ULONG joining_type;
50 } ARABIC_SHAPING;
51
52 typedef struct ARABIC_FORM_STRUCT
53 {
54 ULONG code_point;
55 ULONG isolated;
56 ULONG final;
57 ULONG initial;
58 ULONG medial;
59 } ARABIC_FORM;
60
61 typedef struct ARABIC_LIGATURE_STRICT
62 {
63 ULONG alef;
64 ULONG lam;
65 ULONG ligature;
66 } ARABIC_LIGATURE;
67
68 typedef struct ARABIC_UNIT_STRUCT
69 {
70 ULONG code_point;
71 ULONG joining_type;
72 ULONG shape_form;
73 } ARABIC_UNIT;
74
75 static ARABIC_SHAPING arabic_shaping_table[] = {
76 {0x0600, 0x060F, JOINING_TYPE_NONE},
77 {0x0610, 0x061A, JOINING_TYPE_TRANSPARENT},
78 {0x061B, 0x061B, JOINING_TYPE_NONE},
79 {0x061C, 0x061C, JOINING_TYPE_TRANSPARENT},
80 {0x061B, 0x061F, JOINING_TYPE_NONE},
81 {0x0620, 0x0620, JOINING_TYPE_DUAL},
82 {0x0621, 0x0621, JOINING_TYPE_NONE},
83 {0x0622, 0x0625, JOINING_TYPE_RIGHT},
84 {0x0626, 0x0626, JOINING_TYPE_DUAL},
85 {0x0627, 0x0627, JOINING_TYPE_RIGHT},
86 {0x0628, 0x0628, JOINING_TYPE_DUAL},
87 {0x0629, 0x0629, JOINING_TYPE_RIGHT},
88 {0x062A, 0x062E, JOINING_TYPE_DUAL},
89 {0x062F, 0x0632, JOINING_TYPE_RIGHT},
90 {0x0633, 0x063F, JOINING_TYPE_DUAL},
91 {0x0640, 0x0640, JOINING_TYPE_CAUSING},
92 {0x0641, 0x0647, JOINING_TYPE_DUAL},
93 {0x0648, 0x0648, JOINING_TYPE_RIGHT},
94 {0x0649, 0x064A, JOINING_TYPE_DUAL},
95 {0x064B, 0x065F, JOINING_TYPE_TRANSPARENT},
96 {0x0660, 0x066D, JOINING_TYPE_NONE},
97 {0x066E, 0x066F, JOINING_TYPE_DUAL},
98 {0x0670, 0x0670, JOINING_TYPE_TRANSPARENT},
99 {0x0671, 0x0673, JOINING_TYPE_RIGHT},
100 {0x0674, 0x0674, JOINING_TYPE_NONE},
101 {0x0675, 0x0677, JOINING_TYPE_RIGHT},
102 {0x0678, 0x0687, JOINING_TYPE_DUAL},
103 {0x0688, 0x0699, JOINING_TYPE_RIGHT},
104 {0x069A, 0x06BF, JOINING_TYPE_DUAL},
105 {0x06C0, 0x06C0, JOINING_TYPE_RIGHT},
106 {0x06C1, 0x06C2, JOINING_TYPE_DUAL},
107 {0x06C3, 0x06CB, JOINING_TYPE_RIGHT},
108 {0x06CC, 0x06CC, JOINING_TYPE_DUAL},
109 {0x06CD, 0x06CD, JOINING_TYPE_RIGHT},
110 {0x06CE, 0x06CE, JOINING_TYPE_DUAL},
111 {0x06CF, 0x06CF, JOINING_TYPE_RIGHT},
112 {0x06D0, 0x06D1, JOINING_TYPE_DUAL},
113 {0x06D2, 0x06D3, JOINING_TYPE_RIGHT},
114 {0x06D4, 0x06D4, JOINING_TYPE_NONE},
115 {0x06D5, 0x06D5, JOINING_TYPE_RIGHT},
116 {0x06D6, 0x06DC, JOINING_TYPE_TRANSPARENT},
117 {0x06DD, 0x06DD, JOINING_TYPE_NONE},
118 {0x06DF, 0x06E4, JOINING_TYPE_TRANSPARENT},
119 {0x06E5, 0x06E6, JOINING_TYPE_NONE},
120 {0x06E7, 0x06E8, JOINING_TYPE_TRANSPARENT},
121 {0x06E9, 0x06E9, JOINING_TYPE_NONE},
122 {0x06EA, 0x06ED, JOINING_TYPE_TRANSPARENT},
123 {0x06EE, 0x06EF, JOINING_TYPE_RIGHT},
124 {0x06FA, 0x06FC, JOINING_TYPE_DUAL},
125 {0x06FF, 0x06FF, JOINING_TYPE_DUAL},
126 {0, 0, 0}
127 };
128
129 static ARABIC_FORM arabic_form_table_b[] = {
130 /* code, isolated, final, initial, medial */
131 {0x0621, 0xFE80, 0xFE80, 0xFE80, 0xFE80}, /* HAMZA 0x0621*/
132 {0x0622, 0xFE81, 0xFE82, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE 0x622 */
133 {0x0623, 0xFE83, 0xFE84, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE 0x0623*/
134 {0x0624, 0xFE85, 0xFE86, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE 0x0624 */
135 {0x0625, 0xFE87, 0xFE88, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW 0x0625*/
136 {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE 0x0626*/
137 {0x0627, 0xFE8D, 0xFE8E, 0xFE8D, 0xFE8E}, /* ALEF 0x0627*/
138 {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH 0x0628*/
139 {0x0629, 0xFE93, 0xFE94, 0xFE93, 0xFE94}, /* TEH MARBUTA 0x0629*/
140 {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH 0x062A*/
141 {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH 0x062B*/
142 {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM 0x062C*/
143 {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH 0x062D*/
144 {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH 0x062E*/
145 {0x062F, 0xFEA9, 0xFEAA, 0xFEA9, 0xFEAA}, /* DAL 0x062F*/
146 {0x0630, 0xFEAB, 0xFEAC, 0xFEAB, 0xFEAC}, /* THAL0x0630 */
147 {0x0631, 0xFEAD, 0xFEAE, 0xFEAD, 0xFEAE}, /* RAA 0x0631*/
148 {0x0632, 0xFEAF, 0xFEB0, 0xFEAF, 0xFEB0}, /* ZAIN 0x0632*/
149 {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN 0x0633*/
150 {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN 0x0634*/
151 {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD 0x0635*/
152 {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD 0x0636*/
153 {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH 0x0637*/
154 {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH 0x0638*/
155 {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN 0x0639*/
156 {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN 0x063A*/
157 {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FAA 0x0641*/
158 {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF 0x0642*/
159 {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF 0x0643*/
160 {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM 0x0644*/
161 {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM 0x0645*/
162 {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON 0x0646*/
163 {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH 0x0647*/
164 {0x0648, 0xFEED, 0xFEEE, 0xFEED, 0xFEEE}, /* WAW 0x0648*/
165 {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA 0x0649*/
166 {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH 0x064A*/
167 {0, 0, 0, 0, 0}
168 };
169
170 static ARABIC_FORM arabic_form_table_a[] = {
171 {0x0671, 0xFB50, 0xFB51, 0xFB50, 0xFB51}, /* Alef Wasla */
172 {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB89}, /* Tteh */
173 {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* Tteheh */
174 {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* Beeh */
175 {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* Peh */
176 {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* Teheh */
177 {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* Beheh */
178 {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* Nyeh */
179 {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* Dyeh */
180 {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* Tcheh */
181 {0x0688, 0xFB88, 0xFB89, 0xFB88, 0xFB89}, /* Ddal */
182 {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* Tcheheh */
183 {0x068D, 0xFB82, 0xFB83, 0xFB82, 0xFB83}, /* Ddahal */
184 {0x068E, 0xFB86, 0xFB87, 0xFB86, 0xFB87}, /* Dul */
185 {0x0691, 0xFB8C, 0xFB8D, 0xFB8C, 0xFB8D}, /* Rreh */
186 {0x0698, 0xFB8A, 0xFB8B, 0xFB8A, 0xFB8B}, /* Jeh */
187 {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* Veh */
188 {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* Peheh */
189 {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* Keheh */
190 {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* Ng */
191 {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* Gaf */
192 {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* Ngoeh */
193 {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* Gueh */
194 {0x06BA, 0xFB9E, 0xFB9F, 0xFB9E, 0xFB9F}, /* Noon Ghunna */
195 {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* Rnoon */
196 {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* Heh Doachashmee */
197 {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* Heh Goal */
198 {0x06C5, 0xFBE0, 0xFBE1, 0xFBE0, 0xFBE1}, /* Kirghiz Oe */
199 {0x06C6, 0xFBD9, 0xFBDA, 0xFBD9, 0xFBDA}, /* Oe */
200 {0x06C7, 0xFBD7, 0xFBD8, 0xFBD7, 0xFBD8}, /* U */
201 {0x06C8, 0xFBDB, 0xFBDC, 0xFBDB, 0xFBDC}, /* Yu */
202 {0x06C9, 0xFBE2, 0xFBE3, 0xFBE2, 0xFBE3}, /* Kirghiz Yu */
203 {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* Farsi Yeh */
204 {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
205 {0x06CB, 0xFBDE, 0xFBDF, 0xFBDE, 0xFBDF}, /* Ve */
206 {0x06D2, 0xFBAE, 0xFBAF, 0xFBAE, 0xFBAF}, /* Yeh Barree */
207 {0x06D3, 0xFBB0, 0xFBB1, 0xFBB0, 0xFBB1} /* Yeh Barree with Hamza Above */
208 };
209
210 static ARABIC_LIGATURE arabic_ligature_table[] =
211 {
212 /*alef, lam, (lam-alef) */
213 {0xFE82, 0xFEDF, 0xFEF5}, /* Arabic Ligature Lam with Alef with Madda Above Isolated Form */
214 {0xFE82, 0xFEE0, 0xFEF6}, /* Arabic Ligature Lam with Alef with Madda Above Final Form */
215 {0xFE84, 0xFEDF, 0xFEF7}, /* Arabic Ligature Lam with Alef with Hamza Above Isolated Form */
216 {0xFE84, 0xFEE0, 0xFEF8}, /* Arabic Ligature Lam with Alef with Hamza Above Final Form */
217 {0xFE88, 0xFEDF, 0xFEF9}, /* Arabic Ligature Lam with Alef with Hamza Below Isolated Form */
218 {0xFE88, 0xFEE0, 0xFEFA}, /* Arabic Ligature Lam with Alef with Hamza Below Final Form */
219 {0xFE8E, 0xFEDF, 0xFEFB}, /* Arabic Ligature Lam with Alef Isolated Form */
220 {0xFE8E, 0xFEE0, 0xFEFC}, /* Arabic Ligature Lam with Alef Final Form */
221 {0, 0, 0}
222 };
223
224 /**************************************************************************/
225 /* */
226 /* FUNCTION RELEASE */
227 /* */
228 /* _gx_utility_bidi_arabic_joining_type_get PORTABLE C */
229 /* 6.1 */
230 /* AUTHOR */
231 /* */
232 /* Kenneth Maxwell, Microsoft Corporation */
233 /* */
234 /* DESCRIPTION */
235 /* */
236 /* This function returns join type of sepecified unicode. */
237 /* */
238 /* INPUT */
239 /* */
240 /* code_point Code point */
241 /* */
242 /* OUTPUT */
243 /* */
244 /* joining type */
245 /* */
246 /* CALLS */
247 /* */
248 /* None */
249 /* */
250 /* CALLED BY */
251 /* */
252 /* _gx_utility_bidi_arabic_shaping */
253 /* */
254 /* RELEASE HISTORY */
255 /* */
256 /* DATE NAME DESCRIPTION */
257 /* */
258 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
259 /* */
260 /**************************************************************************/
_gx_utility_bidi_arabic_joining_type_get(ULONG code_point)261 static UINT _gx_utility_bidi_arabic_joining_type_get(ULONG code_point)
262 {
263 ARABIC_SHAPING *shaping = arabic_shaping_table;
264
265 if (code_point >= 0x0600 && code_point <= 0x06FF)
266 {
267 /* Arabic. */
268 while (shaping -> range_start)
269 {
270 if ((code_point >= shaping -> range_start) &&
271 (code_point <= shaping -> range_end))
272 {
273 return shaping -> joining_type;
274 }
275 shaping++;
276 }
277 }
278
279 return JOINING_TYPE_NONE;
280 }
281
282 /**************************************************************************/
283 /* */
284 /* FUNCTION RELEASE */
285 /* */
286 /* _gx_utility_bidi_arabic_form_get PORTABLE C */
287 /* 6.1 */
288 /* AUTHOR */
289 /* */
290 /* Kenneth Maxwell, Microsoft Corporation */
291 /* */
292 /* DESCRIPTION */
293 /* */
294 /* This function gets Arabic shape form. */
295 /* */
296 /* INPUT */
297 /* */
298 /* code_point Code point */
299 /* form_type Joining type */
300 /* */
301 /* OUTPUT */
302 /* */
303 /* status Completion status */
304 /* */
305 /* CALLS */
306 /* */
307 /* None */
308 /* */
309 /* CALLED BY */
310 /* */
311 /* _gx_utility_bidi_arabic_shaping */
312 /* */
313 /* RELEASE HISTORY */
314 /* */
315 /* DATE NAME DESCRIPTION */
316 /* */
317 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
318 /* */
319 /**************************************************************************/
_gx_utility_bidi_arabic_form_get(ULONG code_point,UINT form_type)320 static ULONG _gx_utility_bidi_arabic_form_get(ULONG code_point, UINT form_type)
321 {
322 ARABIC_FORM *entry = GX_NULL;
323
324 if ((code_point) >= 0x0621 && (code_point <= 0x064A))
325 {
326 entry = arabic_form_table_b;
327 }
328 else if (code_point >= 0x0671 && code_point <= 0x06D3)
329 {
330 entry = arabic_form_table_a;
331 }
332
333 if (entry)
334 {
335 while (entry -> code_point)
336 {
337 if (entry -> code_point == code_point)
338 {
339 switch (form_type)
340 {
341 case ARABIC_FORM_ISOLATED:
342 return entry -> isolated;
343
344 case ARABIC_FORM_INITIAL:
345 return entry -> initial;
346
347 case ARABIC_FORM_FINAL:
348 return entry -> final;
349
350 case ARABIC_FORM_MEDIAL:
351 return entry -> medial;
352 }
353 }
354
355 entry++;
356 }
357 }
358
359 return code_point;
360 }
361 /**************************************************************************/
362 /* */
363 /* FUNCTION RELEASE */
364 /* */
365 /* _gx_utility_bidi_arabic_ligature_get PORTABLE C */
366 /* 6.1 */
367 /* AUTHOR */
368 /* */
369 /* Kenneth Maxwell, Microsoft Corporation */
370 /* */
371 /* DESCRIPTION */
372 /* */
373 /* This function retrieves Arabic ligature. */
374 /* */
375 /* INPUT */
376 /* */
377 /* alef Code of Arabic letter alef */
378 /* lam Code of Arabic letter lam */
379 /* */
380 /* OUTPUT */
381 /* */
382 /* status Completion status */
383 /* */
384 /* CALLS */
385 /* */
386 /* None */
387 /* */
388 /* CALLED BY */
389 /* */
390 /* _gx_utility_bidi_arabic_shaping */
391 /* */
392 /* RELEASE HISTORY */
393 /* */
394 /* DATE NAME DESCRIPTION */
395 /* */
396 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
397 /* */
398 /**************************************************************************/
_gx_utility_bidi_arabic_ligature_get(ULONG alef,ULONG lam)399 static ULONG _gx_utility_bidi_arabic_ligature_get(ULONG alef, ULONG lam)
400 {
401 ARABIC_LIGATURE *entry = arabic_ligature_table;
402
403 while (entry -> ligature)
404 {
405 if (entry -> alef == alef && entry -> lam == lam)
406 {
407 return entry -> ligature;
408 }
409 entry++;
410 }
411
412 return 0;
413 }
414
415 /**************************************************************************/
416 /* */
417 /* FUNCTION RELEASE */
418 /* */
419 /* _gx_utility_bidi_right_joining_causing_test PORTABLE C */
420 /* 6.1 */
421 /* AUTHOR */
422 /* */
423 /* Kenneth Maxwell, Microsoft Corporation */
424 /* */
425 /* DESCRIPTION */
426 /* */
427 /* This function tests if a join type is right joining causing. */
428 /* */
429 /* INPUT */
430 /* */
431 /* joining_type Joining type */
432 /* */
433 /* OUTPUT */
434 /* */
435 /* status Completion status */
436 /* */
437 /* CALLS */
438 /* */
439 /* None */
440 /* */
441 /* CALLED BY */
442 /* */
443 /* _gx_utility_bidi_arabic_shaping */
444 /* */
445 /* RELEASE HISTORY */
446 /* */
447 /* DATE NAME DESCRIPTION */
448 /* */
449 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
450 /* */
451 /**************************************************************************/
_gx_utility_bidi_right_joining_causing_test(UINT joining_type)452 static GX_BOOL _gx_utility_bidi_right_joining_causing_test(UINT joining_type)
453 {
454 switch (joining_type)
455 {
456 case JOINING_TYPE_DUAL:
457 case JOINING_TYPE_LEFT:
458 case JOINING_TYPE_CAUSING:
459 return GX_TRUE;
460 }
461
462 return GX_FALSE;
463 }
464
465 /**************************************************************************/
466 /* */
467 /* FUNCTION RELEASE */
468 /* */
469 /* _gx_utility_bidi_left_joining_causing_test PORTABLE C */
470 /* 6.1 */
471 /* AUTHOR */
472 /* */
473 /* Kenneth Maxwell, Microsoft Corporation */
474 /* */
475 /* DESCRIPTION */
476 /* */
477 /* This function tests if a joing type is left joining causing. */
478 /* */
479 /* INPUT */
480 /* */
481 /* joinint_type Joining type */
482 /* */
483 /* OUTPUT */
484 /* */
485 /* status Completion status */
486 /* */
487 /* CALLS */
488 /* */
489 /* None */
490 /* */
491 /* CALLED BY */
492 /* */
493 /* _gx_utility_bidi_arabic_shaping */
494 /* */
495 /* RELEASE HISTORY */
496 /* */
497 /* DATE NAME DESCRIPTION */
498 /* */
499 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
500 /* */
501 /**************************************************************************/
_gx_utility_bidi_left_joining_causing_test(UINT joining_type)502 static GX_BOOL _gx_utility_bidi_left_joining_causing_test(UINT joining_type)
503 {
504 switch (joining_type)
505 {
506 case JOINING_TYPE_DUAL:
507 case JOINING_TYPE_RIGHT:
508 case JOINING_TYPE_CAUSING:
509 return GX_TRUE;
510 }
511
512 return GX_FALSE;
513 }
514
515 /**************************************************************************/
516 /* */
517 /* FUNCTION RELEASE */
518 /* */
519 /* _gx_utility_bidi_arabic_test PORTABLE C */
520 /* 6.1 */
521 /* AUTHOR */
522 /* */
523 /* Kenneth Maxwell, Microsoft Corporation */
524 /* */
525 /* DESCRIPTION */
526 /* */
527 /* This function tests is the specified strings contains Arabic. */
528 /* */
529 /* INPUT */
530 /* */
531 /* context Bidi information control block*/
532 /* */
533 /* OUTPUT */
534 /* */
535 /* status Completion status */
536 /* */
537 /* CALLS */
538 /* */
539 /* None */
540 /* */
541 /* CALLED BY */
542 /* */
543 /* _gx_utility_bidi_arabic_shaping */
544 /* */
545 /* RELEASE HISTORY */
546 /* */
547 /* DATE NAME DESCRIPTION */
548 /* */
549 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
550 /* */
551 /**************************************************************************/
_gx_utility_bidi_arabic_test(GX_BIDI_CONTEXT * context)552 static GX_BOOL _gx_utility_bidi_arabic_test(GX_BIDI_CONTEXT *context)
553 {
554 GX_BIDI_UNIT *unit = context -> gx_bidi_context_unit_list;
555 INT index;
556
557 for (index = 0; index < context -> gx_bidi_context_unit_count; index++)
558 {
559 if ((unit -> gx_bidi_unit_code >= 0x0600) && (unit -> gx_bidi_unit_code <= 0x06FF))
560 {
561 return GX_TRUE;
562 }
563
564 unit++;
565 }
566
567 return GX_FALSE;
568 }
569
570 /**************************************************************************/
571 /* */
572 /* FUNCTION RELEASE */
573 /* */
574 /* _gx_utility_bidi_arabic_shaping PORTABLE C */
575 /* 6.1 */
576 /* AUTHOR */
577 /* */
578 /* Kenneth Maxwell, Microsoft Corporation */
579 /* */
580 /* DESCRIPTION */
581 /* */
582 /* This function shapes Arabic glyphs according to logical order. */
583 /* */
584 /* INPUT */
585 /* */
586 /* context Bidi information control block*/
587 /* */
588 /* OUTPUT */
589 /* */
590 /* status Completion status */
591 /* */
592 /* CALLS */
593 /* */
594 /* None */
595 /* */
596 /* CALLED BY */
597 /* */
598 /* _gx_utility_bidi_paragraph_reorder */
599 /* */
600 /* RELEASE HISTORY */
601 /* */
602 /* DATE NAME DESCRIPTION */
603 /* */
604 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
605 /* */
606 /**************************************************************************/
_gx_utility_bidi_arabic_shaping(GX_BIDI_CONTEXT * context)607 UINT _gx_utility_bidi_arabic_shaping(GX_BIDI_CONTEXT *context)
608 {
609 ARABIC_UNIT *arabic_unit;
610 ARABIC_UNIT *pre_unit;
611 ARABIC_UNIT *unit;
612 ARABIC_UNIT *follow_unit;
613 ULONG ligature;
614 INT index;
615 GX_BIDI_UNIT *bidi_unit;
616 GX_BIDI_UNIT *pre_bidi_unit;
617 GX_UBYTE utf8[6];
618 UINT glyph_len;
619 INT increment;
620 UINT form_type = 0;
621 INT buffer_size;
622
623 /* Test Arabic glyph. */
624 if (_gx_utility_bidi_arabic_test(context) == GX_FALSE)
625 {
626 /* Nothing to change. */
627 return GX_SUCCESS;
628 }
629
630 buffer_size = (context -> gx_bidi_context_unit_count + 1) * (INT)sizeof(ARABIC_UNIT);
631
632 /* Allocate memory for Arabic shaping. */
633 arabic_unit = (ARABIC_UNIT *)_gx_system_memory_allocator((UINT)buffer_size);
634
635 if (arabic_unit == GX_NULL)
636 {
637 return GX_SYSTEM_MEMORY_ERROR;
638 }
639
640 /* Initiate Arabic shaping information list. */
641 for (index = 0; index < context -> gx_bidi_context_unit_count; index++)
642 {
643 arabic_unit[index].code_point = context -> gx_bidi_context_unit_list[index].gx_bidi_unit_code;
644 arabic_unit[index].shape_form = arabic_unit[index].code_point;
645 arabic_unit[index].joining_type = _gx_utility_bidi_arabic_joining_type_get(arabic_unit[index].code_point);
646 }
647
648 arabic_unit[index].code_point = 0;
649 arabic_unit[index].joining_type = 0;
650
651 pre_unit = NULL;
652 unit = arabic_unit;
653 bidi_unit = context -> gx_bidi_context_unit_list;
654
655 /* Start shaping. */
656 while (unit -> code_point)
657 {
658 increment = 1;
659
660 if (unit -> joining_type == JOINING_TYPE_TRANSPARENT)
661 {
662 /* Rule 1: Transparent characters do not affect the joining behavior of base characters. */
663 unit++;
664 }
665 else
666 {
667 follow_unit = unit + 1;
668
669 /* Find next non-transparent character. */
670 while (follow_unit -> code_point && follow_unit -> joining_type == JOINING_TYPE_TRANSPARENT)
671 {
672 increment++;
673 follow_unit++;
674 }
675
676 if (unit -> joining_type == JOINING_TYPE_RIGHT && pre_unit && _gx_utility_bidi_right_joining_causing_test(pre_unit -> joining_type))
677 {
678 /* Rule 2: a right-joining character x that has a right joining-causing character on the right(preceding) will
679 adopt the form x-right. */
680 form_type = ARABIC_FORM_FINAL;
681 }
682 else if (unit -> joining_type == JOINING_TYPE_LEFT && _gx_utility_bidi_left_joining_causing_test(follow_unit -> joining_type))
683 {
684 /* Rule 3: a left-joining character x that has a left joining-causing character on the left(following) will
685 adopt the form x-left. */
686 form_type = ARABIC_FORM_INITIAL;
687 }
688 else if (unit -> joining_type == JOINING_TYPE_DUAL &&
689 pre_unit && _gx_utility_bidi_right_joining_causing_test(pre_unit -> joining_type) &&
690 _gx_utility_bidi_left_joining_causing_test(follow_unit -> joining_type))
691 {
692 /* Rule 4: a dual-joining character x that has a right joining-causing character on the right(preceding) and
693 a left join-causing character on the left(following) will adopt the form x-medial. */
694 form_type = ARABIC_FORM_MEDIAL;
695 }
696 else if (unit -> joining_type == JOINING_TYPE_DUAL &&
697 pre_unit && _gx_utility_bidi_right_joining_causing_test(pre_unit -> joining_type) &&
698 !_gx_utility_bidi_left_joining_causing_test(follow_unit -> joining_type))
699 {
700 /* Rule 5: a dual-joining character x that has a right join-causing character on the right(preceding) and
701 no left join-causing character on the left(following) will adopt the form x-right. */
702 form_type = ARABIC_FORM_FINAL;
703 }
704 else if (unit -> joining_type == JOINING_TYPE_DUAL &&
705 _gx_utility_bidi_left_joining_causing_test(follow_unit -> joining_type) &&
706 ((pre_unit == GX_NULL) || !_gx_utility_bidi_right_joining_causing_test(pre_unit -> joining_type)))
707 {
708 /* Rule 6: a dual-joining character x that has left joining-causing character on the left(following) and
709 no right join-causing character on the right(preceding) will adopt the form x-left. */
710 form_type = ARABIC_FORM_INITIAL;
711 }
712
713 if (form_type)
714 {
715 unit -> shape_form = _gx_utility_bidi_arabic_form_get(unit -> code_point, form_type);
716 form_type = 0;
717
718 if (pre_unit)
719 {
720 /* Any sequence with alef-right on the left(following) and lam-medial on the right(preceding) will form
721 the ligature (lam-alef)-right. */
722 ligature = _gx_utility_bidi_arabic_ligature_get(unit -> shape_form, pre_unit -> shape_form);
723 if (ligature)
724 {
725 pre_unit -> shape_form = ligature;
726 pre_bidi_unit -> gx_bidi_unit_code = ligature;
727 unit -> shape_form = 0;
728 }
729 }
730
731 bidi_unit -> gx_bidi_unit_code = unit -> shape_form;
732 }
733
734 pre_bidi_unit = bidi_unit;
735 pre_unit = unit;
736 unit = follow_unit;
737 }
738
739 bidi_unit += increment;
740 }
741
742 /* Calculate total utf8 size for shaped glyphs. */
743 context -> gx_bidi_context_reordered_utf8_size = 0;
744 bidi_unit = context -> gx_bidi_context_unit_list;
745 for (index = 0; index < context -> gx_bidi_context_unit_count; index++)
746 {
747 if (bidi_unit -> gx_bidi_unit_code)
748 {
749 _gx_utility_unicode_to_utf8(bidi_unit -> gx_bidi_unit_code, utf8, &glyph_len);
750 context -> gx_bidi_context_reordered_utf8_size += glyph_len;
751 }
752
753 bidi_unit++;
754 }
755
756 _gx_system_memory_free(arabic_unit);
757
758 return GX_SUCCESS;
759 }
760 #endif
761 #endif
762
763