diff --git a/dlls/usp10/opentype.c b/dlls/usp10/opentype.c index e15df8d9598..377558afbd2 100644 --- a/dlls/usp10/opentype.c +++ b/dlls/usp10/opentype.c @@ -73,6 +73,37 @@ typedef struct { CMAP_SegmentedCoverage_group groups[1]; } CMAP_SegmentedCoverage; +/* 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; /********** * CMAP @@ -160,3 +191,118 @@ DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWOR } return 0; } + +/********** + * GDEF + **********/ + +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; +} + +void OpenType_GDEF_UpdateGlyphProps(HDC hdc, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) +{ + int i; + + if (!psc->GDEF_Table) + psc->GDEF_Table = load_gdef_table(hdc); + + for (i = 0; i < cGlyphs; i++) + { + WORD class; + int char_count = 0; + int k; + + for (k = 0; k < cChars; k++) + if (pwLogClust[k] == i) + char_count++; + + class = GDEF_get_glyph_class(psc->GDEF_Table, 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; + } + + if (char_count == 0) + pGlyphProp[i].sva.fClusterStart = 0; + } +} diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index e33e9222eb7..151f9a4a48d 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -283,38 +283,6 @@ 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); static HRESULT GSUB_GetFontScriptTags(ScriptCache *psc, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags, LPCVOID* script_table); static HRESULT GSUB_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pLanguageTags, int *pcTags, LPCVOID* language_table); @@ -1210,117 +1178,6 @@ INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, Script return rc; } -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, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) -{ - int i; - - if (!psc->GDEF_Table) - psc->GDEF_Table = load_gdef_table(hdc); - - for (i = 0; i < cGlyphs; i++) - { - WORD class; - int char_count = 0; - int k; - - for (k = 0; k < cChars; k++) - if (pwLogClust[k] == i) - char_count++; - - class = GDEF_get_glyph_class(psc->GDEF_Table, 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; - } - - if (char_count == 0) - pGlyphProp[i].sva.fClusterStart = 0; - } -} - static void UpdateClustersFromGlyphProp(const int cGlyphs, const int cChars, WORD* pwLogClust, SCRIPT_GLYPHPROP *pGlyphProp) { int i; @@ -3087,7 +2944,7 @@ static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYS pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; } - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); } @@ -3198,7 +3055,7 @@ static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; } - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); HeapFree(GetProcessHeap(),0,spaces); } @@ -3234,7 +3091,7 @@ static void ShapeCharGlyphProp_Thai( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } } - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); for (i = 0; i < cGlyphs; i++) { @@ -3308,7 +3165,7 @@ static void ShapeCharGlyphProp_None( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* else pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; } - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); } @@ -3341,7 +3198,7 @@ static void ShapeCharGlyphProp_Tibet( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS else pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; } - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); /* Tibeten script does not set sva.fDiacritic or sva.fZeroWidth */ @@ -3359,7 +3216,7 @@ static void ShapeCharGlyphProp_BaseIndic( HDC hdc, ScriptCache *psc, SCRIPT_ANAL { int i,k; - GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); for (i = 0; i < cGlyphs; i++) { int char_index[20]; diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 6738ef055cd..2df8a69519d 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -222,3 +222,4 @@ void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCW void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) DECLSPEC_HIDDEN; DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) DECLSPEC_HIDDEN; +void OpenType_GDEF_UpdateGlyphProps(HDC hdc, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN;