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

This commit is contained in:
Aric Stewart 2011-05-23 11:41:32 -05:00 committed by Alexandre Julliard
parent c7e42c05a5
commit 8e8d4be5a4

View file

@ -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)