Aric Stewart : usp10: Use the font GDEF table to update glyph properties.

Alexandre Julliard julliard at winehq.org
Tue May 24 12:53:47 CDT 2011


Module: wine
Branch: master
Commit: 8e8d4be5a4b3d04b9025757cd966b54cf0b6a5c9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8e8d4be5a4b3d04b9025757cd966b54cf0b6a5c9

Author: Aric Stewart <aric at codeweavers.com>
Date:   Mon May 23 11:41:32 2011 -0500

usp10: Use the font GDEF table to update glyph properties.

---

 dlls/usp10/shape.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c
index c587ca7..debd242 100644
--- a/dlls/usp10/shape.c
+++ b/dlls/usp10/shape.c
@@ -241,6 +241,38 @@ typedef struct{
     WORD Alternate[1];
 } GSUB_AlternateSet;
 
+/* These are all structures needed for the GDEF table */
+#define GDEF_TAG MS_MAKE_TAG('G', 'D', 'E', 'F')
+
+enum {BaseGlyph=1, LigatureGlyph, MarkGlyph, ComponentGlyph};
+
+typedef struct {
+    DWORD Version;
+    WORD GlyphClassDef;
+    WORD AttachList;
+    WORD LigCaretList;
+    WORD MarkAttachClassDef;
+} GDEF_Header;
+
+typedef struct {
+    WORD ClassFormat;
+    WORD StartGlyph;
+    WORD GlyphCount;
+    WORD ClassValueArray[1];
+} GDEF_ClassDefFormat1;
+
+typedef struct {
+    WORD Start;
+    WORD End;
+    WORD Class;
+} GDEF_ClassRangeRecord;
+
+typedef struct {
+    WORD ClassFormat;
+    WORD ClassRangeCount;
+    GDEF_ClassRangeRecord ClassRangeRecord[1];
+} GDEF_ClassDefFormat2;
+
 static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count);
 
 /* the orders of joined_forms and contextual_features need to line up */
@@ -894,6 +926,106 @@ static VOID *load_gsub_table(HDC hdc)
     return GSUB_Table;
 }
 
+static WORD GDEF_get_glyph_class(const GDEF_Header *header, WORD glyph)
+{
+    int offset;
+    WORD class = 0;
+    const GDEF_ClassDefFormat1 *cf1;
+
+    if (!header)
+        return 0;
+
+    offset = GET_BE_WORD(header->GlyphClassDef);
+    if (!offset)
+        return 0;
+
+    cf1 = (GDEF_ClassDefFormat1*)(((BYTE*)header)+offset);
+    if (GET_BE_WORD(cf1->ClassFormat) == 1)
+    {
+        if (glyph >= GET_BE_WORD(cf1->StartGlyph))
+        {
+            int index = glyph - GET_BE_WORD(cf1->StartGlyph);
+            if (index < GET_BE_WORD(cf1->GlyphCount))
+                class = GET_BE_WORD(cf1->ClassValueArray[index]);
+        }
+    }
+    else if (GET_BE_WORD(cf1->ClassFormat) == 2)
+    {
+        const GDEF_ClassDefFormat2 *cf2 = (GDEF_ClassDefFormat2*)cf1;
+        int i, top;
+        top = GET_BE_WORD(cf2->ClassRangeCount);
+        for (i = 0; i < top; i++)
+        {
+            if (glyph >= GET_BE_WORD(cf2->ClassRangeRecord[i].Start) &&
+                glyph <= GET_BE_WORD(cf2->ClassRangeRecord[i].End))
+            {
+                class = GET_BE_WORD(cf2->ClassRangeRecord[i].Class);
+                break;
+            }
+        }
+    }
+    else
+        ERR("Unknown Class Format %i\n",GET_BE_WORD(cf1->ClassFormat));
+
+    return class;
+}
+
+static VOID *load_gdef_table(HDC hdc)
+{
+    VOID* GDEF_Table = NULL;
+    int length = GetFontData(hdc, GDEF_TAG , 0, NULL, 0);
+    if (length != GDI_ERROR)
+    {
+        GDEF_Table = HeapAlloc(GetProcessHeap(),0,length);
+        GetFontData(hdc, GDEF_TAG , 0, GDEF_Table, length);
+        TRACE("Loaded GDEF table of %i bytes\n",length);
+    }
+    return GDEF_Table;
+}
+
+static void GDEF_UpdateGlyphProps(HDC hdc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, SCRIPT_GLYPHPROP *pGlyphProp)
+{
+    VOID* header = load_gdef_table(hdc);
+    int i;
+
+    for (i = 0; i < cGlyphs; i++)
+    {
+        WORD class;
+
+        class = GDEF_get_glyph_class(header, pwGlyphs[i]);
+
+        switch (class)
+        {
+            case 0:
+            case BaseGlyph:
+                pGlyphProp[i].sva.fClusterStart = 1;
+                pGlyphProp[i].sva.fDiacritic = 0;
+                pGlyphProp[i].sva.fZeroWidth = 0;
+                break;
+            case LigatureGlyph:
+                pGlyphProp[i].sva.fClusterStart = 1;
+                pGlyphProp[i].sva.fDiacritic = 0;
+                pGlyphProp[i].sva.fZeroWidth = 0;
+                break;
+            case MarkGlyph:
+                pGlyphProp[i].sva.fClusterStart = 0;
+                pGlyphProp[i].sva.fDiacritic = 1;
+                pGlyphProp[i].sva.fZeroWidth = 1;
+                break;
+            case ComponentGlyph:
+                pGlyphProp[i].sva.fClusterStart = 0;
+                pGlyphProp[i].sva.fDiacritic = 0;
+                pGlyphProp[i].sva.fZeroWidth = 0;
+                break;
+            default:
+                ERR("Unknown glyph class %i\n",class);
+                pGlyphProp[i].sva.fClusterStart = 1;
+                pGlyphProp[i].sva.fDiacritic = 0;
+                pGlyphProp[i].sva.fZeroWidth = 0;
+        }
+    }
+}
+
 static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int chars, WORD* pwLogClust )
 {
     if (changeCount == 0)
@@ -1351,6 +1483,8 @@ static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYS
         else
             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER;
     }
+
+    GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
 }
 
 void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp)




More information about the wine-cvs mailing list