Aric Stewart : usp10: Implement Multiple Substitution Subtable.
Alexandre Julliard
julliard at winehq.org
Tue Aug 23 12:44:59 CDT 2011
Module: wine
Branch: master
Commit: fda05436d11c687273b731e8f8d35424ef0e3125
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fda05436d11c687273b731e8f8d35424ef0e3125
Author: Aric Stewart <aric at codeweavers.com>
Date: Mon Aug 22 07:18:09 2011 -0500
usp10: Implement Multiple Substitution Subtable.
---
dlls/usp10/shape.c | 118 +++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 99 insertions(+), 19 deletions(-)
diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c
index aacb998..0068b41 100644
--- a/dlls/usp10/shape.c
+++ b/dlls/usp10/shape.c
@@ -203,6 +203,18 @@ typedef struct {
typedef struct {
WORD SubstFormat; /* = 1 */
WORD Coverage;
+ WORD SequenceCount;
+ WORD Sequence[1];
+}GSUB_MultipleSubstFormat1;
+
+typedef struct {
+ WORD GlyphCount;
+ WORD Substitute[1];
+}GSUB_Sequence;
+
+typedef struct {
+ WORD SubstFormat; /* = 1 */
+ WORD Coverage;
WORD LigSetCount;
WORD LigatureSet[1];
}GSUB_LigatureSubstFormat1;
@@ -733,6 +745,54 @@ static INT GSUB_apply_SingleSubst(const GSUB_LookupTable *look, WORD *glyphs, IN
return GSUB_E_NOGLYPH;
}
+static INT GSUB_apply_MultipleSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
+{
+ int j;
+ TRACE("Multiple Substitution Subtable\n");
+
+ for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
+ {
+ int offset, index;
+ const GSUB_MultipleSubstFormat1 *msf1;
+ offset = GET_BE_WORD(look->SubTable[j]);
+ msf1 = (const GSUB_MultipleSubstFormat1*)((const BYTE*)look+offset);
+
+ offset = GET_BE_WORD(msf1->Coverage);
+ index = GSUB_is_glyph_covered((const BYTE*)msf1+offset, glyphs[glyph_index]);
+ if (index != -1)
+ {
+ const GSUB_Sequence *seq;
+ int sub_count;
+ int j;
+ offset = GET_BE_WORD(msf1->Sequence[index]);
+ seq = (const GSUB_Sequence*)((const BYTE*)msf1+offset);
+ sub_count = GET_BE_WORD(seq->GlyphCount);
+ TRACE(" Glyph 0x%x (+%i)->",glyphs[glyph_index],(sub_count-1));
+
+ for (j = (*glyph_count)+(sub_count-1); j > glyph_index; j--)
+ glyphs[j] =glyphs[j-(sub_count-1)];
+
+ for (j = 0; j < sub_count; j++)
+ if (write_dir < 0)
+ glyphs[glyph_index + (sub_count-1) - j] = GET_BE_WORD(seq->Substitute[j]);
+ else
+ glyphs[glyph_index + j] = GET_BE_WORD(seq->Substitute[j]);
+
+ *glyph_count = *glyph_count + (sub_count - 1);
+
+ if (TRACE_ON(uniscribe))
+ {
+ for (j = 0; j < sub_count; j++)
+ TRACE(" 0x%x",glyphs[glyph_index+j]);
+ TRACE("\n");
+ }
+
+ return glyph_index + sub_count;
+ }
+ }
+ return GSUB_E_NOGLYPH;
+}
+
static INT GSUB_apply_AlternateSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
{
int j;
@@ -943,6 +1003,8 @@ static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WO
{
case 1:
return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count);
+ case 2:
+ return GSUB_apply_MultipleSubst(look, glyphs, glyph_index, write_dir, glyph_count);
case 3:
return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir, glyph_count);
case 4:
@@ -1261,28 +1323,41 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch
{
int i;
int target_glyph = nextIndex - 1;
+ int seeking_glyph;
int target_index = -1;
int replacing_glyph = -1;
int changed = 0;
- if (write_dir > 0)
- for (i = 0; i < chars; i++)
- {
- if (pwLogClust[i] == target_glyph)
+
+ if (changeCount > 0)
+ target_glyph = nextIndex - (changeCount+1);
+
+ seeking_glyph = target_glyph;
+
+ do {
+ if (write_dir > 0)
+ for (i = 0; i < chars; i++)
{
- target_index = i;
- break;
+ if (pwLogClust[i] == seeking_glyph)
+ {
+ target_index = i;
+ break;
+ }
}
- }
- else
- for (i = chars - 1; i >= 0; i--)
- {
- if (pwLogClust[i] == target_glyph)
+ else
+ for (i = chars - 1; i >= 0; i--)
{
- target_index = i;
- break;
+ if (pwLogClust[i] == seeking_glyph)
+ {
+ target_index = i;
+ break;
+ }
}
- }
+ if (target_index == -1)
+ seeking_glyph ++;
+ }
+ while (target_index == -1 && seeking_glyph < chars);
+
if (target_index == -1)
{
ERR("Unable to find target glyph\n");
@@ -1310,13 +1385,18 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch
break;
}
}
- }
- /* renumber trailing indexes*/
- for(i = target_index; i < chars && i >= 0; i+=write_dir)
+ /* renumber trailing indexes*/
+ for(i = target_index; i < chars && i >= 0; i+=write_dir)
+ {
+ if (pwLogClust[i] != target_glyph)
+ pwLogClust[i] += changeCount;
+ }
+ }
+ else
{
- if (pwLogClust[i] != target_glyph)
- pwLogClust[i] += changeCount;
+ for(i = target_index; i < chars && i >= 0; i+=write_dir)
+ pwLogClust[i] += changeCount;
}
}
}
More information about the wine-cvs
mailing list