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