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
31 #define GX_LINK_RESOLVED_BIDI_TEXT_INFO \
32 if (pre) \
33 { \
34 pre -> gx_bidi_resolved_text_info_next = resolved_info; \
35 } \
36 pre = resolved_info; \
37 if (!head) \
38 { \
39 head = pre; \
40 }
41
42 /**************************************************************************/
43 /* */
44 /* FUNCTION RELEASE */
45 /* */
46 /* _gx_utility_bidi_buffer_allocate PORTABLE C */
47 /* 6.1 */
48 /* AUTHOR */
49 /* */
50 /* Kenneth Maxwell, Microsoft Corporation */
51 /* */
52 /* DESCRIPTION */
53 /* */
54 /* Internal helper function to calculate character count to be handled */
55 /* and allocate a buffer for following processing. */
56 /* */
57 /* INPUT */
58 /* */
59 /* context Bidi information control block*/
60 /* */
61 /* OUTPUT */
62 /* */
63 /* status Completion status */
64 /* */
65 /* CALLS */
66 /* */
67 /* None */
68 /* */
69 /* CALLED BY */
70 /* */
71 /* _gx_utility_bidi_paragraph_reorder */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
78 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
79 /* update with bidi context */
80 /* structure change, */
81 /* moved a pointer check to */
82 /* its caller function, */
83 /* resulting in version 6.1 */
84 /* */
85 /**************************************************************************/
_gx_utility_bidi_buffer_allocate(GX_BIDI_CONTEXT * context)86 static UINT _gx_utility_bidi_buffer_allocate(GX_BIDI_CONTEXT *context)
87 {
88 INT character_count = 0;
89 GX_STRING text;
90 ULONG unicode;
91 INT max_depth = 0;
92 INT depth = 0;
93 INT level_run_count = 1;
94 INT bracket_pair_count = 0;
95 INT max_bracket_pair = 0;
96 INT run_stack_size;
97 INT explicite_stack_size;
98 GX_BIDI_BRACKET_PAIR bracket_pair;
99 GX_BIDI_TEXT_INFO *input_info = context -> gx_bidi_context_input_info;
100
101 text = input_info -> gx_bidi_text_info_text;
102
103 while (text.gx_string_length > 0)
104 {
105 if ((text.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN) ||
106 (text.gx_string_ptr[0] == GX_KEY_LINE_FEED))
107 {
108 break;
109 }
110
111 /* Convert utf8 to unicode. */
112 unicode = 0;
113 _gx_utility_utf8_string_character_get(&text, (GX_CHAR_CODE *)&unicode, GX_NULL);
114
115 switch (unicode)
116 {
117 case GX_BIDI_DIRECTION_FORMAT_RLE:
118 case GX_BIDI_DIRECTION_FORMAT_LRE:
119 case GX_BIDI_DIRECTION_FORMAT_RLO:
120 case GX_BIDI_DIRECTION_FORMAT_LRO:
121 case GX_BIDI_DIRECTION_FORMAT_RLI:
122 case GX_BIDI_DIRECTION_FORMAT_LRI:
123 case GX_BIDI_DIRECTION_FORMAT_FSI:
124 depth++;
125 level_run_count++;
126 break;
127
128 case GX_BIDI_DIRECTION_FORMAT_PDF:
129 case GX_BIDI_DIRECTION_FORMAT_PDI:
130 depth--;
131 level_run_count++;
132 break;
133 default:
134 if (max_bracket_pair < GX_BIDI_MAX_BRACKET_DEPTH)
135 {
136
137 _gx_utility_bidi_bracket_pair_get(unicode, &bracket_pair);
138 if (bracket_pair.gx_bidi_bracket_pair_open)
139 {
140 if (bracket_pair.gx_bidi_bracket_pair_open == unicode)
141 {
142 bracket_pair_count++;
143 if (bracket_pair_count > max_bracket_pair)
144 {
145 max_bracket_pair = bracket_pair_count;
146 }
147 }
148 }
149 }
150 break;
151 }
152
153 if (depth > max_depth)
154 {
155 max_depth = depth;
156 }
157
158 character_count++;
159 }
160
161 if (max_depth > GX_BIDI_MAX_EXPLICIT_DEPTH + 1)
162 {
163 max_depth = GX_BIDI_MAX_EXPLICIT_DEPTH + 1;
164 }
165
166 context -> gx_bidi_context_processced_size = input_info -> gx_bidi_text_info_text.gx_string_length - text.gx_string_length;
167 context -> gx_bidi_context_reordered_utf8_size = context -> gx_bidi_context_processced_size;
168 context -> gx_bidi_context_unit_count = character_count;
169
170 context -> gx_bidi_context_buffer_size = sizeof(GX_BIDI_UNIT) * (UINT)(character_count); /* unit list size. */
171
172 if (input_info -> gx_bidi_text_info_font && input_info -> gx_bidi_text_info_display_width > 0)
173 {
174 context -> gx_bidi_context_buffer_size += sizeof(ULONG) * (UINT)character_count; /* line index cache size. */
175 }
176
177 /* Size of buffer used for loading explicit level data
178 Will be released before level run buffer is used. */
179 explicite_stack_size = (INT)sizeof(GX_BIDI_EXPLICIT_ENTRY) * (max_depth + 1);
180
181 /* Size of buffer used for loading level run data. */
182 run_stack_size = (INT)sizeof(GX_BIDI_LEVEL_RUN) * character_count;
183
184 /* Size of buffer used for loading isolate run data. */
185 run_stack_size += (INT)sizeof(GX_BIDI_ISOLATE_RUN) * level_run_count + (INT)sizeof(ULONG) * character_count;
186
187 /* Size of buffer used for loading bracket pair data. */
188 context -> gx_bidi_context_bracket_pair_size = sizeof(ULONG) * (UINT)(max_bracket_pair * 2);
189 run_stack_size += (INT)context -> gx_bidi_context_bracket_pair_size;
190 run_stack_size += (INT)sizeof(ULONG) * (INT)max_bracket_pair;
191
192 if (run_stack_size < explicite_stack_size)
193 {
194 run_stack_size = explicite_stack_size;
195 }
196
197 context -> gx_bidi_context_buffer_size += (UINT)run_stack_size;
198
199 context -> gx_bidi_context_buffer = (GX_UBYTE *)_gx_system_memory_allocator(context -> gx_bidi_context_buffer_size);
200 if (context -> gx_bidi_context_buffer == GX_NULL)
201 {
202 return GX_SYSTEM_MEMORY_ERROR;
203 }
204
205 memset(context -> gx_bidi_context_buffer, 0, (size_t)context -> gx_bidi_context_buffer_size);
206
207 return GX_SUCCESS;
208 }
209
210 /**************************************************************************/
211 /* */
212 /* FUNCTION RELEASE */
213 /* */
214 /* _gx_utility_bidi_initiate PORTABLE C */
215 /* 6.1 */
216 /* AUTHOR */
217 /* */
218 /* Kenneth Maxwell, Microsoft Corporation */
219 /* */
220 /* DESCRIPTION */
221 /* */
222 /* Internal helper function to convert utf8 text to unicode, initiate */
223 /* initiate character types and calculate the total lines. */
224 /* */
225 /* INPUT */
226 /* */
227 /* context Bidi information control block*/
228 /* font Text font, if not set, the */
229 /* text is handled as a single */
230 /* line */
231 /* display_width The max width of text in one */
232 /* line , if not set, the text */
233 /* is handled as a single line */
234 /* total_lines Total lines of handled text */
235 /* */
236 /* OUTPUT */
237 /* */
238 /* status Completion status */
239 /* */
240 /* CALLS */
241 /* */
242 /* None */
243 /* */
244 /* CALLED BY */
245 /* */
246 /* _gx_utility_bidi_paragraph_reorder */
247 /* */
248 /* RELEASE HISTORY */
249 /* */
250 /* DATE NAME DESCRIPTION */
251 /* */
252 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
253 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
254 /* removed line breaking logic,*/
255 /* resulting in version 6.1 */
256 /* */
257 /**************************************************************************/
_gx_utility_bidi_initiate(GX_BIDI_CONTEXT * context)258 static UINT _gx_utility_bidi_initiate(GX_BIDI_CONTEXT *context)
259 {
260 GX_BIDI_TEXT_INFO *input_info = context -> gx_bidi_context_input_info;
261 INT index = 0;
262 GX_STRING string;
263 GX_CHAR_CODE code;
264 GX_BIDI_UNIT *unit;
265
266 context -> gx_bidi_context_unit_list = (GX_BIDI_UNIT *)context -> gx_bidi_context_buffer;
267 context -> gx_bidi_context_buffer_index += sizeof(GX_BIDI_UNIT) * (UINT)context -> gx_bidi_context_unit_count;
268
269 string = input_info -> gx_bidi_text_info_text;
270
271 while (index < context -> gx_bidi_context_unit_count)
272 {
273 unit = &context -> gx_bidi_context_unit_list[index];
274
275 /* Convert utf8 to unicode. */
276 _gx_utility_utf8_string_character_get(&string, &code, GX_NULL);
277 unit -> gx_bidi_unit_code = code;
278
279 _gx_utility_bidi_character_type_get(unit -> gx_bidi_unit_code, &unit -> gx_bidi_unit_type);
280 unit -> gx_bidi_unit_org_type = unit -> gx_bidi_unit_type;
281
282 index++;
283 }
284
285 return GX_SUCCESS;
286 }
287
288 /**************************************************************************/
289 /* */
290 /* FUNCTION RELEASE */
291 /* */
292 /* _gx_utility_bidi_block_level_determine PORTABLE C */
293 /* 6.1 */
294 /* AUTHOR */
295 /* */
296 /* Kenneth Maxwell, Microsoft Corporation */
297 /* */
298 /* DESCRIPTION */
299 /* */
300 /* Internal helper function to calculate the level of the specified */
301 /* text block */
302 /* */
303 /* INPUT */
304 /* */
305 /* context Bidi information control block*/
306 /* start_index The start index of the text */
307 /* block */
308 /* end_index The end index of the text */
309 /* block */
310 /* level Buffer for level value */
311 /* */
312 /* OUTPUT */
313 /* */
314 /* status Completion status */
315 /* */
316 /* CALLS */
317 /* */
318 /* None */
319 /* */
320 /* CALLED BY */
321 /* */
322 /* _gx_utility_bidi_paragraph_reorder */
323 /* _gx_utility_bidi_explicit_levels_determine */
324 /* */
325 /* RELEASE HISTORY */
326 /* */
327 /* DATE NAME DESCRIPTION */
328 /* */
329 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
330 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
331 /* resulting in version 6.1 */
332 /* */
333 /**************************************************************************/
_gx_utility_bidi_block_level_determine(GX_BIDI_CONTEXT * context,UINT start_index,UINT end_index,GX_UBYTE * level)334 static UINT _gx_utility_bidi_block_level_determine(GX_BIDI_CONTEXT *context, UINT start_index, UINT end_index, GX_UBYTE *level)
335 {
336 INT isolate_count = 0;
337 GX_BIDI_UNIT *unit;
338
339 unit = &context -> gx_bidi_context_unit_list[start_index];
340
341 while (start_index <= end_index)
342 {
343 /* Find the first character of type L, AL, or R
344 while skipping over any hcaracters between an isolate initiator and its matching PDI. */
345 switch (unit -> gx_bidi_unit_type)
346 {
347 case GX_BIDI_CHARACTER_TYPE_AL:
348 case GX_BIDI_CHARACTER_TYPE_R:
349 if (isolate_count == 0)
350 {
351 *level = 1;
352 return GX_SUCCESS;
353 }
354 break;
355
356 case GX_BIDI_CHARACTER_TYPE_L:
357 if (isolate_count == 0)
358 {
359 *level = 0;
360 return GX_SUCCESS;
361 }
362 break;
363
364 case GX_BIDI_CHARACTER_TYPE_RLI:
365 case GX_BIDI_CHARACTER_TYPE_LRI:
366 isolate_count++;
367 break;
368
369 case GX_BIDI_CHARACTER_TYPE_PDI:
370 if (isolate_count)
371 {
372 isolate_count--;
373 }
374 break;
375 }
376
377 start_index++;
378 unit++;
379 }
380
381 /* Otherwise, set paragraph embedding level to 0. */
382 *level = 0;
383 return GX_SUCCESS;
384 }
385
386 /**************************************************************************/
387 /* */
388 /* FUNCTION RELEASE */
389 /* */
390 /* _gx_utility_bidi_explicit_levels_determine PORTABLE C */
391 /* 6.1 */
392 /* AUTHOR */
393 /* */
394 /* Kenneth Maxwell, Microsoft Corporation */
395 /* */
396 /* DESCRIPTION */
397 /* */
398 /* Internal helper function to calculate explicite level of every */
399 /* character. */
400 /* */
401 /* INPUT */
402 /* */
403 /* context Bidi information control block*/
404 /* format. */
405 /* */
406 /* OUTPUT */
407 /* */
408 /* status Completion status */
409 /* */
410 /* CALLS */
411 /* */
412 /* None */
413 /* */
414 /* CALLED BY */
415 /* */
416 /* _gx_utility_bidi_paragraph_reorder */
417 /* */
418 /* RELEASE HISTORY */
419 /* */
420 /* DATE NAME DESCRIPTION */
421 /* */
422 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
423 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
424 /* resulting in version 6.1 */
425 /* */
426 /**************************************************************************/
_gx_utility_bidi_explicit_levels_determine(GX_BIDI_CONTEXT * context)427 static UINT _gx_utility_bidi_explicit_levels_determine(GX_BIDI_CONTEXT *context)
428 {
429 GX_BIDI_EXPLICIT_ENTRY *stack;
430 GX_BIDI_EXPLICIT_ENTRY *entry;
431 GX_BIDI_EXPLICIT_ENTRY *last_entry;
432 INT stack_top = 0;
433 INT overflow_isolate_count = 0;
434 INT overflow_embedding_count = 0;
435 INT valid_isolate_count = 0;
436 INT index = 0;
437 INT end_index;
438 GX_UBYTE level;
439 ULONG type;
440 GX_BIDI_UNIT *unit;
441
442 stack = (GX_BIDI_EXPLICIT_ENTRY *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
443
444 if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
445 {
446 return GX_INVALID_MEMORY_SIZE;
447 }
448 entry = stack;
449
450 /* Push onto the stack an entry consisting of the paragraph embedding level,
451 a neutral directional override status, and a false directional isolate status. */
452 entry -> gx_bidi_explicit_level = context -> gx_bidi_context_base_level;
453 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
454 entry -> gx_bidi_explicit_isolate_status = GX_FALSE;
455 last_entry = entry;
456 entry++;
457 stack_top++;
458
459 unit = &context -> gx_bidi_context_unit_list[index];
460
461 while (index < context -> gx_bidi_context_unit_count)
462 {
463 type = unit -> gx_bidi_unit_type;
464
465 switch (type)
466 {
467 case GX_BIDI_CHARACTER_TYPE_RLE:
468 case GX_BIDI_CHARACTER_TYPE_LRE:
469 case GX_BIDI_CHARACTER_TYPE_RLO:
470 case GX_BIDI_CHARACTER_TYPE_LRO:
471 /* Handle explicit embeddings/overrides. */
472 entry -> gx_bidi_explicit_level = (GX_UBYTE)(last_entry -> gx_bidi_explicit_level + 1);
473 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_BN;
474
475 if (type == GX_BIDI_CHARACTER_TYPE_RLE ||
476 type == GX_BIDI_CHARACTER_TYPE_RLO)
477 {
478 /* Compute the least odd embedding level greater than the embedding level of the last entry. */
479 if ((entry -> gx_bidi_explicit_level & 0x01) == 0)
480 {
481 entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
482 }
483 }
484 else
485 {
486 /* Compute the least even embedding level greater than the embedding level of the last entry. */
487 if ((entry -> gx_bidi_explicit_level & 0x01) != 0)
488 {
489 entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
490 }
491 }
492
493 if ((entry -> gx_bidi_explicit_level <= GX_BIDI_MAX_EXPLICIT_DEPTH) &&
494 (overflow_isolate_count == 0) &&
495 (overflow_embedding_count == 0))
496 {
497 /* Push an entry to stack. */
498
499 if (type == GX_BIDI_CHARACTER_TYPE_RLE ||
500 type == GX_BIDI_CHARACTER_TYPE_LRE)
501 {
502 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
503 }
504 else if (type == GX_BIDI_CHARACTER_TYPE_RLO)
505 {
506 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_R;
507 }
508 else
509 {
510 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_L;
511 }
512
513 entry -> gx_bidi_explicit_isolate_status = GX_FALSE;
514 last_entry = entry;
515 entry++;
516 stack_top++;
517 }
518 else if (overflow_isolate_count == 0)
519 {
520 overflow_embedding_count++;
521 }
522 break;
523
524 case GX_BIDI_CHARACTER_TYPE_RLI:
525 case GX_BIDI_CHARACTER_TYPE_LRI:
526 case GX_BIDI_CHARACTER_TYPE_FSI:
527 if (type == GX_BIDI_CHARACTER_TYPE_FSI)
528 {
529 for (end_index = index + 1; end_index < context -> gx_bidi_context_unit_count; end_index++)
530 {
531 if (context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_PDI)
532 {
533 break;
534 }
535 }
536
537 _gx_utility_bidi_block_level_determine(context, (UINT)index, (UINT)end_index, &level);
538
539 if (level == 1)
540 {
541 type = GX_BIDI_CHARACTER_TYPE_RLI;
542 }
543 else
544 {
545 type = GX_BIDI_CHARACTER_TYPE_LRI;
546 }
547 }
548
549 /* Set the RLI's embedding level to the embedding level of the last entry. */
550 unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
551 entry -> gx_bidi_explicit_level = (GX_UBYTE)(last_entry -> gx_bidi_explicit_level + 1);
552
553 if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
554 {
555 /* Reset the current character type from RLI to L if last override status is left to right. */
556 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
557 }
558 else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
559 {
560 /* Reset the current character type from RLI to R if last overried status is right to left. */
561 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
562 }
563
564 if ((type == GX_BIDI_CHARACTER_TYPE_RLI && (entry -> gx_bidi_explicit_level & 0x01) == 0) ||
565 (type == GX_BIDI_CHARACTER_TYPE_LRI && (entry -> gx_bidi_explicit_level & 0x01) != 0))
566 {
567 entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
568 }
569
570 if (entry -> gx_bidi_explicit_level <= GX_BIDI_MAX_EXPLICIT_DEPTH &&
571 overflow_isolate_count == 0 &&
572 overflow_embedding_count == 0)
573 {
574 valid_isolate_count++;
575 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
576 entry -> gx_bidi_explicit_isolate_status = GX_TRUE;
577 last_entry = entry;
578 entry++;
579 stack_top++;
580 }
581 else
582 {
583 /* This is an overflow RLI/LRI. */
584 overflow_isolate_count++;
585 }
586 break;
587
588 case GX_BIDI_CHARACTER_TYPE_PDF:
589 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_BN;
590 if (overflow_isolate_count == 0)
591 {
592 if (overflow_embedding_count)
593 {
594 overflow_embedding_count--;
595 }
596 else if (last_entry -> gx_bidi_explicit_isolate_status == GX_FALSE &&
597 stack_top >= 2)
598 {
599 last_entry--;
600 entry--;
601 stack_top--;
602 }
603 }
604 break;
605
606 case GX_BIDI_CHARACTER_TYPE_PDI:
607 if (overflow_isolate_count > 0)
608 {
609 /* This PDI matches an overflow isolate initiator. */
610 overflow_isolate_count--;
611 }
612 else if (valid_isolate_count != 0)
613 {
614 overflow_embedding_count = 0;
615
616 while ((stack_top > 1) &&
617 (last_entry -> gx_bidi_explicit_isolate_status == GX_FALSE))
618 {
619 /* Pop the last entry. */
620 last_entry--;
621 entry--;
622 stack_top--;
623 }
624
625 last_entry--;
626 entry--;
627 stack_top--;
628 valid_isolate_count--;
629 }
630
631 unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
632
633 if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
634 {
635 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
636 }
637 else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
638 {
639 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
640 }
641 break;
642
643 case GX_BIDI_CHARACTER_TYPE_BN:
644 break;
645
646 default:
647 /* Set current character's embedding level to the embedding level of the last entry. */
648 unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
649
650 if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
651 {
652 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
653 }
654 else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
655 {
656 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
657 }
658 break;
659 }
660
661 index++;
662 unit++;
663 }
664
665 return GX_SUCCESS;
666 }
667
668 /**************************************************************************/
669 /* */
670 /* FUNCTION RELEASE */
671 /* */
672 /* _gx_utility_bidi_level_runs_compute PORTABLE C */
673 /* 6.1 */
674 /* AUTHOR */
675 /* */
676 /* Kenneth Maxwell, Microsoft Corporation */
677 /* */
678 /* DESCRIPTION */
679 /* */
680 /* Internal helper function to calculate the level runs of the */
681 /* specified text block */
682 /* */
683 /* INPUT */
684 /* */
685 /* context Bidi information control block*/
686 /* start_index The start index of the text */
687 /* block */
688 /* end_index The end index of the text */
689 /* block */
690 /* */
691 /* OUTPUT */
692 /* */
693 /* status Completion status */
694 /* */
695 /* CALLS */
696 /* */
697 /* None */
698 /* */
699 /* CALLED BY */
700 /* */
701 /* _gx_utility_bidi_paragraph_reorder */
702 /* */
703 /* RELEASE HISTORY */
704 /* */
705 /* DATE NAME DESCRIPTION */
706 /* */
707 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
708 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
709 /* resulting in version 6.1 */
710 /* */
711 /**************************************************************************/
_gx_utility_bidi_level_runs_compute(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)712 static UINT _gx_utility_bidi_level_runs_compute(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
713 {
714 INT run_start_index = -1;
715 INT run_end_index;
716 INT index = start_index;
717 GX_BIDI_LEVEL_RUN *entry;
718 GX_BIDI_LEVEL_RUN *last_entry = GX_NULL;
719 GX_UBYTE run_level;
720 GX_BIDI_UNIT *unit;
721
722 if (context -> gx_bidi_context_level_runs == GX_NULL)
723 {
724 context -> gx_bidi_context_level_runs = (GX_BIDI_LEVEL_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
725 context -> gx_bidi_context_buffer_index += sizeof(GX_BIDI_LEVEL_RUN) * (UINT)context -> gx_bidi_context_unit_count;
726
727 if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
728 {
729 return GX_INVALID_MEMORY_SIZE;
730 }
731 }
732
733 entry = context -> gx_bidi_context_level_runs;
734
735 unit = &context -> gx_bidi_context_unit_list[index];
736 while (index <= end_index)
737 {
738 switch (unit -> gx_bidi_unit_type)
739 {
740 case GX_BIDI_CHARACTER_TYPE_BN:
741 break;
742
743 default:
744 if (run_start_index == -1)
745 {
746 run_start_index = index;
747 run_level = unit -> gx_bidi_unit_level;
748 }
749 else if (run_level != unit -> gx_bidi_unit_level)
750 {
751 entry -> gx_bidi_level_run_start_index = run_start_index;
752 entry -> gx_bidi_level_run_end_index = run_end_index;
753 entry -> gx_bidi_level_run_level = run_level;
754 entry -> gx_bidi_level_run_next = GX_NULL;
755
756 if (last_entry)
757 {
758 last_entry -> gx_bidi_level_run_next = entry;
759 }
760 last_entry = entry;
761 entry++;
762 run_start_index = index;
763 run_level = unit -> gx_bidi_unit_level;
764 }
765 run_end_index = index;
766 break;
767 }
768
769 index++;
770 unit++;
771 }
772
773 entry -> gx_bidi_level_run_start_index = run_start_index;
774 entry -> gx_bidi_level_run_end_index = run_end_index;
775 entry -> gx_bidi_level_run_level = run_level;
776 entry -> gx_bidi_level_run_next = GX_NULL;
777
778 if (last_entry)
779 {
780 last_entry -> gx_bidi_level_run_next = entry;
781 }
782 return GX_SUCCESS;
783 }
784
785 /**************************************************************************/
786 /* */
787 /* FUNCTION RELEASE */
788 /* */
789 /* _gx_utiltiy_isolate_run_sequence_append PORTABLE C */
790 /* 6.1 */
791 /* AUTHOR */
792 /* */
793 /* Kenneth Maxwell, Microsoft Corporation */
794 /* */
795 /* DESCRIPTION */
796 /* */
797 /* Internal helper function to append a sequence to the specified */
798 /* isolate run sequence. */
799 /* */
800 /* INPUT */
801 /* */
802 /* context Bidi information control block*/
803 /* start_index Start position of the append */
804 /* sequence */
805 /* end_index End position of the append */
806 /* sequence */
807 /* siolate_run Pointer to isolate run */
808 /* structure */
809 /* */
810 /* OUTPUT */
811 /* */
812 /* status Completion status */
813 /* */
814 /* CALLS */
815 /* */
816 /* None */
817 /* */
818 /* CALLED BY */
819 /* */
820 /* _gx_utility_bidi_one_isolate_run_sequences_get */
821 /* */
822 /* RELEASE HISTORY */
823 /* */
824 /* DATE NAME DESCRIPTION */
825 /* */
826 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
827 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
828 /* resulting in version 6.1 */
829 /* */
830 /**************************************************************************/
_gx_utiltiy_isolate_run_sequence_append(GX_BIDI_CONTEXT * context,INT start_index,INT end_index,GX_BIDI_ISOLATE_RUN * isolate_run)831 static UINT _gx_utiltiy_isolate_run_sequence_append(GX_BIDI_CONTEXT *context, INT start_index, INT end_index,
832 GX_BIDI_ISOLATE_RUN *isolate_run)
833 {
834 INT index;
835 GX_BIDI_UNIT *unit;
836
837 unit = &context -> gx_bidi_context_unit_list[start_index];
838 for (index = start_index; index <= end_index; index++)
839 {
840 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_BN)
841 {
842 unit++;
843 continue;
844 }
845
846 isolate_run -> gx_bidi_isolate_run_index_list[isolate_run -> gx_bidi_isolate_run_index_count++] = index;
847 context -> gx_bidi_context_buffer_index += sizeof(ULONG);
848
849 unit++;
850 }
851
852 if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
853 {
854 return GX_INVALID_MEMORY_SIZE;
855 }
856
857 return GX_SUCCESS;
858 }
859
860 /**************************************************************************/
861 /* */
862 /* FUNCTION RELEASE */
863 /* */
864 /* _gx_utility_bidi_one_isolate_run_sequence_get PORTABLE C */
865 /* 6.1 */
866 /* AUTHOR */
867 /* */
868 /* Kenneth Maxwell, Microsoft Corporation */
869 /* */
870 /* DESCRIPTION */
871 /* */
872 /* Internal helper function to calculate one isolate run sequence */
873 /* start from the specified level run. */
874 /* */
875 /* INPUT */
876 /* */
877 /* context Bidi information control block*/
878 /* pre_level Embedding level of the */
879 /* previous level run */
880 /* level_run Pointer to level run structure*/
881 /* isolate_run Buffer to load an isolate run */
882 /* sequence */
883 /* */
884 /* OUTPUT */
885 /* */
886 /* status Completion status */
887 /* */
888 /* CALLS */
889 /* */
890 /* _gx_utiltiy_isolate_run_sequence_append */
891 /* */
892 /* CALLED BY */
893 /* */
894 /* _gx_utility_bidi_isolate_run_sequence_get */
895 /* */
896 /* RELEASE HISTORY */
897 /* */
898 /* DATE NAME DESCRIPTION */
899 /* */
900 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
901 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
902 /* resulting in version 6.1 */
903 /* */
904 /**************************************************************************/
_gx_utility_bidi_one_isolate_run_sequence_get(GX_BIDI_CONTEXT * context,GX_UBYTE pre_level,GX_BIDI_LEVEL_RUN * level_run,GX_BIDI_ISOLATE_RUN * isolate_run)905 static UINT _gx_utility_bidi_one_isolate_run_sequence_get(GX_BIDI_CONTEXT *context, GX_UBYTE pre_level,
906 GX_BIDI_LEVEL_RUN *level_run, GX_BIDI_ISOLATE_RUN *isolate_run)
907 {
908 UINT status;
909 GX_UBYTE next_level;
910 GX_UBYTE run_level;
911 GX_UBYTE higher_level;
912 INT start_index;
913 INT end_index;
914 UINT isolate_initiator_count;
915 GX_BIDI_UNIT *unit;
916 ULONG last_character;
917
918 run_level = level_run -> gx_bidi_level_run_level;
919 start_index = level_run -> gx_bidi_level_run_start_index;
920 end_index = level_run -> gx_bidi_level_run_end_index;
921
922 isolate_run -> gx_bidi_isolate_run_index_count = 0;
923
924 status = _gx_utiltiy_isolate_run_sequence_append(context, start_index, end_index, isolate_run);
925
926 if (status != GX_SUCCESS)
927 {
928 return status;
929 }
930
931 isolate_run -> gx_bidi_isolate_run_next = GX_NULL;
932
933 last_character = context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_code;
934
935 level_run = level_run -> gx_bidi_level_run_next;
936 isolate_initiator_count = 1;
937
938 next_level = (level_run == GX_NULL) ? context -> gx_bidi_context_base_level : level_run -> gx_bidi_level_run_level;
939
940 while (level_run)
941 {
942 /* while the level run last in the sequence ends with an isolate initiator that has a matching PDI,
943 append the level run containing the matching PDI to the isolate run sequence. */
944 if ((last_character != GX_BIDI_DIRECTION_FORMAT_RLI) &&
945 (last_character != GX_BIDI_DIRECTION_FORMAT_LRI) &&
946 (last_character != GX_BIDI_DIRECTION_FORMAT_FSI))
947 {
948 break;
949 }
950
951 start_index = level_run -> gx_bidi_level_run_start_index;
952 end_index = level_run -> gx_bidi_level_run_end_index;
953
954 unit = &context -> gx_bidi_context_unit_list[start_index];
955 if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_PDI)
956 {
957 isolate_initiator_count--;
958 if (isolate_initiator_count == 0)
959 {
960 /* This is a matching PDI. */
961 status = _gx_utiltiy_isolate_run_sequence_append(context, start_index, end_index, isolate_run);
962
963 if (status != GX_SUCCESS)
964 {
965 return status;
966 }
967
968 last_character = context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_code;
969
970 if (level_run -> gx_bidi_level_run_next)
971 {
972 next_level = level_run -> gx_bidi_level_run_next -> gx_bidi_level_run_level;
973 }
974 else
975 {
976 next_level = context -> gx_bidi_context_base_level;
977 }
978 }
979 }
980
981 unit = &context -> gx_bidi_context_unit_list[end_index];
982
983 if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_LRI ||
984 unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_RLI ||
985 unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_FSI)
986 {
987 isolate_initiator_count++;
988 }
989
990 level_run = level_run -> gx_bidi_level_run_next;
991 }
992
993 /* Determine sos. */
994 higher_level = (pre_level > run_level) ? pre_level : run_level;
995 isolate_run -> gx_bidi_isolate_run_sos = ((higher_level & 0x01) == 1) ? GX_BIDI_CHARACTER_TYPE_R : GX_BIDI_CHARACTER_TYPE_L;
996
997 /* Determine eos. */
998 higher_level = (next_level > run_level) ? next_level : run_level;
999 isolate_run -> gx_bidi_isolate_run_eos = ((higher_level & 0x01) == 1) ? GX_BIDI_CHARACTER_TYPE_R : GX_BIDI_CHARACTER_TYPE_L;
1000
1001 return GX_SUCCESS;
1002 }
1003
1004 /**************************************************************************/
1005 /* */
1006 /* FUNCTION RELEASE */
1007 /* */
1008 /* _gx_utility_bidi_isolate_run_sequences_get PORTABLE C */
1009 /* 6.1 */
1010 /* AUTHOR */
1011 /* */
1012 /* Kenneth Maxwell, Microsoft Corporation */
1013 /* */
1014 /* DESCRIPTION */
1015 /* */
1016 /* Internal helper function to calculate the isolate run sequences. */
1017 /* */
1018 /* INPUT */
1019 /* */
1020 /* context Bidi information control block*/
1021 /* */
1022 /* OUTPUT */
1023 /* */
1024 /* status Completion status */
1025 /* */
1026 /* CALLS */
1027 /* */
1028 /* None */
1029 /* */
1030 /* CALLED BY */
1031 /* */
1032 /* _gx_utility_bidi_paragraph_reorder */
1033 /* */
1034 /* RELEASE HISTORY */
1035 /* */
1036 /* DATE NAME DESCRIPTION */
1037 /* */
1038 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1039 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1040 /* resulting in version 6.1 */
1041 /* */
1042 /**************************************************************************/
_gx_utility_bidi_isolate_run_sequences_get(GX_BIDI_CONTEXT * context)1043 static UINT _gx_utility_bidi_isolate_run_sequences_get(GX_BIDI_CONTEXT *context)
1044 {
1045 UINT status;
1046 INT level_run_start_index;
1047 INT level_run_end_index;
1048 INT isolate_initiator_count = 0;
1049 GX_BIDI_LEVEL_RUN *level_run_entry;
1050 GX_BIDI_ISOLATE_RUN *isolate_run_entry;
1051 GX_BIDI_ISOLATE_RUN *last_isolate_run_entry = GX_NULL;
1052 GX_UBYTE pre_level = context -> gx_bidi_context_base_level;
1053 GX_BIDI_UNIT *unit;
1054
1055 /* Compute level runs. */
1056 status = _gx_utility_bidi_level_runs_compute(context, 0, context -> gx_bidi_context_unit_count - 1);
1057
1058 if (status != GX_SUCCESS)
1059 {
1060 return status;
1061 }
1062
1063 /* Compute isolate runs. */
1064 context -> gx_bidi_context_isolate_runs = (GX_BIDI_ISOLATE_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1065
1066 level_run_entry = context -> gx_bidi_context_level_runs;
1067 while (level_run_entry)
1068 {
1069 /* For each level run in the paragraph whose first characer is not a PDI,
1070 or is a PDI that does not match any isolate initiator,
1071 create a new isolate run sequence and initiate it to the level run. */
1072 level_run_start_index = level_run_entry -> gx_bidi_level_run_start_index;
1073 level_run_end_index = level_run_entry -> gx_bidi_level_run_end_index;
1074
1075 unit = &context -> gx_bidi_context_unit_list[level_run_start_index];
1076
1077 if ((unit -> gx_bidi_unit_code != GX_BIDI_DIRECTION_FORMAT_PDI) ||
1078 (isolate_initiator_count == 0))
1079 {
1080 isolate_run_entry = (GX_BIDI_ISOLATE_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1081 context -> gx_bidi_context_buffer_index += (INT)(sizeof(GX_BIDI_ISOLATE_RUN));
1082 isolate_run_entry -> gx_bidi_isolate_run_index_list = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1083
1084 if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
1085 {
1086 return GX_INVALID_MEMORY_SIZE;
1087 }
1088
1089 /* Get one isolate run sequence. */
1090 _gx_utility_bidi_one_isolate_run_sequence_get(context, pre_level, level_run_entry, isolate_run_entry);
1091
1092 if (last_isolate_run_entry)
1093 {
1094 last_isolate_run_entry -> gx_bidi_isolate_run_next = isolate_run_entry;
1095 }
1096
1097 last_isolate_run_entry = isolate_run_entry;
1098 }
1099
1100 if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_PDI)
1101 {
1102 isolate_initiator_count--;
1103 }
1104
1105 unit = &context -> gx_bidi_context_unit_list[level_run_end_index];
1106
1107 if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_LRI ||
1108 unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_RLI ||
1109 unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_FSI)
1110 {
1111 isolate_initiator_count++;
1112 }
1113
1114 pre_level = level_run_entry -> gx_bidi_level_run_level;
1115 level_run_entry = level_run_entry -> gx_bidi_level_run_next;
1116 }
1117
1118 return status;
1119 }
1120
1121 /**************************************************************************/
1122 /* */
1123 /* FUNCTION RELEASE */
1124 /* */
1125 /* _gx_utility_bidi_weak_type_resolve_1 PORTABLE C */
1126 /* 6.1 */
1127 /* AUTHOR */
1128 /* */
1129 /* Kenneth Maxwell, Microsoft Corporation */
1130 /* */
1131 /* DESCRIPTION */
1132 /* */
1133 /* Internal helper function to apply rule 1 to weak characters in an */
1134 /* isolate run sequence. */
1135 /* */
1136 /* INPUT */
1137 /* */
1138 /* context Bidi information control block*/
1139 /* entry Pointer to an isolate run */
1140 /* sequence */
1141 /* */
1142 /* OUTPUT */
1143 /* */
1144 /* status Completion status */
1145 /* */
1146 /* CALLS */
1147 /* */
1148 /* None */
1149 /* */
1150 /* CALLED BY */
1151 /* */
1152 /* _gx_utility_bidi_paragraph_reorder */
1153 /* */
1154 /* RELEASE HISTORY */
1155 /* */
1156 /* DATE NAME DESCRIPTION */
1157 /* */
1158 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1159 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1160 /* resulting in version 6.1 */
1161 /* */
1162 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_1(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1163 static UINT _gx_utility_bidi_weak_type_resolve_1(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1164 {
1165 INT run_index;
1166 INT text_index;
1167 GX_UBYTE pre_type = 0;
1168 GX_BIDI_UNIT *unit;
1169
1170 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1171 {
1172 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1173 unit = &context -> gx_bidi_context_unit_list[text_index];
1174
1175 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_NSM)
1176 {
1177 if (pre_type == 0)
1178 {
1179 /* If the NSM is at the start of the isolating run sequence, it will get the type of sos. */
1180 unit -> gx_bidi_unit_type = entry -> gx_bidi_isolate_run_sos;
1181 }
1182 else
1183 {
1184 switch (pre_type)
1185 {
1186 case GX_BIDI_CHARACTER_TYPE_RLI:
1187 case GX_BIDI_CHARACTER_TYPE_LRI:
1188 case GX_BIDI_CHARACTER_TYPE_PDI:
1189 /* If the previous character type is an isolate initiator or PDI, change type to ON. */
1190 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_ON;
1191 break;
1192
1193 default:
1194 /* Otherwise, change type to the type of previous character. */
1195 unit -> gx_bidi_unit_type = pre_type;
1196 break;
1197 }
1198 }
1199 }
1200
1201 pre_type = unit -> gx_bidi_unit_type;
1202 }
1203 return GX_SUCCESS;
1204 }
1205
1206 /**************************************************************************/
1207 /* */
1208 /* FUNCTION RELEASE */
1209 /* */
1210 /* _gx_utility_bidi_weak_type_resolve_2_3 PORTABLE C */
1211 /* 6.1 */
1212 /* AUTHOR */
1213 /* */
1214 /* Kenneth Maxwell, Microsoft Corporation */
1215 /* */
1216 /* DESCRIPTION */
1217 /* */
1218 /* Internal helper function to apply rule 2 and 3 to weak characters in*/
1219 /* an isolate run sequence. */
1220 /* */
1221 /* INPUT */
1222 /* */
1223 /* context Bidi information control block*/
1224 /* entry Pointer to an isolate run */
1225 /* sequence */
1226 /* */
1227 /* OUTPUT */
1228 /* */
1229 /* status Completion status */
1230 /* */
1231 /* CALLS */
1232 /* */
1233 /* None */
1234 /* */
1235 /* CALLED BY */
1236 /* */
1237 /* _gx_utility_bidi_paragraph_reorder */
1238 /* */
1239 /* RELEASE HISTORY */
1240 /* */
1241 /* DATE NAME DESCRIPTION */
1242 /* */
1243 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1244 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1245 /* resulting in version 6.1 */
1246 /* */
1247 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_2_3(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1248 static UINT _gx_utility_bidi_weak_type_resolve_2_3(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1249 {
1250 INT run_index = 0;
1251 INT text_index;
1252 GX_BOOL do_change = GX_FALSE;
1253 GX_BIDI_UNIT *unit;
1254
1255 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1256 {
1257 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1258 unit = &context -> gx_bidi_context_unit_list[text_index];
1259
1260 /* Search backward from each instance of a EN until the first strong type is found,
1261 If AL is found, replacing following EN to AN. */
1262
1263 switch (unit -> gx_bidi_unit_type)
1264 {
1265 case GX_BIDI_CHARACTER_TYPE_R:
1266 case GX_BIDI_CHARACTER_TYPE_L:
1267 do_change = GX_FALSE;
1268 break;
1269
1270 case GX_BIDI_CHARACTER_TYPE_AL:
1271 do_change = GX_TRUE;
1272
1273 /* Change all ALs to R. */
1274 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
1275 break;
1276
1277 case GX_BIDI_CHARACTER_TYPE_EN:
1278 if (do_change)
1279 {
1280 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_AN;
1281 }
1282 break;
1283 }
1284 }
1285
1286 return GX_SUCCESS;
1287 }
1288
1289 /**************************************************************************/
1290 /* */
1291 /* FUNCTION RELEASE */
1292 /* */
1293 /* _gx_utility_bidi_weak_type_resolve_4 PORTABLE C */
1294 /* 6.1 */
1295 /* AUTHOR */
1296 /* */
1297 /* Kenneth Maxwell, Microsoft Corporation */
1298 /* */
1299 /* DESCRIPTION */
1300 /* */
1301 /* Internal helper function to apply rule 4 to weak characters in an */
1302 /* isolate run sequence. */
1303 /* */
1304 /* INPUT */
1305 /* */
1306 /* context Bidi information control block*/
1307 /* entry Pointer to an isolate run */
1308 /* sequence */
1309 /* */
1310 /* OUTPUT */
1311 /* */
1312 /* status Completion status */
1313 /* */
1314 /* CALLS */
1315 /* */
1316 /* None */
1317 /* */
1318 /* CALLED BY */
1319 /* */
1320 /* _gx_utility_bidi_paragraph_reorder */
1321 /* */
1322 /* RELEASE HISTORY */
1323 /* */
1324 /* DATE NAME DESCRIPTION */
1325 /* */
1326 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1327 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1328 /* resulting in version 6.1 */
1329 /* */
1330 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_4(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1331 static UINT _gx_utility_bidi_weak_type_resolve_4(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1332 {
1333 INT run_index;
1334 INT text_index;
1335 GX_UBYTE pre_type = 0;
1336 GX_UBYTE follow_type = 0;
1337 GX_BIDI_UNIT *unit;
1338
1339 /* A single ES between two EN, change to EN,
1340 a single CS between two EN, change to EN,
1341 a single CS between two AN, change to AN. */
1342
1343 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1344 {
1345 if (run_index + 1 < entry -> gx_bidi_isolate_run_index_count)
1346 {
1347 text_index = entry -> gx_bidi_isolate_run_index_list[run_index + 1];
1348 follow_type = context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type;
1349 }
1350
1351 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1352 unit = &context -> gx_bidi_context_unit_list[text_index];
1353
1354 if (pre_type == follow_type)
1355 {
1356 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ES &&
1357 pre_type == GX_BIDI_CHARACTER_TYPE_EN)
1358 {
1359 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1360 }
1361 else if ((unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_CS) &&
1362 (pre_type == GX_BIDI_CHARACTER_TYPE_EN || pre_type == GX_BIDI_CHARACTER_TYPE_AN))
1363 {
1364 unit -> gx_bidi_unit_type = pre_type;
1365 }
1366 run_index++;
1367 }
1368 else
1369 {
1370 pre_type = unit -> gx_bidi_unit_type;
1371 }
1372 }
1373
1374 return GX_SUCCESS;
1375 }
1376
1377 /**************************************************************************/
1378 /* */
1379 /* FUNCTION RELEASE */
1380 /* */
1381 /* _gx_utility_bidi_weak_type_resolve_5 PORTABLE C */
1382 /* 6.1 */
1383 /* AUTHOR */
1384 /* */
1385 /* Kenneth Maxwell, Microsoft Corporation */
1386 /* */
1387 /* DESCRIPTION */
1388 /* */
1389 /* Internal helper function to apply rule 5 to weak characters in an */
1390 /* isolate run sequence. */
1391 /* */
1392 /* INPUT */
1393 /* */
1394 /* context Bidi information control block*/
1395 /* entry Pointer to an isolate run */
1396 /* sequence */
1397 /* */
1398 /* OUTPUT */
1399 /* */
1400 /* status Completion status */
1401 /* */
1402 /* CALLS */
1403 /* */
1404 /* None */
1405 /* */
1406 /* CALLED BY */
1407 /* */
1408 /* _gx_utility_bidi_paragraph_reorder */
1409 /* */
1410 /* RELEASE HISTORY */
1411 /* */
1412 /* DATE NAME DESCRIPTION */
1413 /* */
1414 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1415 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1416 /* resulting in version 6.1 */
1417 /* */
1418 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_5(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1419 static UINT _gx_utility_bidi_weak_type_resolve_5(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1420 {
1421
1422 INT run_index;
1423 INT pre_run_index;
1424 INT text_index;
1425 GX_BOOL do_change = GX_FALSE;
1426 GX_BIDI_UNIT *unit;
1427
1428 /* A sequence of ETs adjacent to EN, change to all ENs. */
1429 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1430 {
1431 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1432 unit = &context -> gx_bidi_context_unit_list[text_index];
1433
1434 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_EN)
1435 {
1436 do_change = GX_TRUE;
1437
1438 pre_run_index = run_index - 1;
1439
1440 while (pre_run_index >= 0)
1441 {
1442 text_index = entry -> gx_bidi_isolate_run_index_list[pre_run_index--];
1443 unit = &context -> gx_bidi_context_unit_list[text_index];
1444
1445 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ET)
1446 {
1447 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1448 }
1449 else
1450 {
1451 break;
1452 }
1453 }
1454 }
1455 else if (do_change && unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ET)
1456 {
1457 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1458 }
1459 else
1460 {
1461 do_change = GX_FALSE;
1462 }
1463 }
1464 return GX_SUCCESS;
1465 }
1466
1467 /**************************************************************************/
1468 /* */
1469 /* FUNCTION RELEASE */
1470 /* */
1471 /* _gx_utility_bidi_weak_type_resolve_6 PORTABLE C */
1472 /* 6.1 */
1473 /* AUTHOR */
1474 /* */
1475 /* Kenneth Maxwell, Microsoft Corporation */
1476 /* */
1477 /* DESCRIPTION */
1478 /* */
1479 /* Internal helper function to apply rule 6 to weak characters in an */
1480 /* isolate run sequence. */
1481 /* */
1482 /* INPUT */
1483 /* */
1484 /* context Bidi information control block*/
1485 /* entry Pointer to an isolate run */
1486 /* sequence */
1487 /* */
1488 /* OUTPUT */
1489 /* */
1490 /* status Completion status */
1491 /* */
1492 /* CALLS */
1493 /* */
1494 /* None */
1495 /* */
1496 /* CALLED BY */
1497 /* */
1498 /* _gx_utility_bidi_paragraph_reorder */
1499 /* */
1500 /* RELEASE HISTORY */
1501 /* */
1502 /* DATE NAME DESCRIPTION */
1503 /* */
1504 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1505 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1506 /* resulting in version 6.1 */
1507 /* */
1508 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_6(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1509 static UINT _gx_utility_bidi_weak_type_resolve_6(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1510 {
1511 INT run_index;
1512 INT text_index;
1513 GX_BIDI_UNIT *unit;
1514
1515 /* ES, CS, ET change to ON. */
1516 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1517 {
1518 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1519 unit = &context -> gx_bidi_context_unit_list[text_index];
1520
1521 switch (unit -> gx_bidi_unit_type)
1522 {
1523 case GX_BIDI_CHARACTER_TYPE_ES:
1524 case GX_BIDI_CHARACTER_TYPE_CS:
1525 case GX_BIDI_CHARACTER_TYPE_ET:
1526 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_ON;
1527 break;
1528 }
1529 }
1530 return GX_SUCCESS;
1531 }
1532
1533 /**************************************************************************/
1534 /* */
1535 /* FUNCTION RELEASE */
1536 /* */
1537 /* _gx_utility_bidi_weak_type_resolve_7 PORTABLE C */
1538 /* 6.1 */
1539 /* AUTHOR */
1540 /* */
1541 /* Kenneth Maxwell, Microsoft Corporation */
1542 /* */
1543 /* DESCRIPTION */
1544 /* */
1545 /* Internal helper function to apply rule 7 to weak characters in an */
1546 /* isolate run sequence. */
1547 /* */
1548 /* INPUT */
1549 /* */
1550 /* context Bidi information control block*/
1551 /* entry Pointer to an isolate run */
1552 /* sequence */
1553 /* */
1554 /* OUTPUT */
1555 /* */
1556 /* status Completion status */
1557 /* */
1558 /* CALLS */
1559 /* */
1560 /* None */
1561 /* */
1562 /* CALLED BY */
1563 /* */
1564 /* _gx_utility_bidi_paragraph_reorder */
1565 /* */
1566 /* RELEASE HISTORY */
1567 /* */
1568 /* DATE NAME DESCRIPTION */
1569 /* */
1570 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1571 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1572 /* resulting in version 6.1 */
1573 /* */
1574 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_7(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1575 static UINT _gx_utility_bidi_weak_type_resolve_7(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1576 {
1577 INT run_index;
1578 INT text_index;
1579 GX_BOOL do_change = GX_FALSE;
1580 GX_BIDI_UNIT *unit;
1581
1582 /* Search backward from each EN until first strong type (R, L, or SOS) is found, if
1583 L is found, change type to L.*/
1584 if (entry -> gx_bidi_isolate_run_sos == GX_BIDI_CHARACTER_TYPE_L)
1585 {
1586 do_change = GX_TRUE;
1587 }
1588 else
1589 {
1590 do_change = GX_FALSE;
1591 }
1592
1593 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1594 {
1595 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1596 unit = &context -> gx_bidi_context_unit_list[text_index];
1597
1598 switch (unit -> gx_bidi_unit_type)
1599 {
1600 case GX_BIDI_CHARACTER_TYPE_R:
1601 do_change = GX_FALSE;
1602 break;
1603
1604 case GX_BIDI_CHARACTER_TYPE_L:
1605 do_change = GX_TRUE;
1606 break;
1607
1608 default:
1609 if (do_change && unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_EN)
1610 {
1611 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
1612 }
1613 break;
1614 }
1615 }
1616 return GX_SUCCESS;
1617 }
1618
1619 /**************************************************************************/
1620 /* */
1621 /* FUNCTION RELEASE */
1622 /* */
1623 /* _gx_utility_bidi_bracket_pair_search PORTABLE C */
1624 /* 6.1 */
1625 /* AUTHOR */
1626 /* */
1627 /* Kenneth Maxwell, Microsoft Corporation */
1628 /* */
1629 /* DESCRIPTION */
1630 /* */
1631 /* Internal helper function to calculate bracket pairs in an isolate */
1632 /* run sequence. */
1633 /* */
1634 /* INPUT */
1635 /* */
1636 /* context Bidi information control block*/
1637 /* entry Pointer to an isolate run */
1638 /* sequence */
1639 /* return_bracket_pair Buffer to load bracket pair */
1640 /* list */
1641 /* return_pair_count Buffer to load the number of */
1642 /* bracket pair characters */
1643 /* */
1644 /* OUTPUT */
1645 /* */
1646 /* status Completion status */
1647 /* */
1648 /* CALLS */
1649 /* */
1650 /* None */
1651 /* */
1652 /* CALLED BY */
1653 /* */
1654 /* _gx_utility_bidi_neutral_type_resolve_0 */
1655 /* */
1656 /* RELEASE HISTORY */
1657 /* */
1658 /* DATE NAME DESCRIPTION */
1659 /* */
1660 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1661 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1662 /* resulting in version 6.1 */
1663 /* */
1664 /**************************************************************************/
_gx_utility_bidi_bracket_pair_search(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry,INT ** return_bracket_pair,INT * return_pair_count)1665 static UINT _gx_utility_bidi_bracket_pair_search(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry, INT **return_bracket_pair, INT *return_pair_count)
1666 {
1667 ULONG *stack;
1668 ULONG *bracket_entry;
1669 ULONG *last_bracket_entry = GX_NULL;
1670 INT top = 0;
1671 INT run_index;
1672 INT text_index;
1673 ULONG character;
1674 INT *bracket_pair = *return_bracket_pair;
1675 INT bracket_pair_count = 0;
1676 GX_BIDI_BRACKET_PAIR pair;
1677 UINT buffer_index;
1678 INT depth;
1679 INT temp = 0;
1680 GX_BIDI_UNIT *unit;
1681
1682 stack = (ULONG *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1683 buffer_index = context -> gx_bidi_context_buffer_index;
1684 bracket_entry = stack;
1685
1686 for (run_index = 0; run_index < (INT)entry -> gx_bidi_isolate_run_index_count; run_index++)
1687 {
1688 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1689 unit = &context -> gx_bidi_context_unit_list[text_index];
1690
1691 if (unit -> gx_bidi_unit_type != GX_BIDI_CHARACTER_TYPE_ON)
1692 {
1693 continue;
1694 }
1695
1696 character = unit -> gx_bidi_unit_code;
1697 _gx_utility_bidi_bracket_pair_get(character, &pair);
1698
1699 if (character == pair.gx_bidi_bracket_pair_open)
1700 {
1701 if (top >= 63)
1702 {
1703 /* Stop processing for the remainder to the isolating run sequence. */
1704 break;
1705 }
1706
1707 last_bracket_entry = bracket_entry;
1708 *bracket_entry = (ULONG)run_index;
1709 bracket_entry++;
1710 top++;
1711 buffer_index += (INT)(sizeof(ULONG));
1712 if (buffer_index > context -> gx_bidi_context_buffer_size)
1713 {
1714 return GX_INVALID_MEMORY_SIZE;
1715 }
1716 }
1717 else if (last_bracket_entry && (character == pair.gx_bidi_bracket_pair_close))
1718 {
1719 depth = 0;
1720
1721 while (top - depth > 0)
1722 {
1723 text_index = entry -> gx_bidi_isolate_run_index_list[*(last_bracket_entry - depth)];
1724 unit = &context -> gx_bidi_context_unit_list[text_index];
1725
1726 if (unit -> gx_bidi_unit_code == pair.gx_bidi_bracket_pair_open ||
1727 (unit -> gx_bidi_unit_code == 0x2329 && pair.gx_bidi_bracket_pair_open == 0x3008) ||
1728 (unit -> gx_bidi_unit_code == 0x3008 && pair.gx_bidi_bracket_pair_open == 0x2329))
1729 {
1730 bracket_pair[bracket_pair_count++] = (INT)(*(last_bracket_entry - depth));
1731 bracket_pair[bracket_pair_count++] = run_index;
1732 depth++;
1733
1734 last_bracket_entry -= depth;
1735 bracket_entry -= depth;
1736 top -= depth;
1737 buffer_index -= sizeof(ULONG) * (UINT)depth;
1738 break;
1739 }
1740 depth++;
1741 }
1742 }
1743 }
1744
1745 /* Sort list of pairs of text position in ascending order
1746 based on the text position of the openging paired bracket. */
1747 for (run_index = 0; run_index < bracket_pair_count - 2; run_index += 2)
1748 {
1749 for (text_index = run_index + 2; text_index < bracket_pair_count; text_index += 2)
1750 {
1751 if (bracket_pair[run_index] > bracket_pair[text_index])
1752 {
1753 temp = bracket_pair[run_index];
1754 bracket_pair[run_index] = bracket_pair[text_index];
1755 bracket_pair[text_index] = temp;
1756
1757 temp = bracket_pair[run_index + 1];
1758 bracket_pair[run_index + 1] = bracket_pair[text_index + 1];
1759 bracket_pair[text_index + 1] = temp;
1760 }
1761 }
1762 }
1763
1764 *return_pair_count = bracket_pair_count;
1765 return GX_SUCCESS;
1766 }
1767
1768 /**************************************************************************/
1769 /* */
1770 /* FUNCTION RELEASE */
1771 /* */
1772 /* _gx_utility_bidi_neutral_type_resolve_0 PORTABLE C */
1773 /* 6.1 */
1774 /* AUTHOR */
1775 /* */
1776 /* Kenneth Maxwell, Microsoft Corporation */
1777 /* */
1778 /* DESCRIPTION */
1779 /* */
1780 /* Internal helper function to apply rule 0 to neutral characters in an*/
1781 /* isolate run sequence. */
1782 /* */
1783 /* INPUT */
1784 /* */
1785 /* context Bidi information control block*/
1786 /* entry Pointer to an isolate run */
1787 /* sequence */
1788 /* */
1789 /* OUTPUT */
1790 /* */
1791 /* status Completion status */
1792 /* */
1793 /* CALLS */
1794 /* */
1795 /* None */
1796 /* */
1797 /* CALLED BY */
1798 /* */
1799 /* _gx_utility_bidi_paragraph_reorder */
1800 /* */
1801 /* RELEASE HISTORY */
1802 /* */
1803 /* DATE NAME DESCRIPTION */
1804 /* */
1805 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1806 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1807 /* resulting in version 6.1 */
1808 /* */
1809 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_0(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1810 static UINT _gx_utility_bidi_neutral_type_resolve_0(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1811 {
1812 UINT status;
1813 INT index = 0;
1814 INT start_index;
1815 INT end_index;
1816 INT text_index;
1817 INT *bracket_pair;
1818 INT bracket_pair_count = 0;
1819 GX_UBYTE embedding_type;
1820 GX_UBYTE oppsite_type;
1821 GX_UBYTE type;
1822 GX_BOOL bracket_type_changed;
1823 GX_BOOL strong_type_found;
1824 GX_BIDI_UNIT *unit;
1825
1826 if (!context -> gx_bidi_context_bracket_pair_size)
1827 {
1828 return GX_SUCCESS;
1829 }
1830
1831 bracket_pair = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1832 context -> gx_bidi_context_buffer_index += context -> gx_bidi_context_bracket_pair_size;
1833
1834 if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
1835 {
1836 return GX_INVALID_MEMORY_SIZE;
1837 }
1838
1839 status = _gx_utility_bidi_bracket_pair_search(context, entry, &bracket_pair, &bracket_pair_count);
1840
1841 if (status != GX_SUCCESS)
1842 {
1843 return GX_SUCCESS;
1844 }
1845
1846 if (bracket_pair_count > 0)
1847 {
1848 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[0]];
1849 unit = &context -> gx_bidi_context_unit_list[text_index];
1850
1851 if ((unit -> gx_bidi_unit_level & 0x01) == 0)
1852 {
1853 embedding_type = GX_BIDI_CHARACTER_TYPE_L;
1854 oppsite_type = GX_BIDI_CHARACTER_TYPE_R;
1855 }
1856 else
1857 {
1858 embedding_type = GX_BIDI_CHARACTER_TYPE_R;
1859 oppsite_type = GX_BIDI_CHARACTER_TYPE_L;
1860 }
1861 }
1862
1863 for (index = 0; index < bracket_pair_count; index += 2)
1864 {
1865 strong_type_found = GX_FALSE;
1866 bracket_type_changed = GX_FALSE;
1867 for (start_index = bracket_pair[index] + 1; start_index < bracket_pair[index + 1]; start_index++)
1868 {
1869 text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1870 unit = &context -> gx_bidi_context_unit_list[text_index];
1871
1872 type = unit -> gx_bidi_unit_type;
1873
1874 if (type == GX_BIDI_CHARACTER_TYPE_EN ||
1875 type == GX_BIDI_CHARACTER_TYPE_AN)
1876 {
1877 /* Within this scope, bidirectional types EN and AN are treated as R. */
1878 type = GX_BIDI_CHARACTER_TYPE_R;
1879 }
1880
1881 if (type == GX_BIDI_CHARACTER_TYPE_L ||
1882 type == GX_BIDI_CHARACTER_TYPE_R)
1883 {
1884 /* If any strong type (either L or R) matching the embedding direction is found,
1885 set the type for both brackets in the pair to match the embedding direction. */
1886 strong_type_found = GX_TRUE;
1887
1888 if (type == embedding_type)
1889 {
1890 bracket_type_changed = GX_TRUE;
1891
1892 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index]];
1893 unit = &context -> gx_bidi_context_unit_list[text_index];
1894 unit -> gx_bidi_unit_type = embedding_type;
1895
1896 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index + 1]];
1897 unit = &context -> gx_bidi_context_unit_list[text_index];
1898 unit -> gx_bidi_unit_type = embedding_type;
1899 break;
1900 }
1901 }
1902 }
1903
1904 if (!bracket_type_changed)
1905 {
1906 if (strong_type_found)
1907 {
1908 bracket_type_changed = GX_TRUE;
1909
1910 end_index = bracket_pair[index] - 1;
1911 strong_type_found = GX_FALSE;
1912 while (end_index >= 0)
1913 {
1914 text_index = entry -> gx_bidi_isolate_run_index_list[end_index];
1915 unit = &context -> gx_bidi_context_unit_list[text_index];
1916
1917 /* Search baackward until first strong type is found. */
1918 type = unit -> gx_bidi_unit_type;
1919
1920 if (type == GX_BIDI_CHARACTER_TYPE_EN ||
1921 type == GX_BIDI_CHARACTER_TYPE_AN)
1922 {
1923 /* Within this scope, bidirectional types EN and AN are treated as R. */
1924 type = GX_BIDI_CHARACTER_TYPE_R;
1925 }
1926
1927 if (type == GX_BIDI_CHARACTER_TYPE_R ||
1928 type == GX_BIDI_CHARACTER_TYPE_L)
1929 {
1930 strong_type_found = GX_TRUE;
1931 break;
1932 }
1933
1934 end_index--;
1935 }
1936
1937 if (!strong_type_found)
1938 {
1939 type = entry -> gx_bidi_isolate_run_sos;
1940 }
1941
1942 if (type != oppsite_type)
1943 {
1944 type = embedding_type;
1945 }
1946
1947 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index]];
1948 unit = &context -> gx_bidi_context_unit_list[text_index];
1949 unit -> gx_bidi_unit_type = type;
1950
1951 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index + 1]];
1952 unit = &context -> gx_bidi_context_unit_list[text_index];
1953 unit -> gx_bidi_unit_type = type;
1954 }
1955 }
1956
1957 if (bracket_type_changed)
1958 {
1959 /* Any number of characters that had original bidirectional character type NSM that immediately follow a
1960 paired bracket which changed to L or R under N0 should change to match the type of their preceding bracket.*/
1961 start_index = bracket_pair[index] + 1;
1962 while (start_index < bracket_pair[index + 1])
1963 {
1964 end_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1965 unit = &context -> gx_bidi_context_unit_list[end_index];
1966
1967 if (unit -> gx_bidi_unit_org_type == GX_BIDI_CHARACTER_TYPE_NSM)
1968 {
1969 unit -> gx_bidi_unit_type = type;
1970 }
1971 else
1972 {
1973 break;
1974 }
1975 start_index++;
1976 }
1977
1978 start_index = bracket_pair[index + 1] + 1;
1979 while (start_index < (INT)entry -> gx_bidi_isolate_run_index_count)
1980 {
1981 text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1982 unit = &context -> gx_bidi_context_unit_list[text_index];
1983
1984 if (unit -> gx_bidi_unit_org_type == GX_BIDI_CHARACTER_TYPE_NSM)
1985 {
1986 unit -> gx_bidi_unit_type = type;
1987 }
1988 else
1989 {
1990 break;
1991 }
1992 start_index++;
1993 }
1994 }
1995 }
1996
1997 context -> gx_bidi_context_buffer_index -= context -> gx_bidi_context_bracket_pair_size;
1998
1999 return GX_SUCCESS;
2000 }
2001
2002 /**************************************************************************/
2003 /* */
2004 /* FUNCTION RELEASE */
2005 /* */
2006 /* _gx_utility_bidi_neutral_type_resolve_1 PORTABLE C */
2007 /* 6.1 */
2008 /* AUTHOR */
2009 /* */
2010 /* Kenneth Maxwell, Microsoft Corporation */
2011 /* */
2012 /* DESCRIPTION */
2013 /* */
2014 /* Internal helper function to apply rule 1 to neutral characters in an*/
2015 /* isolate run sequence. */
2016 /* */
2017 /* INPUT */
2018 /* */
2019 /* context Bidi information control block*/
2020 /* entry Pointer to an isolate run */
2021 /* sequence */
2022 /* */
2023 /* OUTPUT */
2024 /* */
2025 /* status Completion status */
2026 /* */
2027 /* CALLS */
2028 /* */
2029 /* None */
2030 /* */
2031 /* CALLED BY */
2032 /* */
2033 /* _gx_utility_bidi_paragraph_reorder */
2034 /* */
2035 /* RELEASE HISTORY */
2036 /* */
2037 /* DATE NAME DESCRIPTION */
2038 /* */
2039 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2040 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2041 /* resulting in version 6.1 */
2042 /* */
2043 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_1(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2044 static UINT _gx_utility_bidi_neutral_type_resolve_1(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2045 {
2046 INT run_index;
2047 INT start_index = 0;
2048 INT text_index;
2049 GX_UBYTE pre_type = entry -> gx_bidi_isolate_run_sos;
2050 GX_UBYTE follow_type;
2051 GX_UBYTE type;
2052
2053 /* A sequence of NIs takes the direction of the surrounding strong text if the text
2054 on both sides has the same direction. */
2055 for (run_index = 0; run_index <= (INT)entry -> gx_bidi_isolate_run_index_count; run_index++)
2056 {
2057 if (run_index < (INT)entry -> gx_bidi_isolate_run_index_count)
2058 {
2059 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2060 type = context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type;
2061 }
2062 else
2063 {
2064 type = entry -> gx_bidi_isolate_run_eos;
2065 }
2066
2067 switch (type)
2068 {
2069 case GX_BIDI_CHARACTER_TYPE_B:
2070 case GX_BIDI_CHARACTER_TYPE_S:
2071 case GX_BIDI_CHARACTER_TYPE_WS:
2072 case GX_BIDI_CHARACTER_TYPE_ON:
2073 case GX_BIDI_CHARACTER_TYPE_FSI:
2074 case GX_BIDI_CHARACTER_TYPE_LRI:
2075 case GX_BIDI_CHARACTER_TYPE_RLI:
2076 case GX_BIDI_CHARACTER_TYPE_PDI:
2077 break;
2078
2079 default:
2080 follow_type = type;
2081
2082 if (follow_type == GX_BIDI_CHARACTER_TYPE_EN ||
2083 follow_type == GX_BIDI_CHARACTER_TYPE_AN)
2084 {
2085 follow_type = GX_BIDI_CHARACTER_TYPE_R;
2086 }
2087
2088 if (pre_type == follow_type)
2089 {
2090 while (start_index < run_index)
2091 {
2092 text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
2093
2094 context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type = pre_type;
2095 start_index++;
2096 }
2097 }
2098 pre_type = follow_type;
2099 start_index = run_index + 1;
2100 break;
2101 }
2102 }
2103
2104 return GX_SUCCESS;
2105 }
2106
2107 /**************************************************************************/
2108 /* */
2109 /* FUNCTION RELEASE */
2110 /* */
2111 /* _gx_utility_bidi_neutral_type_resolve_2 PORTABLE C */
2112 /* 6.1 */
2113 /* AUTHOR */
2114 /* */
2115 /* Kenneth Maxwell, Microsoft Corporation */
2116 /* */
2117 /* DESCRIPTION */
2118 /* */
2119 /* Internal helper function to apply rule 2 to neutral characters in an*/
2120 /* isolate run sequence. */
2121 /* */
2122 /* INPUT */
2123 /* */
2124 /* context Bidi information control block*/
2125 /* entry Pointer to an isolate run */
2126 /* sequence */
2127 /* */
2128 /* OUTPUT */
2129 /* */
2130 /* status Completion status */
2131 /* */
2132 /* CALLS */
2133 /* */
2134 /* None */
2135 /* */
2136 /* CALLED BY */
2137 /* */
2138 /* _gx_utility_bidi_paragraph_reorder */
2139 /* */
2140 /* RELEASE HISTORY */
2141 /* */
2142 /* DATE NAME DESCRIPTION */
2143 /* */
2144 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2145 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2146 /* resulting in version 6.1 */
2147 /* */
2148 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_2(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2149 static UINT _gx_utility_bidi_neutral_type_resolve_2(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2150 {
2151 INT run_index = 0;
2152 INT text_index;
2153 GX_BIDI_UNIT *unit;
2154
2155 /* Any remaining NIs take the embedding direction. */
2156 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
2157 {
2158 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2159 unit = &context -> gx_bidi_context_unit_list[text_index];
2160
2161 switch (unit -> gx_bidi_unit_type)
2162 {
2163 case GX_BIDI_CHARACTER_TYPE_B:
2164 case GX_BIDI_CHARACTER_TYPE_S:
2165 case GX_BIDI_CHARACTER_TYPE_WS:
2166 case GX_BIDI_CHARACTER_TYPE_ON:
2167 case GX_BIDI_CHARACTER_TYPE_FSI:
2168 case GX_BIDI_CHARACTER_TYPE_LRI:
2169 case GX_BIDI_CHARACTER_TYPE_RLI:
2170 case GX_BIDI_CHARACTER_TYPE_PDI:
2171 if ((unit -> gx_bidi_unit_level & 0x01) == 0)
2172 {
2173 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
2174 }
2175 else
2176 {
2177 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
2178 }
2179 break;
2180 }
2181 }
2182
2183 return GX_SUCCESS;
2184 }
2185
2186 /**************************************************************************/
2187 /* */
2188 /* FUNCTION RELEASE */
2189 /* */
2190 /* _gx_utility_bidi_implicit_level_resolve PORTABLE C */
2191 /* 6.1 */
2192 /* AUTHOR */
2193 /* */
2194 /* Kenneth Maxwell, Microsoft Corporation */
2195 /* */
2196 /* DESCRIPTION */
2197 /* */
2198 /* Internal helper function to increase the embedding level of text */
2199 /* based on the resolved character type. */
2200 /* */
2201 /* INPUT */
2202 /* */
2203 /* context Bidi information control block*/
2204 /* entry Pointer to an isolate run */
2205 /* sequence */
2206 /* */
2207 /* OUTPUT */
2208 /* */
2209 /* status Completion status */
2210 /* */
2211 /* CALLS */
2212 /* */
2213 /* None */
2214 /* */
2215 /* CALLED BY */
2216 /* */
2217 /* _gx_utility_bidi_paragraph_reorder */
2218 /* */
2219 /* RELEASE HISTORY */
2220 /* */
2221 /* DATE NAME DESCRIPTION */
2222 /* */
2223 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2224 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2225 /* resulting in version 6.1 */
2226 /* */
2227 /**************************************************************************/
_gx_utility_bidi_implicit_level_resolve(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2228 static UINT _gx_utility_bidi_implicit_level_resolve(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2229 {
2230 INT run_index;
2231 INT text_index;
2232 GX_BIDI_UNIT *unit;
2233
2234 /* Any remaining NIs take the embedding direction. */
2235 for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
2236 {
2237 text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2238 unit = &context -> gx_bidi_context_unit_list[text_index];
2239
2240 if ((unit -> gx_bidi_unit_level & 0x01) == 0)
2241 {
2242 /* For all characers with an even embedding level,
2243 those of type R go up ove level and those of type AN or EN go up two levels. */
2244 switch (unit -> gx_bidi_unit_type)
2245 {
2246 case GX_BIDI_CHARACTER_TYPE_R:
2247 unit -> gx_bidi_unit_level++;
2248 break;
2249
2250 case GX_BIDI_CHARACTER_TYPE_AN:
2251 case GX_BIDI_CHARACTER_TYPE_EN:
2252 unit -> gx_bidi_unit_level = (GX_UBYTE)(unit -> gx_bidi_unit_level + 2);
2253 break;
2254 }
2255 }
2256
2257 if ((unit -> gx_bidi_unit_level & 0x01) == 1)
2258 {
2259 /* For all characers with an odd embedding level,
2260 those of type L, EN and AN go up ove level. */
2261 switch (unit -> gx_bidi_unit_type)
2262 {
2263 case GX_BIDI_CHARACTER_TYPE_L:
2264 case GX_BIDI_CHARACTER_TYPE_EN:
2265 case GX_BIDI_CHARACTER_TYPE_AN:
2266 unit -> gx_bidi_unit_level++;
2267 break;
2268 }
2269 }
2270 }
2271
2272 return GX_SUCCESS;
2273 }
2274
2275 /**************************************************************************/
2276 /* */
2277 /* FUNCTION RELEASE */
2278 /* */
2279 /* _gx_utility_bidi_isolate_run_sequences_resolve PORTABLE C */
2280 /* 6.1 */
2281 /* AUTHOR */
2282 /* */
2283 /* Kenneth Maxwell, Microsoft Corporation */
2284 /* */
2285 /* DESCRIPTION */
2286 /* */
2287 /* Internal helper function to determine the embedding levels of the */
2288 /* text. */
2289 /* */
2290 /* INPUT */
2291 /* */
2292 /* context Bidi information control block*/
2293 /* */
2294 /* OUTPUT */
2295 /* */
2296 /* status Completion status */
2297 /* */
2298 /* CALLS */
2299 /* */
2300 /* None */
2301 /* */
2302 /* CALLED BY */
2303 /* */
2304 /* _gx_utility_bidi_paragraph_reorder */
2305 /* */
2306 /* RELEASE HISTORY */
2307 /* */
2308 /* DATE NAME DESCRIPTION */
2309 /* */
2310 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2311 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2312 /* resulting in version 6.1 */
2313 /* */
2314 /**************************************************************************/
_gx_utility_bidi_isolate_run_sequences_resolve(GX_BIDI_CONTEXT * context)2315 static UINT _gx_utility_bidi_isolate_run_sequences_resolve(GX_BIDI_CONTEXT *context)
2316 {
2317 UINT status = GX_SUCCESS;
2318
2319 GX_BIDI_ISOLATE_RUN *entry = context -> gx_bidi_context_isolate_runs;
2320
2321 while (entry)
2322 {
2323 status = _gx_utility_bidi_weak_type_resolve_1(context, entry);
2324
2325 if (status != GX_SUCCESS)
2326 {
2327 break;
2328 }
2329
2330 status = _gx_utility_bidi_weak_type_resolve_2_3(context, entry);
2331
2332 if (status != GX_SUCCESS)
2333 {
2334 break;
2335 }
2336 status = _gx_utility_bidi_weak_type_resolve_4(context, entry);
2337
2338 if (status != GX_SUCCESS)
2339 {
2340 break;
2341 }
2342 status = _gx_utility_bidi_weak_type_resolve_5(context, entry);
2343
2344 if (status != GX_SUCCESS)
2345 {
2346 break;
2347 }
2348 status = _gx_utility_bidi_weak_type_resolve_6(context, entry);
2349
2350 if (status != GX_SUCCESS)
2351 {
2352 break;
2353 }
2354
2355 status = _gx_utility_bidi_weak_type_resolve_7(context, entry);
2356
2357 if (status != GX_SUCCESS)
2358 {
2359 break;
2360 }
2361
2362 /* Process bracket pairs. */
2363 status = _gx_utility_bidi_neutral_type_resolve_0(context, entry);
2364
2365 if (status != GX_SUCCESS)
2366 {
2367 break;
2368 }
2369
2370 status = _gx_utility_bidi_neutral_type_resolve_1(context, entry);
2371
2372 if (status != GX_SUCCESS)
2373 {
2374 break;
2375 }
2376
2377 status = _gx_utility_bidi_neutral_type_resolve_2(context, entry);
2378
2379 if (status != GX_SUCCESS)
2380 {
2381 break;
2382 }
2383
2384 status = _gx_utility_bidi_implicit_level_resolve(context, entry);
2385
2386 if (status != GX_SUCCESS)
2387 {
2388 break;
2389 }
2390
2391 entry = entry -> gx_bidi_isolate_run_next;
2392 }
2393
2394 return status;
2395 }
2396
2397 /**************************************************************************/
2398 /* */
2399 /* FUNCTION RELEASE */
2400 /* */
2401 /* _gx_utility_bidi_reordering_resolve_1 PORTABLE C */
2402 /* 6.1.9 */
2403 /* AUTHOR */
2404 /* */
2405 /* Kenneth Maxwell, Microsoft Corporation */
2406 /* */
2407 /* DESCRIPTION */
2408 /* */
2409 /* Internal helper function to reset the embedding level of some */
2410 /* characters in specified text block. */
2411 /* */
2412 /* INPUT */
2413 /* */
2414 /* context Bidi information control block*/
2415 /* */
2416 /* OUTPUT */
2417 /* */
2418 /* status Completion status */
2419 /* start_index Start index of the text block */
2420 /* end_index End index of the text block */
2421 /* */
2422 /* CALLS */
2423 /* */
2424 /* None */
2425 /* */
2426 /* CALLED BY */
2427 /* */
2428 /* _gx_utility_bidi_paragraph_reorder */
2429 /* */
2430 /* RELEASE HISTORY */
2431 /* */
2432 /* DATE NAME DESCRIPTION */
2433 /* */
2434 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2435 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2436 /* resulting in version 6.1 */
2437 /* 10-15-2021 Kenneth Maxwell Modified comment(s), */
2438 /* corrected logic, */
2439 /* resulting in version 6.1.9 */
2440 /* */
2441 /**************************************************************************/
_gx_utility_bidi_reordering_resolve_1(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)2442 static UINT _gx_utility_bidi_reordering_resolve_1(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
2443 {
2444 INT index;
2445 INT pre_index;
2446 GX_BOOL check_before;
2447 GX_BIDI_UNIT *unit;
2448 GX_BIDI_UNIT *pre_unit;
2449 USHORT mirror;
2450
2451 for (index = start_index; index <= end_index; index++)
2452 {
2453 check_before = GX_FALSE;
2454 unit = &context -> gx_bidi_context_unit_list[index];
2455
2456 switch (unit -> gx_bidi_unit_org_type)
2457 {
2458 case GX_BIDI_CHARACTER_TYPE_S:
2459 case GX_BIDI_CHARACTER_TYPE_B:
2460 /* Reset segment separators and paragraph separators to the paragraph embedding level. */
2461 unit -> gx_bidi_unit_level = context -> gx_bidi_context_base_level;
2462 check_before = GX_TRUE;
2463 break;
2464
2465 default:
2466 if (index == context -> gx_bidi_context_unit_count - 1)
2467 {
2468 index = context -> gx_bidi_context_unit_count;
2469 check_before = GX_TRUE;
2470 }
2471 break;
2472 }
2473
2474 if (check_before)
2475 {
2476 /* Any sequence of whitespace or isolate formatting characters preceding a
2477 segment/paragraph separator or at the end of the text, reset to paragraph level. */
2478 pre_index = index - 1;
2479 pre_unit = &context -> gx_bidi_context_unit_list[pre_index];
2480 while (pre_index >= 0)
2481 {
2482 if (pre_unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_BN)
2483 {
2484 pre_index--;
2485 pre_unit--;
2486 continue;
2487 }
2488
2489 switch (pre_unit -> gx_bidi_unit_org_type)
2490 {
2491 case GX_BIDI_CHARACTER_TYPE_WS:
2492 case GX_BIDI_CHARACTER_TYPE_FSI:
2493 case GX_BIDI_CHARACTER_TYPE_LRI:
2494 case GX_BIDI_CHARACTER_TYPE_RLI:
2495 case GX_BIDI_CHARACTER_TYPE_PDI:
2496 pre_unit -> gx_bidi_unit_level = context -> gx_bidi_context_base_level;
2497 break;
2498
2499 default:
2500 pre_index = -1;
2501 break;
2502 }
2503 pre_index--;
2504 pre_unit--;
2505 }
2506 }
2507
2508 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_R &&
2509 unit -> gx_bidi_unit_code < 0xffff)
2510 {
2511 /* Mirror */
2512 _gx_utility_bidi_mirroring_get((USHORT)unit -> gx_bidi_unit_code, &mirror);
2513
2514 if (mirror)
2515 {
2516 unit -> gx_bidi_unit_code = mirror;
2517 }
2518 }
2519 }
2520 return GX_SUCCESS;
2521 }
2522
2523 /**************************************************************************/
2524 /* */
2525 /* FUNCTION RELEASE */
2526 /* */
2527 /* _gx_utility_bidi_reordering_resolve_2 PORTABLE C */
2528 /* 6.1 */
2529 /* AUTHOR */
2530 /* */
2531 /* Kenneth Maxwell, Microsoft Corporation */
2532 /* */
2533 /* DESCRIPTION */
2534 /* */
2535 /* Internal helper function to reverse text for the specified text */
2536 /* block. */
2537 /* */
2538 /* INPUT */
2539 /* */
2540 /* context Bidi information control block*/
2541 /* */
2542 /* OUTPUT */
2543 /* */
2544 /* status Completion status */
2545 /* start_index Start index of the text block */
2546 /* end_index End index of the text block */
2547 /* */
2548 /* CALLS */
2549 /* */
2550 /* None */
2551 /* */
2552 /* CALLED BY */
2553 /* */
2554 /* _gx_utility_bidi_paragraph_reorder */
2555 /* */
2556 /* RELEASE HISTORY */
2557 /* */
2558 /* DATE NAME DESCRIPTION */
2559 /* */
2560 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2561 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2562 /* resulting in version 6.1 */
2563 /* */
2564 /**************************************************************************/
_gx_utility_bidi_reordering_resolve_2(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)2565 static UINT _gx_utility_bidi_reordering_resolve_2(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
2566 {
2567 INT max_level;
2568 INT min_level;
2569 INT level;
2570 INT index;
2571 INT run_start_index;
2572 INT run_end_index;
2573 GX_BIDI_LEVEL_RUN *entry;
2574 GX_BIDI_LEVEL_RUN *next_entry;
2575 GX_BIDI_UNIT *unit;
2576 GX_BIDI_UNIT *tail_unit;
2577 GX_BIDI_UNIT temp;
2578 INT count;
2579
2580 _gx_utility_bidi_level_runs_compute(context, start_index, end_index);
2581
2582 /* Find max level. */
2583 entry = context -> gx_bidi_context_level_runs;
2584 if (entry)
2585 {
2586 unit = &context -> gx_bidi_context_unit_list[entry -> gx_bidi_level_run_start_index];
2587 max_level = unit -> gx_bidi_unit_level;
2588 min_level = max_level;
2589 entry = entry -> gx_bidi_level_run_next;
2590 }
2591
2592 while (entry)
2593 {
2594 unit = &context -> gx_bidi_context_unit_list[entry -> gx_bidi_level_run_start_index];
2595
2596 if (unit -> gx_bidi_unit_level > max_level)
2597 {
2598 max_level = unit -> gx_bidi_unit_level;
2599 }
2600 else if (unit -> gx_bidi_unit_level < min_level)
2601 {
2602 min_level = unit -> gx_bidi_unit_level;
2603 }
2604 entry = entry -> gx_bidi_level_run_next;
2605 }
2606
2607 if ((min_level & 0x01) == 0)
2608 {
2609 min_level += 1;
2610 }
2611
2612 /* From highest level, reverse any contiguous sequence of characters that are at that level or higher. */
2613 for (level = max_level; level >= min_level; level--)
2614 {
2615 entry = context -> gx_bidi_context_level_runs;
2616
2617 while (entry)
2618 {
2619 run_start_index = entry -> gx_bidi_level_run_start_index;
2620 run_end_index = entry -> gx_bidi_level_run_end_index;
2621
2622 next_entry = entry -> gx_bidi_level_run_next;
2623 unit = &context -> gx_bidi_context_unit_list[run_start_index];
2624
2625 if (unit -> gx_bidi_unit_level >= level)
2626 {
2627 while (next_entry &&
2628 context -> gx_bidi_context_unit_list[next_entry -> gx_bidi_level_run_start_index].gx_bidi_unit_level >= level)
2629 {
2630 run_end_index = next_entry -> gx_bidi_level_run_end_index;
2631 next_entry = next_entry -> gx_bidi_level_run_next;
2632 }
2633
2634 count = (run_end_index - run_start_index + 1) >> 1;
2635
2636 /* Reverse characters. */
2637 unit = &context -> gx_bidi_context_unit_list[run_start_index];
2638 tail_unit = &context -> gx_bidi_context_unit_list[run_end_index];
2639
2640 for (index = 0; index < count; index++)
2641 {
2642 temp = *unit;
2643 *unit = *tail_unit;
2644 *tail_unit = temp;
2645
2646 unit++;
2647 tail_unit--;
2648 }
2649 }
2650 entry = next_entry;
2651 }
2652 }
2653
2654 context -> gx_bidi_context_buffer_index -= sizeof(GX_BIDI_LEVEL_RUN) * (UINT)context -> gx_bidi_context_unit_count;
2655
2656 return GX_SUCCESS;
2657 }
2658
2659 /**************************************************************************/
2660 /* */
2661 /* FUNCTION RELEASE */
2662 /* */
2663 /* _gx_utility_bidi_line_break PORTABLE C */
2664 /* 6.1 */
2665 /* AUTHOR */
2666 /* */
2667 /* Kenneth Maxwell, Microsoft Corporation */
2668 /* */
2669 /* DESCRIPTION */
2670 /* */
2671 /* Internal helper function to break text into lines. */
2672 /* */
2673 /* INPUT */
2674 /* */
2675 /* context Bidi information control block*/
2676 /* */
2677 /* OUTPUT */
2678 /* */
2679 /* status Completion status */
2680 /* */
2681 /* CALLS */
2682 /* */
2683 /* None */
2684 /* */
2685 /* CALLED BY */
2686 /* */
2687 /* _gx_utility_bidi_paragraph_reorder */
2688 /* */
2689 /* RELEASE HISTORY */
2690 /* */
2691 /* DATE NAME DESCRIPTION */
2692 /* */
2693 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
2694 /* */
2695 /**************************************************************************/
_gx_utility_bidi_line_break(GX_BIDI_CONTEXT * context)2696 static UINT _gx_utility_bidi_line_break(GX_BIDI_CONTEXT *context)
2697 {
2698 GX_BIDI_TEXT_INFO *input_info = context -> gx_bidi_context_input_info;
2699 INT index = 0;
2700 GX_STRING ch;
2701 UINT glyph_len;
2702 GX_VALUE glyph_width;
2703 UINT line = 0;
2704 GX_BIDI_UNIT *unit;
2705 GX_UBYTE utf8[6];
2706 INT display_number = 0;
2707 INT display_width = 0;
2708 INT line_break_display_number = 0;
2709 INT line_break_display_width = 0;
2710 INT line_index = -1;
2711
2712 unit = context -> gx_bidi_context_unit_list;
2713
2714 if ((!input_info -> gx_bidi_text_info_font) || (input_info -> gx_bidi_text_info_display_width <= 0))
2715 {
2716 context -> gx_bidi_context_total_lines = 1;
2717 return GX_SUCCESS;
2718 }
2719
2720 context -> gx_bidi_context_line_index_cache = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
2721 context -> gx_bidi_context_line_index_cache[0] = 0;
2722
2723 for (index = 0; index < context -> gx_bidi_context_unit_count; index++)
2724 {
2725 _gx_utility_unicode_to_utf8(unit -> gx_bidi_unit_code, utf8, &glyph_len);
2726
2727 ch.gx_string_ptr = (GX_CHAR *)utf8;
2728 ch.gx_string_length = glyph_len;
2729 _gx_system_string_width_get_ext(input_info -> gx_bidi_text_info_font, &ch, &glyph_width);
2730
2731 if ((display_width + glyph_width > input_info -> gx_bidi_text_info_display_width) &&
2732 (display_number > 0) &&
2733 (ch.gx_string_ptr[0] != ' '))
2734 {
2735 /* Breadk line. */
2736 if (line_break_display_number)
2737 {
2738 line_index += line_break_display_number;
2739 display_number -= line_break_display_number;
2740 display_width -= line_break_display_width;
2741 }
2742 else
2743 {
2744 line_index += display_number;
2745 display_number = 0;
2746 display_width = 0;
2747 }
2748
2749 context -> gx_bidi_context_line_index_cache[line++] = line_index;
2750 line_break_display_number = 0;
2751 line_break_display_width = 0;
2752 }
2753
2754 display_width += glyph_width;
2755 display_number++;
2756
2757 if ((ch.gx_string_ptr[0] == ' ') ||
2758 (ch.gx_string_ptr[0] == ',') ||
2759 (ch.gx_string_ptr[0] == ';'))
2760 {
2761 line_break_display_number = display_number;
2762 line_break_display_width = display_width;
2763 }
2764
2765 unit++;
2766 }
2767
2768 context -> gx_bidi_context_line_index_cache[line++] = context -> gx_bidi_context_unit_count - 1;
2769 context -> gx_bidi_context_total_lines = line;
2770
2771 context -> gx_bidi_context_buffer_index += sizeof(INT *) * line;
2772
2773 return GX_SUCCESS;
2774 }
2775
2776 /**************************************************************************/
2777 /* */
2778 /* FUNCTION RELEASE */
2779 /* */
2780 /* _gx_utility_bidi_reordering_resolve PORTABLE C */
2781 /* 6.1 */
2782 /* AUTHOR */
2783 /* */
2784 /* Kenneth Maxwell, Microsoft Corporation */
2785 /* */
2786 /* DESCRIPTION */
2787 /* */
2788 /* Internal helper function to reorder text based on resolved embedding*/
2789 /* levels or each line. */
2790 /* */
2791 /* INPUT */
2792 /* */
2793 /* context Bidi information control block*/
2794 /* total_lines Total lines of the text */
2795 /* returned_utf8_text Pointer to the utf8 string of */
2796 /* the first line, following */
2797 /* lines are linked one after */
2798 /* another. */
2799 /* */
2800 /* OUTPUT */
2801 /* */
2802 /* status Completion status */
2803 /* */
2804 /* CALLS */
2805 /* */
2806 /* None */
2807 /* */
2808 /* CALLED BY */
2809 /* */
2810 /* _gx_utility_bidi_paragraph_reorder */
2811 /* */
2812 /* RELEASE HISTORY */
2813 /* */
2814 /* DATE NAME DESCRIPTION */
2815 /* */
2816 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2817 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2818 /* update with bidi context */
2819 /* structure change, */
2820 /* resulting in version 6.1 */
2821 /* */
2822 /**************************************************************************/
_gx_utility_bidi_reordering_resolve(GX_BIDI_CONTEXT * context,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info)2823 static UINT _gx_utility_bidi_reordering_resolve(GX_BIDI_CONTEXT *context, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info)
2824 {
2825 UINT status = GX_SUCCESS;
2826 INT start_index = 0;
2827 INT end_index;
2828 UINT line_index;
2829 GX_STRING *out_text_list = GX_NULL;
2830 GX_CHAR *line_text;
2831 ULONG byte_size;
2832 INT index;
2833 UINT glyph_count;
2834 GX_BIDI_UNIT *unit;
2835 GX_BIDI_RESOLVED_TEXT_INFO *bidi_text;
2836
2837 byte_size = context -> gx_bidi_context_total_lines * (sizeof(GX_BIDI_RESOLVED_TEXT_INFO) + sizeof(GX_STRING));
2838 byte_size += context -> gx_bidi_context_reordered_utf8_size + context -> gx_bidi_context_total_lines;
2839
2840 bidi_text = (GX_BIDI_RESOLVED_TEXT_INFO *)_gx_system_memory_allocator(byte_size);
2841
2842 if (!bidi_text)
2843 {
2844 return GX_SYSTEM_MEMORY_ERROR;
2845 }
2846
2847 memset(bidi_text, 0, (size_t)byte_size);
2848
2849 bidi_text -> gx_bidi_resolved_text_info_text = (GX_STRING *)(bidi_text + 1);
2850 bidi_text -> gx_bidi_resolved_text_info_total_lines = context -> gx_bidi_context_total_lines;
2851
2852 *resolved_info = bidi_text;
2853
2854 out_text_list = bidi_text -> gx_bidi_resolved_text_info_text;
2855 line_text = (GX_CHAR *)(out_text_list + context -> gx_bidi_context_total_lines);
2856
2857
2858 for (line_index = 0; line_index < context -> gx_bidi_context_total_lines; line_index++)
2859 {
2860 if (context -> gx_bidi_context_total_lines == 1)
2861 {
2862 end_index = context -> gx_bidi_context_unit_count - 1;
2863 }
2864 else
2865 {
2866 end_index = context -> gx_bidi_context_line_index_cache[line_index];
2867 }
2868
2869 status = _gx_utility_bidi_reordering_resolve_1(context, start_index, end_index);
2870
2871 if (status == GX_SUCCESS)
2872 {
2873 status = _gx_utility_bidi_reordering_resolve_2(context, start_index, end_index);
2874 }
2875
2876 if (status == GX_SUCCESS)
2877 {
2878 unit = &context -> gx_bidi_context_unit_list[start_index];
2879
2880 out_text_list -> gx_string_ptr = line_text;
2881
2882 /* Convert unicode to utf8 text. */
2883 for (index = start_index; index <= end_index; index++)
2884 {
2885 switch (unit -> gx_bidi_unit_type)
2886 {
2887 case GX_BIDI_CHARACTER_TYPE_BN:
2888 /* Skip above characters. */
2889 break;
2890
2891 default:
2892 if (unit -> gx_bidi_unit_code)
2893 {
2894 if (unit -> gx_bidi_unit_code < 0x80)
2895 {
2896 *(GX_UBYTE *)(line_text) = (GX_UBYTE)(unit -> gx_bidi_unit_code);
2897 glyph_count = 1;
2898 }
2899 else
2900 {
2901
2902 _gx_utility_unicode_to_utf8(unit -> gx_bidi_unit_code, (GX_UBYTE *)line_text, &glyph_count);
2903 }
2904 line_text += glyph_count;
2905 out_text_list -> gx_string_length += glyph_count;
2906 }
2907 break;
2908 }
2909
2910 unit++;
2911 }
2912
2913 line_text++;
2914 out_text_list++;
2915 }
2916
2917 start_index = end_index + 1;
2918 }
2919
2920 return status;
2921 }
2922
2923 /**************************************************************************/
2924 /* */
2925 /* FUNCTION RELEASE */
2926 /* */
2927 /* _gx_utility_bidi_one_paragraph_reorder PORTABLE C */
2928 /* 6.1.10 */
2929 /* AUTHOR */
2930 /* */
2931 /* Kenneth Maxwell, Microsoft Corporation */
2932 /* */
2933 /* DESCRIPTION */
2934 /* */
2935 /* This function reorders a bidi text for displaying. */
2936 /* */
2937 /* INPUT */
2938 /* */
2939 /* text_info Pointer to bidi text */
2940 /* reordered_text Reordered text, each line is */
2941 /* ended a with string */
2942 /* terminator '\0', multi line */
2943 /* strings are linked one after*/
2944 /* another */
2945 /* processed_count The processed text size in */
2946 /* byte */
2947 /* */
2948 /* OUTPUT */
2949 /* */
2950 /* status Completion status */
2951 /* */
2952 /* CALLS */
2953 /* */
2954 /* None */
2955 /* */
2956 /* CALLED BY */
2957 /* */
2958 /* _gx_utility_bidi_paragraph_reorder */
2959 /* */
2960 /* RELEASE HISTORY */
2961 /* */
2962 /* DATE NAME DESCRIPTION */
2963 /* */
2964 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2965 /* 09-30-2020 Kenneth Maxwell Modified comment(s), modified */
2966 /* line breaking logic, */
2967 /* supported Arabic shaping, */
2968 /* updated with resolved text */
2969 /* info structure change, */
2970 /* resulting in version 6.1 */
2971 /* 01-31-2022 Kenneth Maxwell Modified comment(s), modified */
2972 /* base level set logic, */
2973 /* resulting in version 6.1.10 */
2974 /* */
2975 /**************************************************************************/
_gx_utility_bidi_one_paragraph_reorder(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info,UINT * processed_size)2976 static UINT _gx_utility_bidi_one_paragraph_reorder(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info, UINT *processed_size)
2977 {
2978 UINT status;
2979 GX_BIDI_CONTEXT context;
2980
2981 memset(&context, 0, sizeof(GX_BIDI_CONTEXT));
2982 context.gx_bidi_context_input_info = input_info;
2983
2984 /* Allocate buffer needed for bidi text reordering. */
2985 status = _gx_utility_bidi_buffer_allocate(&context);
2986
2987 if (status == GX_SUCCESS)
2988 {
2989 status = _gx_utility_bidi_initiate(&context);
2990 }
2991
2992 if (status == GX_SUCCESS)
2993 {
2994 switch (input_info -> gx_bidi_text_info_direction)
2995 {
2996 case GX_LANGUAGE_DIRECTION_LTR:
2997 context.gx_bidi_context_base_level = 0;
2998 break;
2999
3000 case GX_LANGUAGE_DIRECTION_RTL:
3001 context.gx_bidi_context_base_level = 1;
3002 break;
3003
3004 default:
3005 /* Compute paragraph embedding_level. */
3006 status = _gx_utility_bidi_block_level_determine(&context, 0,
3007 (UINT)(context.gx_bidi_context_unit_count - 1),
3008 &context.gx_bidi_context_base_level);
3009 break;
3010 }
3011 }
3012
3013 if (status == GX_SUCCESS)
3014 {
3015 /* Compute explicie level for every character. */
3016 status = _gx_utility_bidi_explicit_levels_determine(&context);
3017 }
3018
3019 if (status == GX_SUCCESS)
3020 {
3021 /* Compute isolate run sequences. */
3022 status = _gx_utility_bidi_isolate_run_sequences_get(&context);
3023 }
3024
3025 if (status == GX_SUCCESS)
3026 {
3027 /* Apply rules to each isolate run sequence. */
3028 status = _gx_utility_bidi_isolate_run_sequences_resolve(&context);
3029 }
3030
3031 #if defined(GX_DYNAMIC_ARABIC_SHAPING_SUPPORT)
3032 if (status == GX_SUCCESS)
3033 {
3034 status = _gx_utility_bidi_arabic_shaping(&context);
3035 }
3036 #endif
3037
3038 if (status == GX_SUCCESS)
3039 {
3040 /* Broke paragraph text into lines. */
3041 status = _gx_utility_bidi_line_break(&context);
3042 }
3043
3044 if (status == GX_SUCCESS)
3045 {
3046 /* Reorder text of each line for display. */
3047 status = _gx_utility_bidi_reordering_resolve(&context, resolved_info);
3048 }
3049
3050 if (status == GX_SUCCESS)
3051 {
3052 if (processed_size)
3053 {
3054 *processed_size = context.gx_bidi_context_processced_size;
3055 }
3056
3057 _gx_system_memory_free(context.gx_bidi_context_buffer);
3058 }
3059
3060 return status;
3061 }
3062
3063
3064
3065 /**************************************************************************/
3066 /* */
3067 /* FUNCTION RELEASE */
3068 /* */
3069 /* _gx_utility_bidi_paragraph_reorder PORTABLE C */
3070 /* 6.1.3 */
3071 /* AUTHOR */
3072 /* */
3073 /* Kenneth Maxwell, Microsoft Corporation */
3074 /* */
3075 /* DESCRIPTION */
3076 /* */
3077 /* This function reorders a bidi text for displaying. */
3078 /* */
3079 /* INPUT */
3080 /* */
3081 /* input_info Pointer to bidi text info */
3082 /* reordered_text Reordered text information */
3083 /* */
3084 /* OUTPUT */
3085 /* */
3086 /* status Completion status */
3087 /* */
3088 /* CALLS */
3089 /* */
3090 /* None */
3091 /* */
3092 /* CALLED BY */
3093 /* */
3094 /* Application Code */
3095 /* */
3096 /* RELEASE HISTORY */
3097 /* */
3098 /* DATE NAME DESCRIPTION */
3099 /* */
3100 /* 09-30-2020 Kenneth Maxwell Initial Version 6.1 */
3101 /* 12-31-2020 Kenneth Maxwell Modified comment(s), */
3102 /* made this function a public */
3103 /* api, */
3104 /* resulting in version 6.1.3 */
3105 /* */
3106 /**************************************************************************/
_gx_utility_bidi_paragraph_reorder(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info_head)3107 UINT _gx_utility_bidi_paragraph_reorder(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info_head)
3108 {
3109 input_info->gx_bidi_text_info_direction = -1;
3110
3111 return _gx_utility_bidi_paragraph_reorder_ext(input_info, resolved_info_head);
3112 }
3113
3114 /**************************************************************************/
3115 /* */
3116 /* FUNCTION RELEASE */
3117 /* */
3118 /* _gx_utility_bidi_paragraph_reorder_ext PORTABLE C */
3119 /* 6.1.10 */
3120 /* AUTHOR */
3121 /* */
3122 /* Kenneth Maxwell, Microsoft Corporation */
3123 /* */
3124 /* DESCRIPTION */
3125 /* */
3126 /* This function reorders a bidi text for displaying. */
3127 /* */
3128 /* INPUT */
3129 /* */
3130 /* input_info Pointer to bidi text info */
3131 /* reordered_text Reordered text information */
3132 /* */
3133 /* OUTPUT */
3134 /* */
3135 /* status Completion status */
3136 /* */
3137 /* CALLS */
3138 /* */
3139 /* None */
3140 /* */
3141 /* CALLED BY */
3142 /* */
3143 /* Application Code */
3144 /* */
3145 /* RELEASE HISTORY */
3146 /* */
3147 /* DATE NAME DESCRIPTION */
3148 /* */
3149 /* 01-31-2022 Ting Zhu Initial Version 6.1.10 */
3150 /* */
3151 /**************************************************************************/
_gx_utility_bidi_paragraph_reorder_ext(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info_head)3152 UINT _gx_utility_bidi_paragraph_reorder_ext(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info_head)
3153 {
3154 UINT status = GX_SUCCESS;
3155 GX_BIDI_TEXT_INFO text_info;
3156 GX_BIDI_RESOLVED_TEXT_INFO *resolved_info;
3157 GX_BIDI_RESOLVED_TEXT_INFO *head = GX_NULL;
3158 GX_BIDI_RESOLVED_TEXT_INFO *pre = GX_NULL;
3159 UINT line_size;
3160 UINT line_break_counts = 0;
3161 GX_STRING string = input_info -> gx_bidi_text_info_text;
3162
3163 if (!_gx_system_memory_allocator)
3164 {
3165 return GX_SYSTEM_MEMORY_ERROR;
3166 }
3167
3168 text_info = *input_info;
3169
3170 while (string.gx_string_length > 0)
3171 {
3172 if (string.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN)
3173 {
3174 if ((string.gx_string_length > 1) && (string.gx_string_ptr[1] == GX_KEY_LINE_FEED))
3175 {
3176 line_size = 2;
3177 }
3178 else
3179 {
3180 line_size = 1;
3181 }
3182 line_break_counts++;
3183 }
3184 else if (string.gx_string_ptr[0] == GX_KEY_LINE_FEED)
3185 {
3186 line_size = 1;
3187 line_break_counts++;
3188 }
3189 else
3190 {
3191 line_size = 0;
3192 }
3193
3194 if (((line_break_counts > 1) && (!line_size)) ||
3195 ((line_break_counts > 0) && (line_size == string.gx_string_length)))
3196 {
3197 /* Collect blank lines as one bidi resolved text info instance. */
3198 resolved_info = (GX_BIDI_RESOLVED_TEXT_INFO *)_gx_system_memory_allocator(sizeof(GX_BIDI_RESOLVED_TEXT_INFO));
3199 if (!resolved_info)
3200 {
3201 status = GX_SYSTEM_MEMORY_ERROR;
3202 break;
3203 }
3204
3205 memset(resolved_info, 0, sizeof(GX_BIDI_RESOLVED_TEXT_INFO));
3206
3207 if (!line_size)
3208 {
3209 resolved_info -> gx_bidi_resolved_text_info_total_lines = (UINT)(line_break_counts - 1);
3210 }
3211 else
3212 {
3213 resolved_info -> gx_bidi_resolved_text_info_total_lines = line_break_counts;
3214 }
3215
3216 GX_LINK_RESOLVED_BIDI_TEXT_INFO
3217 }
3218
3219 if (!line_size)
3220 {
3221 /* Start bidi text reorderding for one paragraph. */
3222 text_info.gx_bidi_text_info_text = string;
3223 status = _gx_utility_bidi_one_paragraph_reorder(&text_info, &resolved_info, &line_size);
3224
3225 if (status != GX_SUCCESS)
3226 {
3227 break;
3228 }
3229
3230 GX_LINK_RESOLVED_BIDI_TEXT_INFO
3231
3232 line_break_counts = 0;
3233 }
3234
3235 /* Increment string pointer and decrement string length. */
3236 string.gx_string_ptr += line_size;
3237 string.gx_string_length -= line_size;
3238 }
3239
3240 if (status == GX_SUCCESS)
3241 {
3242 *resolved_info_head = head;
3243 }
3244 else if (head)
3245 {
3246 /* Clean generated resolved bidi text link. */
3247 _gx_utility_bidi_resolved_text_info_delete(&head);
3248 }
3249
3250 return status;
3251 }
3252 #endif
3253
3254