diff --git a/conf/common.rmk b/conf/common.rmk index d790abade..c157e9578 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -82,7 +82,7 @@ grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c util/hostfs.c \ # For grub-mkfont. ifeq ($(enable_grub_mkfont), yes) bin_UTILITIES += grub-mkfont -grub_mkfont_SOURCES = gnulib/progname.c util/grub-mkfont.c util/misc.c +grub_mkfont_SOURCES = gnulib/progname.c util/grub-mkfont.c util/misc.c unidata.c grub_mkfont_CFLAGS = $(freetype_cflags) grub_mkfont_LDFLAGS = $(freetype_libs) endif diff --git a/include/grub/unicode.h b/include/grub/unicode.h index 28c752b9e..9fde69cc8 100644 --- a/include/grub/unicode.h +++ b/include/grub/unicode.h @@ -39,6 +39,19 @@ struct grub_unicode_compact_range grub_uint8_t join_type:3; } __attribute__ ((packed)); +/* Old-style Arabic shaping. Used for "visual UTF-8" and + in grub-mkfont to find variant glyphs in absence of GPOS tables. */ +struct grub_unicode_arabic_shape +{ + grub_uint32_t code; + grub_uint32_t isolated; + grub_uint32_t right_linked; + grub_uint32_t both_linked; + grub_uint32_t left_linked; +}; + +extern struct grub_unicode_arabic_shape grub_unicode_arabic_shapes[]; + enum grub_bidi_type { GRUB_BIDI_TYPE_L = 0, @@ -150,6 +163,8 @@ struct grub_unicode_glyph #define GRUB_UNICODE_HEBREW_WAW 0x05d5 #define GRUB_UNICODE_ZWNJ 0x200c #define GRUB_UNICODE_ZWJ 0x200d +#define GRUB_UNICODE_ARABIC_START 0x600 +#define GRUB_UNICODE_ARABIC_END 0x700 extern struct grub_unicode_compact_range grub_unicode_compact[]; extern struct grub_unicode_bidi_pair grub_unicode_bidi_pairs[]; diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index c9d48ed7a..886fc8d4a 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -184,12 +185,18 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, err = FT_Load_Glyph (face, glyph_idx, flag); if (err) { - if (err < ARRAY_SIZE (ft_errmsgs)) - printf ("Freetype Error %d loading glyph 0x%x for U+0x%x: %s\n", - err, glyph_idx, char_code, ft_errmsgs[err]); + printf ("Freetype Error %d loading glyph 0x%x for U+0x%x%s", + err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK, + char_code & GRUB_FONT_CODE_RIGHT_JOINED + ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (medial)": + " (leftmost)") + : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)": + "")); + + if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) + printf (": %s\n", ft_errmsgs[err]); else - printf ("Freetype Error %d loading glyph 0x%x for U+0x%x\n", - err, glyph_idx, char_code); + printf ("\n"); return; } @@ -268,6 +275,25 @@ add_char (struct grub_font_info *font_info, FT_Face face, char_code | GRUB_FONT_CODE_RIGHT_JOINED); break; } + if (!cur && char_code >= GRUB_UNICODE_ARABIC_START + && char_code < GRUB_UNICODE_ARABIC_END) + { + int i; + for (i = 0; grub_unicode_arabic_shapes[i].code; i++) + if (grub_unicode_arabic_shapes[i].code == char_code + && grub_unicode_arabic_shapes[i].right_linked) + { + FT_UInt idx2; + idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i] + .right_linked); + if (idx2) + add_glyph (font_info, idx2, face, + char_code | GRUB_FONT_CODE_RIGHT_JOINED); + break; + } + + } + for (cur = subst_leftjoin; cur; cur = cur->next) if (cur->from == glyph_idx) { @@ -275,6 +301,24 @@ add_char (struct grub_font_info *font_info, FT_Face face, char_code | GRUB_FONT_CODE_LEFT_JOINED); break; } + if (!cur && char_code >= GRUB_UNICODE_ARABIC_START + && char_code < GRUB_UNICODE_ARABIC_END) + { + int i; + for (i = 0; grub_unicode_arabic_shapes[i].code; i++) + if (grub_unicode_arabic_shapes[i].code == char_code + && grub_unicode_arabic_shapes[i].left_linked) + { + FT_UInt idx2; + idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i] + .left_linked); + if (idx2) + add_glyph (font_info, idx2, face, + char_code | GRUB_FONT_CODE_LEFT_JOINED); + break; + } + + } for (cur = subst_medijoin; cur; cur = cur->next) if (cur->from == glyph_idx) { @@ -283,6 +327,25 @@ add_char (struct grub_font_info *font_info, FT_Face face, | GRUB_FONT_CODE_RIGHT_JOINED); break; } + if (!cur && char_code >= GRUB_UNICODE_ARABIC_START + && char_code < GRUB_UNICODE_ARABIC_END) + { + int i; + for (i = 0; grub_unicode_arabic_shapes[i].code; i++) + if (grub_unicode_arabic_shapes[i].code == char_code + && grub_unicode_arabic_shapes[i].both_linked) + { + FT_UInt idx2; + idx2 = FT_Get_Char_Index (face, grub_unicode_arabic_shapes[i] + .both_linked); + if (idx2) + add_glyph (font_info, idx2, face, + char_code | GRUB_FONT_CODE_LEFT_JOINED + | GRUB_FONT_CODE_RIGHT_JOINED); + break; + } + + } } struct gsub_header diff --git a/util/import_unicode.py b/util/import_unicode.py index 653d7bae2..1ee162d3f 100644 --- a/util/import_unicode.py +++ b/util/import_unicode.py @@ -35,15 +35,15 @@ for line in infile: sp = line.split (";") curcode = int (sp[0], 16) if sp[2] == "U": - joining[curcode] = "GRUB_JOIN_TYPE_NONJOINING" + joining[curcode] = "NONJOINING" elif sp[2] == "L": - joining[curcode] = "GRUB_JOIN_TYPE_LEFT" + joining[curcode] = "LEFT" elif sp[2] == "R": - joining[curcode] = "GRUB_JOIN_TYPE_RIGHT" + joining[curcode] = "RIGHT" elif sp[2] == "D": - joining[curcode] = "GRUB_JOIN_TYPE_DUAL" + joining[curcode] = "DUAL" elif sp[2] == "C": - joining[curcode] = "GRUB_JOIN_TYPE_CAUSING" + joining[curcode] = "CAUSING" else: print ("Unknown joining type '%s'" % sp[2]) exit (1) @@ -60,6 +60,7 @@ lastcode = -2 lastbiditype = "X" lastmirrortype = False lastcombtype = -1 +arabicsubst = {} for line in infile: sp = line.split (";") curcode = int (sp[0], 16) @@ -102,15 +103,35 @@ for line in infile: if curcode in joining: curjoin = joining[curcode] elif sp[2] == "Me" or sp[2] == "Mn" or sp[2] == "Cf": - curjoin = "GRUB_JOIN_TYPE_TRANSPARENT" + curjoin = "TRANSPARENT" else: - curjoin = "GRUB_JOIN_TYPE_NONJOINING" + curjoin = "NONJOINING" + if sp[1].startswith ("ARABIC LETTER "): + arabname = sp[1][len ("ARABIC LETTER "):] + form = 0 + if arabname.endswith (" ISOLATED FORM"): + arabname = arabname[0:len (arabname) - len (" ISOLATED FORM")] + form = 1 + if arabname.endswith (" FINAL FORM"): + arabname = arabname[0:len (arabname) - len (" FINAL FORM")] + form = 2 + if arabname.endswith (" MEDIAL FORM"): + arabname = arabname[0:len (arabname) - len (" MEDIAL FORM")] + form = 3 + if arabname.endswith (" INITIAL FORM"): + arabname = arabname[0:len (arabname) - len (" INITIAL FORM")] + form = 4 + if arabname not in arabicsubst: + arabicsubst[arabname]={} + arabicsubst[arabname][form] = curcode; + if form == 0: + arabicsubst[arabname]['join'] = curjoin if lastcode + 1 != curcode or curbiditype != lastbiditype \ or curcombtype != lastcombtype or curmirrortype != lastmirrortype \ or curjoin != lastjoin: if begincode != -2 and (lastbiditype != "L" or lastcombtype != 0 or \ lastmirrortype): - outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, %s},\n" \ + outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, GRUB_JOIN_TYPE_%s},\n" \ % (begincode, lastcode, lastbiditype, \ lastcombtype, lastmirrortype, \ lastjoin))) @@ -121,7 +142,7 @@ for line in infile: lastcombtype = curcombtype lastmirrortype = curmirrortype if lastbiditype != "L" or lastcombtype != 0 or lastmirrortype: - outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, %s},\n" \ + outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, GRUB_JOIN_TYPE_%s},\n" \ % (begincode, lastcode, lastbiditype, lastcombtype, \ lastmirrortype, lastjoin))) outfile.write ("{0, 0, 0, 0, 0, 0},\n") @@ -147,3 +168,24 @@ for line in infile: outfile.write ("{0, 0},\n") outfile.write ("};\n") +infile.close () + +outfile.write ("struct grub_unicode_arabic_shape grub_unicode_arabic_shapes[] = {\n ") + +for x in arabicsubst: + try: + if arabicsubst[x]['join'] == "DUAL": + outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], arabicsubst[x][2], arabicsubst[x][3], arabicsubst[x][4])) + elif arabicsubst[x]['join'] == "RIGHT": + outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], arabicsubst[x][2], 0, 0)) + elif arabicsubst[x]['join'] == "LEFT": + outfile.write ("{0x%x, 0x%x, 0x%x, 0x%x, 0x%x},\n " % (arabicsubst[x][0], arabicsubst[x][1], 0, 0, arabicsubst[x][4])) + except: + pass + +outfile.write ("{0, 0, 0, 0, 0},\n") +outfile.write ("};\n") + + +outfile.close () +