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