Aric Stewart : usp10: Handle GSUB SubType 7: Extension Substitution.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Feb 15 09:41:49 CST 2016
Module: wine
Branch: master
Commit: 12fb74ac565fc2b8f7f79c3706106b560197e0ce
URL: http://source.winehq.org/git/wine.git/?a=commit;h=12fb74ac565fc2b8f7f79c3706106b560197e0ce
Author: Aric Stewart <aric at codeweavers.com>
Date: Fri Feb 12 11:24:05 2016 -0600
usp10: Handle GSUB SubType 7: Extension Substitution.
Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/usp10/opentype.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 58 insertions(+), 15 deletions(-)
diff --git a/dlls/usp10/opentype.c b/dlls/usp10/opentype.c
index e7f2dfd..5b39663 100644
--- a/dlls/usp10/opentype.c
+++ b/dlls/usp10/opentype.c
@@ -277,6 +277,12 @@ typedef struct{
WORD Alternate[1];
} GSUB_AlternateSet;
+typedef struct {
+ WORD SubstFormat;
+ WORD ExtensionLookupType;
+ DWORD ExtensionOffset;
+} GSUB_ExtensionPosFormat1;
+
/* These are all structures needed for the GPOS table */
typedef struct {
@@ -725,6 +731,25 @@ static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
return -1;
}
+static const BYTE *GSUB_get_subtable(const OT_LookupTable *look, int index)
+{
+ int offset = GET_BE_WORD(look->SubTable[index]);
+
+ if (GET_BE_WORD(look->LookupType) == 7)
+ {
+ const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)look + offset);
+ if (GET_BE_WORD(ext->SubstFormat) == 1)
+ {
+ offset += GET_BE_DWORD(ext->ExtensionOffset);
+ }
+ else
+ {
+ FIXME("Unhandled Extension Substitution Format %i\n",GET_BE_WORD(ext->SubstFormat));
+ }
+ }
+ return (const BYTE *)look + offset;
+}
+
static INT GSUB_apply_SingleSubst(const OT_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
{
int j;
@@ -732,10 +757,7 @@ static INT GSUB_apply_SingleSubst(const OT_LookupTable *look, WORD *glyphs, INT
for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
{
- int offset;
- const GSUB_SingleSubstFormat1 *ssf1;
- offset = GET_BE_WORD(look->SubTable[j]);
- ssf1 = (const GSUB_SingleSubstFormat1*)((const BYTE*)look+offset);
+ const GSUB_SingleSubstFormat1 *ssf1 = (const GSUB_SingleSubstFormat1*)GSUB_get_subtable(look, j);
if (GET_BE_WORD(ssf1->SubstFormat) == 1)
{
int offset = GET_BE_WORD(ssf1->Coverage);
@@ -783,8 +805,7 @@ static INT GSUB_apply_MultipleSubst(const OT_LookupTable *look, WORD *glyphs, IN
{
int offset, index;
const GSUB_MultipleSubstFormat1 *msf1;
- offset = GET_BE_WORD(look->SubTable[j]);
- msf1 = (const GSUB_MultipleSubstFormat1*)((const BYTE*)look+offset);
+ msf1 = (const GSUB_MultipleSubstFormat1*)GSUB_get_subtable(look, j);
offset = GET_BE_WORD(msf1->Coverage);
index = GSUB_is_glyph_covered((const BYTE*)msf1+offset, glyphs[glyph_index]);
@@ -833,8 +854,7 @@ static INT GSUB_apply_AlternateSubst(const OT_LookupTable *look, WORD *glyphs, I
const GSUB_AlternateSubstFormat1 *asf1;
INT index;
- offset = GET_BE_WORD(look->SubTable[j]);
- asf1 = (const GSUB_AlternateSubstFormat1*)((const BYTE*)look+offset);
+ asf1 = (const GSUB_AlternateSubstFormat1*)GSUB_get_subtable(look, j);
offset = GET_BE_WORD(asf1->Coverage);
index = GSUB_is_glyph_covered((const BYTE*)asf1+offset, glyphs[glyph_index]);
@@ -866,8 +886,7 @@ static INT GSUB_apply_LigatureSubst(const OT_LookupTable *look, WORD *glyphs, IN
const GSUB_LigatureSubstFormat1 *lsf1;
int offset,index;
- offset = GET_BE_WORD(look->SubTable[j]);
- lsf1 = (const GSUB_LigatureSubstFormat1*)((const BYTE*)look+offset);
+ lsf1 = (const GSUB_LigatureSubstFormat1*)GSUB_get_subtable(look, j);
offset = GET_BE_WORD(lsf1->Coverage);
index = GSUB_is_glyph_covered((const BYTE*)lsf1+offset, glyphs[glyph_index]);
TRACE(" Coverage index %i\n",index);
@@ -933,8 +952,7 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo
int dirLookahead = write_dir;
int dirBacktrack = -1 * write_dir;
- offset = GET_BE_WORD(look->SubTable[j]);
- ccsf1 = (const GSUB_ChainContextSubstFormat1*)((const BYTE*)look+offset);
+ ccsf1 = (const GSUB_ChainContextSubstFormat1*)GSUB_get_subtable(look, j);
if (GET_BE_WORD(ccsf1->SubstFormat) == 1)
{
static int once;
@@ -1029,12 +1047,34 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo
static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
{
int offset;
+ int type;
const OT_LookupTable *look;
offset = GET_BE_WORD(lookup->Lookup[lookup_index]);
look = (const OT_LookupTable*)((const BYTE*)lookup + offset);
- TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
- switch(GET_BE_WORD(look->LookupType))
+ type = GET_BE_WORD(look->LookupType);
+ TRACE("type %i, flag %x, subtables %i\n",type,GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
+ if (type == 7)
+ {
+ if (GET_BE_WORD(look->SubTableCount))
+ {
+ const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)look + GET_BE_WORD(look->SubTable[0]));
+ if (GET_BE_WORD(ext->SubstFormat) == 1)
+ {
+ type = GET_BE_WORD(ext->ExtensionLookupType);
+ TRACE("extension type %i\n",type);
+ }
+ else
+ {
+ FIXME("Unhandled Extension Substitution Format %i\n",GET_BE_WORD(ext->SubstFormat));
+ }
+ }
+ else
+ {
+ WARN("lookup type is Extension Substitution but no extension subtable exists\n");
+ }
+ }
+ switch(type)
{
case 1:
return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count);
@@ -1046,8 +1086,11 @@ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD
return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir, glyph_count);
case 6:
return GSUB_apply_ChainContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count);
+ case 7:
+ FIXME("Extension Substitution types not valid here\n");
+ break;
default:
- FIXME("We do not handle SubType %i\n",GET_BE_WORD(look->LookupType));
+ FIXME("We do not handle SubType %i\n",type);
}
return GSUB_E_NOGLYPH;
}
More information about the wine-cvs
mailing list