2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
5
* GRUB is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* GRUB is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20
Current problems with Unicode rendering:
21
- B and BN bidi type characters (ignored)
22
- Mc type characters with combining class 0 (poorly combined)
23
- Mn type characters with combining class 0 (poorly combined)
24
- Me type characters with combining class 0 (poorly combined)
25
- Cf type characters (ignored)
26
- Cc type characters (ignored)
27
- Line-breaking rules (e.g. Zs type characters)
29
- non-Semitic shaping (rarely used)
30
- Zl and Zp characters
31
- Combining characters of types 7, 8, 9, 21, 35, 36, 84, 91, 103, 107,
32
118, 122, 129, 130, 132, 218, 224, 226, 233, 234
33
- Private use characters (not really a problem)
34
- Variations (no font support)
37
Font information ignored:
42
Most underline diacritics aren't displayed in gfxterm
45
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
46
bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string.
47
Return the number of characters converted. DEST must be able to hold
48
at least DESTSIZE characters. If an invalid sequence is found, return -1.
49
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
50
last byte used in SRC. */
52
#include <grub/charset.h>
54
#include <grub/misc.h>
55
#include <grub/unicode.h>
56
#include <grub/term.h>
57
#include <grub/normal.h>
59
#ifdef HAVE_UNIFONT_WIDTHSPEC
60
#include "widthspec.h"
64
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
65
const grub_uint8_t *src, grub_size_t srcsize,
66
const grub_uint8_t **srcend)
68
grub_uint16_t *p = dest;
70
grub_uint32_t code = 0;
75
while (srcsize && destsize)
77
grub_uint32_t c = *src++;
78
if (srcsize != (grub_size_t)-1)
82
if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT)
90
code |= (c & GRUB_UINT8_6_TRAILINGBITS);
99
if ((c & GRUB_UINT8_1_LEADINGBIT) == 0)
101
else if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS)
104
code = c & GRUB_UINT8_5_TRAILINGBITS;
106
else if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS)
109
code = c & GRUB_UINT8_4_TRAILINGBITS;
111
else if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS)
114
code = c & GRUB_UINT8_3_TRAILINGBITS;
116
else if ((c & GRUB_UINT8_6_LEADINGBITS) == GRUB_UINT8_5_LEADINGBITS)
119
code = c & GRUB_UINT8_2_TRAILINGBITS;
121
else if ((c & GRUB_UINT8_7_LEADINGBITS) == GRUB_UINT8_6_LEADINGBITS)
124
code = c & GRUB_UINT8_1_TRAILINGBIT;
132
if (destsize < 2 && code >= GRUB_UCS2_LIMIT)
134
if (code >= GRUB_UCS2_LIMIT)
136
*p++ = GRUB_UTF16_UPPER_SURROGATE (code);
137
*p++ = GRUB_UTF16_LOWER_SURROGATE (code);
153
/* Convert UCS-4 to UTF-8. */
155
grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size,
156
grub_uint8_t *dest, grub_size_t destsize)
158
/* Keep last char for \0. */
159
grub_uint8_t *destend = dest + destsize - 1;
161
while (size-- && dest < destend)
163
grub_uint32_t code = *src++;
167
else if (code <= 0x07FF)
169
if (dest + 1 >= destend)
171
*dest++ = (code >> 6) | 0xC0;
172
*dest++ = (code & 0x3F) | 0x80;
174
else if ((code >= 0xDC00 && code <= 0xDFFF)
175
|| (code >= 0xD800 && code <= 0xDBFF))
177
/* No surrogates in UCS-4... */
182
if (dest + 2 >= destend)
184
*dest++ = (code >> 12) | 0xE0;
185
*dest++ = ((code >> 6) & 0x3F) | 0x80;
186
*dest++ = (code & 0x3F) | 0x80;
192
/* Convert UCS-4 to UTF-8. */
194
grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size)
196
grub_size_t remaining;
205
grub_uint32_t code = *ptr++;
209
else if (code <= 0x07FF)
211
else if ((code >= 0xDC00 && code <= 0xDFFF)
212
|| (code >= 0xD800 && code <= 0xDBFF))
213
/* No surrogates in UCS-4... */
220
ret = grub_malloc (cnt);
224
grub_ucs4_to_utf8 (src, size, ret, cnt);
230
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize)
232
grub_uint32_t code = 0;
237
grub_uint32_t c = *src++;
238
if (srcsize != (grub_size_t)-1)
242
if ((c & 0xc0) != 0x80)
259
if ((c & 0x80) == 0x00)
261
else if ((c & 0xe0) == 0xc0)
266
else if ((c & 0xf0) == 0xe0)
271
else if ((c & 0xf8) == 0xf0)
276
else if ((c & 0xfc) == 0xf8)
281
else if ((c & 0xfe) == 0xfc)
295
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
296
grub_uint32_t **last_position)
298
grub_size_t msg_len = grub_strlen (msg);
300
*unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t));
304
grub_printf ("utf8_to_ucs4 ERROR1: %s", msg);
308
msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len,
309
(grub_uint8_t *) msg, -1, 0);
312
*last_position = *unicode_msg + msg_len;
317
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
318
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
319
Return the number of characters converted. DEST must be able to hold
320
at least DESTSIZE characters.
321
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
322
last byte used in SRC. */
324
grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
325
const grub_uint8_t *src, grub_size_t srcsize,
326
const grub_uint8_t **srcend)
328
grub_uint32_t *p = dest;
330
grub_uint32_t code = 0;
335
while (srcsize && destsize)
337
grub_uint32_t c = *src++;
338
if (srcsize != (grub_size_t)-1)
342
if ((c & 0xc0) != 0x80)
346
/* Character c may be valid, don't eat it. */
348
if (srcsize != (grub_size_t)-1)
364
if ((c & 0x80) == 0x00)
366
else if ((c & 0xe0) == 0xc0)
371
else if ((c & 0xf0) == 0xe0)
376
else if ((c & 0xf8) == 0xf0)
381
else if ((c & 0xfc) == 0xf8)
386
else if ((c & 0xfe) == 0xfc)
411
static grub_uint8_t *join_types = NULL;
417
struct grub_unicode_compact_range *cur;
419
join_types = grub_zalloc (GRUB_UNICODE_MAX_CACHED_CHAR);
422
grub_errno = GRUB_ERR_NONE;
425
for (cur = grub_unicode_compact; cur->end; cur++)
426
for (i = cur->start; i <= cur->end
427
&& i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
428
join_types[i] = cur->join_type;
431
static grub_uint8_t *bidi_types = NULL;
437
struct grub_unicode_compact_range *cur;
439
bidi_types = grub_zalloc (GRUB_UNICODE_MAX_CACHED_CHAR);
442
grub_errno = GRUB_ERR_NONE;
445
for (cur = grub_unicode_compact; cur->end; cur++)
446
for (i = cur->start; i <= cur->end
447
&& i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
448
if (cur->bidi_mirror)
449
bidi_types[i] = cur->bidi_type | 0x80;
451
bidi_types[i] = cur->bidi_type | 0x00;
454
static inline enum grub_bidi_type
455
get_bidi_type (grub_uint32_t c)
457
struct grub_unicode_compact_range *cur;
462
if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
463
return bidi_types[c] & 0x7f;
465
for (cur = grub_unicode_compact; cur->end; cur++)
466
if (cur->start <= c && c <= cur->end)
467
return cur->bidi_type;
469
return GRUB_BIDI_TYPE_L;
472
static inline enum grub_join_type
473
get_join_type (grub_uint32_t c)
475
struct grub_unicode_compact_range *cur;
480
if (join_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
481
return join_types[c];
483
for (cur = grub_unicode_compact; cur->end; cur++)
484
if (cur->start <= c && c <= cur->end)
485
return cur->join_type;
487
return GRUB_JOIN_TYPE_NONJOINING;
491
is_mirrored (grub_uint32_t c)
493
struct grub_unicode_compact_range *cur;
498
if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
499
return !!(bidi_types[c] & 0x80);
501
for (cur = grub_unicode_compact; cur->end; cur++)
502
if (cur->start <= c && c <= cur->end)
503
return cur->bidi_mirror;
509
grub_unicode_get_comb_type (grub_uint32_t c)
511
static grub_uint8_t *comb_types = NULL;
512
struct grub_unicode_compact_range *cur;
517
comb_types = grub_zalloc (GRUB_UNICODE_MAX_CACHED_CHAR);
519
for (cur = grub_unicode_compact; cur->end; cur++)
520
for (i = cur->start; i <= cur->end
521
&& i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
522
comb_types[i] = cur->comb_type;
524
grub_errno = GRUB_ERR_NONE;
527
if (comb_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
528
return comb_types[c];
530
for (cur = grub_unicode_compact; cur->end; cur++)
531
if (cur->start <= c && c <= cur->end)
532
return cur->comb_type;
534
return GRUB_UNICODE_COMB_NONE;
537
#ifdef HAVE_UNIFONT_WIDTHSPEC
540
grub_unicode_estimate_width (const struct grub_unicode_glyph *c)
542
if (grub_unicode_get_comb_type (c->base))
544
if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
553
is_type_after (enum grub_comb_type a, enum grub_comb_type b)
555
/* Shadda is numerically higher than most of Arabic diacritics but has
556
to be rendered before them. */
557
if (a == GRUB_UNICODE_COMB_ARABIC_SHADDA
558
&& b <= GRUB_UNICODE_COMB_ARABIC_KASRA
559
&& b >= GRUB_UNICODE_COMB_ARABIC_FATHATAN)
561
if (b == GRUB_UNICODE_COMB_ARABIC_SHADDA
562
&& a <= GRUB_UNICODE_COMB_ARABIC_KASRA
563
&& a >= GRUB_UNICODE_COMB_ARABIC_FATHATAN)
569
grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
570
struct grub_unicode_glyph *out)
573
const grub_uint32_t *ptr;
574
unsigned last_comb_pointer = 0;
576
grub_memset (out, 0, sizeof (*out));
578
for (ptr = in; ptr < in + inlen; ptr++)
580
/* Variation selectors >= 17 are outside of BMP and SMP.
581
Handle variation selectors first to avoid potentially costly lookups.
583
if (*ptr >= GRUB_UNICODE_VARIATION_SELECTOR_1
584
&& *ptr <= GRUB_UNICODE_VARIATION_SELECTOR_16)
587
out->variant = *ptr - GRUB_UNICODE_VARIATION_SELECTOR_1 + 1;
591
if (*ptr >= GRUB_UNICODE_VARIATION_SELECTOR_17
592
&& *ptr <= GRUB_UNICODE_VARIATION_SELECTOR_256)
595
out->variant = *ptr - GRUB_UNICODE_VARIATION_SELECTOR_17 + 17;
599
enum grub_comb_type comb_type;
600
comb_type = grub_unicode_get_comb_type (*ptr);
603
struct grub_unicode_combining *n;
609
if (comb_type == GRUB_UNICODE_COMB_MC
610
|| comb_type == GRUB_UNICODE_COMB_ME
611
|| comb_type == GRUB_UNICODE_COMB_MN)
612
last_comb_pointer = out->ncomb;
613
n = grub_realloc (out->combining,
614
sizeof (n[0]) * (out->ncomb + 1));
617
grub_errno = GRUB_ERR_NONE;
622
for (j = last_comb_pointer; j < out->ncomb; j++)
623
if (is_type_after (out->combining[j].type, comb_type))
625
grub_memmove (out->combining + j + 1,
628
* sizeof (out->combining[0]));
630
out->combining[j].code = *ptr;
631
out->combining[j].type = comb_type;
642
out->estimated_width = 1;
643
out->combining = NULL;
649
bidi_line_wrap (struct grub_unicode_glyph *visual_out,
650
struct grub_unicode_glyph *visual,
651
grub_size_t visual_len, unsigned *levels,
652
grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual),
653
grub_size_t maxwidth, grub_size_t startwidth)
655
struct grub_unicode_glyph *outptr = visual_out;
656
unsigned line_start = 0;
657
grub_ssize_t line_width = startwidth;
659
grub_ssize_t last_space = -1;
660
grub_ssize_t last_space_width = 0;
662
auto void revert (unsigned start, unsigned end);
663
void revert (unsigned start, unsigned end)
665
struct grub_unicode_glyph t;
667
for (i = 0; i <= (end - start) / 2; i++)
669
t = visual[start + i];
670
visual[start + i] = visual[end - i];
672
tl = levels[start + i];
673
levels[start + i] = levels[end - i];
674
levels[end - i] = tl;
681
for (k = 0; k <= visual_len; k++)
683
grub_ssize_t last_width = 0;
685
if (getcharwidth && k != visual_len)
686
line_width += last_width = getcharwidth (&visual[k]);
688
if (k != visual_len && visual[k].base == ' ')
691
last_space_width = line_width;
694
if (((grub_ssize_t) maxwidth > 0
695
&& line_width > (grub_ssize_t) maxwidth) || k == visual_len)
697
unsigned min_odd_level = 0xffffffff;
698
unsigned max_level = 0;
700
if (k != visual_len && last_space > (signed) line_start)
702
else if (k != visual_len && line_start == 0 && startwidth != 0)
705
last_space_width = startwidth;
708
last_space_width = line_width - last_width;
712
for (i = line_start; i < k; i++)
714
if (levels[i] > max_level)
715
max_level = levels[i];
716
if (levels[i] < min_odd_level && (levels[i] & 1))
717
min_odd_level = levels[i];
723
/* FIXME: can be optimized. */
724
for (j = max_level; j >= min_odd_level; j--)
728
for (i = line_start; i < k; i++)
730
if (i != line_start && levels[i] >= j && levels[i-1] < j)
732
if (levels[i] >= j && (i + 1 == k || levels[i+1] < j))
740
for (i = line_start; i < k; i++)
742
if (is_mirrored (visual[i].base) && levels[i])
743
visual[i].attributes |= GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR;
744
if ((visual[i].attributes & GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN)
748
left = visual[i].attributes
749
& (GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
750
| GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT);
751
right = visual[i].attributes
752
& (GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
753
| GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT);
754
visual[i].attributes &= ~GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN;
755
left <<= GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN_LEFT_TO_RIGHT_SHIFT;
756
right >>= GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN_LEFT_TO_RIGHT_SHIFT;
757
visual[i].attributes |= (left | right);
765
for (i = line_start; i < k; i++)
767
enum grub_join_type join_type = get_join_type (visual[i].base);
768
if (!(visual[i].attributes
769
& GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT)
770
&& (join_type == GRUB_JOIN_TYPE_LEFT
771
|| join_type == GRUB_JOIN_TYPE_DUAL))
775
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED;
778
&= ~GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED;
780
if (join_type == GRUB_JOIN_TYPE_NONJOINING
781
|| join_type == GRUB_JOIN_TYPE_LEFT)
783
if (join_type == GRUB_JOIN_TYPE_RIGHT
784
|| join_type == GRUB_JOIN_TYPE_DUAL
785
|| join_type == GRUB_JOIN_TYPE_CAUSING)
793
for (i = k - 1; i >= (signed) line_start; i--)
795
enum grub_join_type join_type = get_join_type (visual[i].base);
796
if (!(visual[i].attributes
797
& GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT)
798
&& (join_type == GRUB_JOIN_TYPE_RIGHT
799
|| join_type == GRUB_JOIN_TYPE_DUAL))
803
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED;
806
&= ~GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED;
808
if (join_type == GRUB_JOIN_TYPE_NONJOINING
809
|| join_type == GRUB_JOIN_TYPE_RIGHT)
811
if (join_type == GRUB_JOIN_TYPE_LEFT
812
|| join_type == GRUB_JOIN_TYPE_DUAL
813
|| join_type == GRUB_JOIN_TYPE_CAUSING)
818
grub_memcpy (outptr, &visual[line_start],
819
(k - line_start) * sizeof (visual[0]));
820
outptr += k - line_start;
823
grub_memset (outptr, 0, sizeof (visual[0]));
828
if ((signed) k == last_space)
832
line_width -= last_space_width;
836
return outptr - visual_out;
841
grub_bidi_line_logical_to_visual (const grub_uint32_t *logical,
842
grub_size_t logical_len,
843
struct grub_unicode_glyph *visual_out,
844
grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual),
845
grub_size_t maxwidth, grub_size_t startwidth)
847
enum grub_bidi_type type = GRUB_BIDI_TYPE_L;
848
enum override_status {OVERRIDE_NEUTRAL = 0, OVERRIDE_R, OVERRIDE_L};
850
enum grub_bidi_type *resolved_types;
852
enum override_status cur_override;
854
unsigned stack_level[GRUB_BIDI_MAX_EXPLICIT_LEVEL + 3];
855
enum override_status stack_override[GRUB_BIDI_MAX_EXPLICIT_LEVEL + 3];
856
unsigned stack_depth = 0;
857
unsigned invalid_pushes = 0;
858
unsigned visual_len = 0;
859
unsigned run_start, run_end;
860
struct grub_unicode_glyph *visual;
864
auto void push_stack (unsigned new_override, unsigned new_level);
865
void push_stack (unsigned new_override, unsigned new_level)
867
if (new_level > GRUB_BIDI_MAX_EXPLICIT_LEVEL)
872
stack_level[stack_depth] = cur_level;
873
stack_override[stack_depth] = cur_override;
875
cur_level = new_level;
876
cur_override = new_override;
879
auto void pop_stack (void);
880
void pop_stack (void)
890
cur_level = stack_level[stack_depth];
891
cur_override = stack_override[stack_depth];
894
levels = grub_malloc (sizeof (levels[0]) * logical_len);
898
resolved_types = grub_malloc (sizeof (resolved_types[0]) * logical_len);
905
visual = grub_malloc (sizeof (visual[0]) * logical_len);
908
grub_free (resolved_types);
913
for (i = 0; i < logical_len; i++)
915
type = get_bidi_type (logical[i]);
916
if (type == GRUB_BIDI_TYPE_L || type == GRUB_BIDI_TYPE_AL
917
|| type == GRUB_BIDI_TYPE_R)
920
if (type == GRUB_BIDI_TYPE_R || type == GRUB_BIDI_TYPE_AL)
925
cur_level = base_level;
926
cur_override = OVERRIDE_NEUTRAL;
928
const grub_uint32_t *lptr;
929
enum {JOIN_DEFAULT, NOJOIN, JOIN_FORCE} join_state = JOIN_DEFAULT;
930
int zwj_propagate_to_previous = 0;
931
for (lptr = logical; lptr < logical + logical_len;)
935
if (*lptr == GRUB_UNICODE_ZWJ)
937
if (zwj_propagate_to_previous)
939
visual[visual_len - 1].attributes
940
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT
941
| GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED;
943
zwj_propagate_to_previous = 0;
944
join_state = JOIN_FORCE;
949
if (*lptr == GRUB_UNICODE_ZWNJ)
951
if (zwj_propagate_to_previous)
953
visual[visual_len - 1].attributes
954
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT;
955
visual[visual_len - 1].attributes
956
&= ~GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED;
958
zwj_propagate_to_previous = 0;
964
p = grub_unicode_aglomerate_comb (lptr, logical + logical_len - lptr,
965
&visual[visual_len]);
967
type = get_bidi_type (visual[visual_len].base);
970
case GRUB_BIDI_TYPE_RLE:
972
push_stack (cur_override, (cur_level | 1) + 1);
974
case GRUB_BIDI_TYPE_RLO:
976
push_stack (OVERRIDE_R, (cur_level | 1) + 1);
978
case GRUB_BIDI_TYPE_LRE:
979
push_stack (cur_override, (cur_level & ~1) + 2);
981
case GRUB_BIDI_TYPE_LRO:
982
push_stack (OVERRIDE_L, (cur_level & ~1) + 2);
984
case GRUB_BIDI_TYPE_PDF:
987
case GRUB_BIDI_TYPE_BN:
989
case GRUB_BIDI_TYPE_R:
990
case GRUB_BIDI_TYPE_AL:
994
if (join_state == JOIN_FORCE)
996
visual[visual_len].attributes
997
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT
998
| GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED;
1001
if (join_state == NOJOIN)
1003
visual[visual_len].attributes
1004
|= GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT;
1005
visual[visual_len].attributes
1006
&= ~GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED;
1009
join_state = JOIN_DEFAULT;
1010
zwj_propagate_to_previous = 1;
1012
levels[visual_len] = cur_level;
1013
if (cur_override != OVERRIDE_NEUTRAL)
1014
resolved_types[visual_len] =
1015
(cur_override == OVERRIDE_L) ? GRUB_BIDI_TYPE_L
1018
resolved_types[visual_len] = type;
1028
for (run_start = 0; run_start < visual_len; run_start = run_end)
1030
unsigned prev_level, next_level, cur_run_level;
1031
unsigned last_type, last_strong_type;
1032
for (run_end = run_start; run_end < visual_len &&
1033
levels[run_end] == levels[run_start]; run_end++);
1035
prev_level = base_level;
1037
prev_level = levels[run_start - 1];
1038
if (run_end == visual_len)
1039
next_level = base_level;
1041
next_level = levels[run_end];
1042
cur_run_level = levels[run_start];
1044
last_type = GRUB_BIDI_TYPE_R;
1046
last_type = GRUB_BIDI_TYPE_L;
1047
last_strong_type = last_type;
1048
for (i = run_start; i < run_end; i++)
1050
switch (resolved_types[i])
1052
case GRUB_BIDI_TYPE_NSM:
1053
resolved_types[i] = last_type;
1055
case GRUB_BIDI_TYPE_EN:
1056
if (last_strong_type == GRUB_BIDI_TYPE_AL)
1057
resolved_types[i] = GRUB_BIDI_TYPE_AN;
1059
case GRUB_BIDI_TYPE_L:
1060
case GRUB_BIDI_TYPE_R:
1061
last_strong_type = resolved_types[i];
1063
case GRUB_BIDI_TYPE_ES:
1064
if (last_type == GRUB_BIDI_TYPE_EN
1066
&& resolved_types[i + 1] == GRUB_BIDI_TYPE_EN)
1067
resolved_types[i] = GRUB_BIDI_TYPE_EN;
1069
resolved_types[i] = GRUB_BIDI_TYPE_ON;
1071
case GRUB_BIDI_TYPE_ET:
1074
if (last_type == GRUB_BIDI_TYPE_EN)
1076
resolved_types[i] = GRUB_BIDI_TYPE_EN;
1079
for (j = i; j < run_end
1080
&& resolved_types[j] == GRUB_BIDI_TYPE_ET; j++);
1081
if (j != run_end && resolved_types[j] == GRUB_BIDI_TYPE_EN)
1084
&& resolved_types[i] == GRUB_BIDI_TYPE_ET; i++)
1085
resolved_types[i] = GRUB_BIDI_TYPE_EN;
1090
&& resolved_types[i] == GRUB_BIDI_TYPE_ET; i++)
1091
resolved_types[i] = GRUB_BIDI_TYPE_ON;
1096
case GRUB_BIDI_TYPE_CS:
1097
if (last_type == GRUB_BIDI_TYPE_EN
1099
&& resolved_types[i + 1] == GRUB_BIDI_TYPE_EN)
1101
resolved_types[i] = GRUB_BIDI_TYPE_EN;
1104
if (last_type == GRUB_BIDI_TYPE_AN
1106
&& (resolved_types[i + 1] == GRUB_BIDI_TYPE_AN
1107
|| (resolved_types[i + 1] == GRUB_BIDI_TYPE_EN
1108
&& last_strong_type == GRUB_BIDI_TYPE_AL)))
1110
resolved_types[i] = GRUB_BIDI_TYPE_EN;
1113
resolved_types[i] = GRUB_BIDI_TYPE_ON;
1115
case GRUB_BIDI_TYPE_AL:
1116
last_strong_type = resolved_types[i];
1117
resolved_types[i] = GRUB_BIDI_TYPE_R;
1119
default: /* Make GCC happy. */
1122
last_type = resolved_types[i];
1123
if (resolved_types[i] == GRUB_BIDI_TYPE_EN
1124
&& last_strong_type == GRUB_BIDI_TYPE_L)
1125
resolved_types[i] = GRUB_BIDI_TYPE_L;
1128
last_type = GRUB_BIDI_TYPE_R;
1130
last_type = GRUB_BIDI_TYPE_L;
1131
for (i = run_start; i < run_end; )
1135
for (j = i; j < run_end &&
1136
(resolved_types[j] == GRUB_BIDI_TYPE_B
1137
|| resolved_types[j] == GRUB_BIDI_TYPE_S
1138
|| resolved_types[j] == GRUB_BIDI_TYPE_WS
1139
|| resolved_types[j] == GRUB_BIDI_TYPE_ON); j++);
1142
if (resolved_types[i] == GRUB_BIDI_TYPE_L)
1143
last_type = GRUB_BIDI_TYPE_L;
1145
last_type = GRUB_BIDI_TYPE_R;
1150
next_type = (next_level & 1) ? GRUB_BIDI_TYPE_R : GRUB_BIDI_TYPE_L;
1153
if (resolved_types[j] == GRUB_BIDI_TYPE_L)
1154
next_type = GRUB_BIDI_TYPE_L;
1156
next_type = GRUB_BIDI_TYPE_R;
1158
if (next_type == last_type)
1160
resolved_types[i] = last_type;
1163
resolved_types[i] = (cur_run_level & 1) ? GRUB_BIDI_TYPE_R
1168
for (i = 0; i < visual_len; i++)
1170
if (!(levels[i] & 1) && resolved_types[i] == GRUB_BIDI_TYPE_R)
1175
if (!(levels[i] & 1) && (resolved_types[i] == GRUB_BIDI_TYPE_AN
1176
|| resolved_types[i] == GRUB_BIDI_TYPE_EN))
1181
if ((levels[i] & 1) && (resolved_types[i] == GRUB_BIDI_TYPE_L
1182
|| resolved_types[i] == GRUB_BIDI_TYPE_AN
1183
|| resolved_types[i] == GRUB_BIDI_TYPE_EN))
1192
for (i = 0; i < visual_len; i++)
1195
grub_free (resolved_types);
1199
ret = bidi_line_wrap (visual_out, visual, visual_len, levels,
1200
getcharwidth, maxwidth, startwidth);
1208
grub_bidi_logical_to_visual (const grub_uint32_t *logical,
1209
grub_size_t logical_len,
1210
struct grub_unicode_glyph **visual_out,
1211
grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual),
1212
grub_size_t max_length, grub_size_t startwidth)
1214
const grub_uint32_t *line_start = logical, *ptr;
1215
struct grub_unicode_glyph *visual_ptr;
1216
*visual_out = visual_ptr = grub_malloc (2 * sizeof (visual_ptr[0])
1218
for (ptr = logical; ptr <= logical + logical_len; ptr++)
1220
if (ptr == logical + logical_len || *ptr == '\n')
1223
ret = grub_bidi_line_logical_to_visual (line_start,
1233
grub_free (*visual_out);
1238
if (ptr != logical + logical_len)
1240
grub_memset (visual_ptr, 0, sizeof (visual_ptr[0]));
1241
visual_ptr->base = '\n';
1247
return visual_ptr - *visual_out;
1251
grub_unicode_mirror_code (grub_uint32_t in)
1254
for (i = 0; grub_unicode_bidi_pairs[i].key; i++)
1255
if (grub_unicode_bidi_pairs[i].key == in)
1256
return grub_unicode_bidi_pairs[i].replace;
1261
grub_unicode_shape_code (grub_uint32_t in, grub_uint8_t attr)
1264
if (!(in >= GRUB_UNICODE_ARABIC_START
1265
&& in < GRUB_UNICODE_ARABIC_END))
1268
for (i = 0; grub_unicode_arabic_shapes[i].code; i++)
1269
if (grub_unicode_arabic_shapes[i].code == in)
1271
grub_uint32_t out = 0;
1272
switch (attr & (GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
1273
| GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED))
1276
out = grub_unicode_arabic_shapes[i].isolated;
1278
case GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED:
1279
out = grub_unicode_arabic_shapes[i].right_linked;
1281
case GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED:
1282
out = grub_unicode_arabic_shapes[i].left_linked;
1284
case GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
1285
|GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED:
1286
out = grub_unicode_arabic_shapes[i].both_linked;