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