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