Commit bea9c706 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite/arabic: Set per-glyph action.

parent 864745e7
......@@ -18,4 +18,5 @@ C_SRCS = \
opentype.c \
scripts.c \
shape.c \
shapers/arabic.c
shapers/arabic.c \
shapers/arabic_table.c
......@@ -75,9 +75,91 @@ static void arabic_collect_features(struct scriptshaping_context *context,
shape_enable_feature(features, DWRITE_MAKE_OPENTYPE_TAG('m','s','e','t'), 0);
}
enum arabic_joining_type
{
JOINING_TYPE_U = 0,
JOINING_TYPE_L = 1,
JOINING_TYPE_R = 2,
JOINING_TYPE_D = 3,
JOINING_TYPE_C = JOINING_TYPE_D,
JOINING_GROUP_ALAPH = 4,
JOINING_GROUP_DALATH_RISH = 5,
JOINING_TYPES = 6,
JOINING_TYPE_T = 6,
};
static const struct arabic_state_table_entry
{
unsigned char prev_action;
unsigned char curr_action;
unsigned char next_state;
}
arabic_state_table[][JOINING_TYPES] =
{
/* U, L, R, D, ALAPH, DALATH_RISH */
/* State 0: prev was U, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
/* State 1: prev was R or ISOL/ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
/* State 2: prev was D/L in ISOL form, willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
/* State 3: prev was D in FINA form, willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
/* State 4: prev was FINA ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
/* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
/* State 6: prev was DALATH/RISH, not willing to join. */
{ {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
};
extern const unsigned short arabic_shaping_table[] DECLSPEC_HIDDEN;
static unsigned short arabic_get_joining_type(WCHAR ch)
{
const unsigned short *table = arabic_shaping_table;
return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
}
static void arabic_set_shaping_action(struct scriptshaping_context *context,
unsigned int idx, enum arabic_shaping_action action)
{
context->glyph_infos[idx].props &= ~(0xf << 16);
context->glyph_infos[idx].props |= (action & 0xf) << 16;
}
static void arabic_setup_masks(struct scriptshaping_context *context,
const struct shaping_features *features)
{
unsigned int i, prev = ~0u, state = 0;
for (i = 0; i < context->length; ++i)
{
unsigned short this_type = arabic_get_joining_type(context->text[i]);
const struct arabic_state_table_entry *entry;
if (this_type == JOINING_TYPE_T)
{
arabic_set_shaping_action(context, i, NONE);
continue;
}
entry = &arabic_state_table[state][this_type];
if (entry->prev_action != NONE && prev != ~0u)
arabic_set_shaping_action(context, prev, entry->prev_action);
arabic_set_shaping_action(context, i, entry->curr_action);
prev = i;
state = entry->next_state;
}
}
const struct shaper arabic_shaper =
......
......@@ -435,7 +435,7 @@ my @tolower_table = ();
my @toupper_table = ();
my @digitmap_table = ();
my @category_table = ();
my @joining_table = ();
my @initial_joining_table = ();
my @direction_table = ();
my @decomp_table = ();
my @combining_class_table = ();
......@@ -645,11 +645,11 @@ sub load_data()
$direction_table[$src] = $bidi;
if ($cat eq "Mn" || $cat eq "Me" || $cat eq "Cf")
{
$joining_table[$src] = $joining_types{"T"};
$initial_joining_table[$src] = $joining_types{"T"};
}
else
{
$joining_table[$src] = $joining_types{"U"};
$initial_joining_table[$src] = $joining_types{"U"};
}
if ($lower ne "")
......@@ -1609,6 +1609,7 @@ sub dump_bracket($)
sub dump_shaping($)
{
my $filename = shift;
my @joining_table = @initial_joining_table;
my $INPUT = open_data_file( $UNIDATA, "ArabicShaping.txt" );
while (<$INPUT>)
......@@ -1651,6 +1652,52 @@ sub dump_shaping($)
}
################################################################
# dump the Arabic shaping table
sub dump_arabic_shaping($)
{
my $filename = shift;
my @joining_table = @initial_joining_table;
my $INPUT = open_data_file( $UNIDATA, "ArabicShaping.txt" );
while (<$INPUT>)
{
next if /^\#/; # skip comments
next if /^\s*$/; # skip empty lines
next if /\x1a/; # skip ^Z
if (/^\s*([0-9a-fA-F]+)\s*;.*;\s*([RLDCUT])\s*;\s*(\w+)/)
{
my $type = $2;
my $group = $3;
if ($group eq "ALAPH" || $group eq "DALATH RISH")
{
$joining_table[hex $1] = $joining_types{$group};
}
else
{
$joining_table[hex $1] = $joining_types{$type};
}
next;
}
die "malformed line $_";
}
close $INPUT;
open OUTPUT,">$filename.new" or die "Cannot create $filename";
print "Building $filename\n";
print OUTPUT "/* Unicode Arabic shaping */\n";
print OUTPUT "/* generated from $UNIDATA:ArabicShaping.txt */\n";
print OUTPUT "/* DO NOT EDIT!! */\n\n";
print OUTPUT "#include \"windef.h\"\n\n";
dump_two_level_mapping( "arabic_shaping_table", 0, 16, @joining_table );
close OUTPUT;
save_file($filename);
}
################################################################
# dump the Vertical Orientation table
sub dump_vertical($)
{
......@@ -2710,6 +2757,7 @@ dump_mirroring( "dlls/dwrite/mirror.c" );
dump_bracket( "dlls/gdi32/uniscribe/bracket.c" );
dump_bracket( "dlls/dwrite/bracket.c" );
dump_shaping( "dlls/gdi32/uniscribe/shaping.c" );
dump_arabic_shaping( "dlls/dwrite/shapers/arabic_table.c" );
dump_linebreak( "dlls/gdi32/uniscribe/linebreak.c" );
dump_linebreak( "dlls/dwrite/linebreak.c" );
dump_scripts( "dlls/dwrite/scripts" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment