Generate shaping table based on unicode if source font has none

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-03-29 02:06:40 +02:00
parent c0420b76b0
commit 3f11c7131e
4 changed files with 135 additions and 15 deletions

View file

@ -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

View file

@ -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[];

View file

@ -23,6 +23,7 @@
#include <grub/i18n.h>
#include <grub/fontformat.h>
#include <grub/font.h>
#include <grub/unicode.h>
#include <stdio.h>
#include <stdlib.h>
@ -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

View file

@ -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 ()