Aric Stewart : usp10: Start implementing Chaining Context Substitution Format 3: Coverage-based Chaining Context Glyph Substitution.
Alexandre Julliard
julliard at winehq.org
Fri Jul 23 10:05:42 CDT 2010
Module: wine
Branch: master
Commit: 1b37809dba65745828d7895ad5fda9bc3fd1e403
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b37809dba65745828d7895ad5fda9bc3fd1e403
Author: Aric Stewart <aric at codeweavers.com>
Date: Thu Jul 22 16:18:02 2010 -0500
usp10: Start implementing Chaining Context Substitution Format 3: Coverage-based Chaining Context Glyph Substitution.
---
dlls/usp10/shape.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 133 insertions(+), 0 deletions(-)
diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c
index 0a4f5b9..0018ae5 100644
--- a/dlls/usp10/shape.c
+++ b/dlls/usp10/shape.c
@@ -185,6 +185,42 @@ typedef struct{
WORD Component[1];
}GSUB_Ligature;
+typedef struct{
+ WORD SequenceIndex;
+ WORD LookupListIndex;
+
+}GSUB_SubstLookupRecord;
+
+typedef struct{
+ WORD SubstFormat; /* = 1 */
+ WORD Coverage;
+ WORD ChainSubRuleSetCount;
+ WORD ChainSubRuleSet[1];
+}GSUB_ChainContextSubstFormat1;
+
+typedef struct {
+ WORD SubstFormat; /* = 3 */
+ WORD BacktrackGlyphCount;
+ WORD Coverage[1];
+}GSUB_ChainContextSubstFormat3_1;
+
+typedef struct{
+ WORD InputGlyphCount;
+ WORD Coverage[1];
+}GSUB_ChainContextSubstFormat3_2;
+
+typedef struct{
+ WORD LookaheadGlyphCount;
+ WORD Coverage[1];
+}GSUB_ChainContextSubstFormat3_3;
+
+typedef struct{
+ WORD SubstCount;
+ GSUB_SubstLookupRecord SubstLookupRecord[1];
+}GSUB_ChainContextSubstFormat3_4;
+
+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 */
static const char* contextual_features[] =
{
@@ -429,6 +465,101 @@ static INT GSUB_apply_LigatureSubst(const GSUB_LookupTable *look, WORD *glyphs,
return GSUB_E_NOGLYPH;
}
+static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
+{
+ int j;
+ BOOL done = FALSE;
+
+ TRACE("Chaining Contextual Substitution Subtable\n");
+ for (j = 0; j < GET_BE_WORD(look->SubTableCount) && !done; j++)
+ {
+ const GSUB_ChainContextSubstFormat1 *ccsf1;
+ int offset;
+ int dirLookahead = write_dir;
+ int dirBacktrack = -1 * write_dir;
+
+ offset = GET_BE_WORD(look->SubTable[j]);
+ ccsf1 = (const GSUB_ChainContextSubstFormat1*)((const BYTE*)look+offset);
+ if (GET_BE_WORD(ccsf1->SubstFormat) == 1)
+ {
+ FIXME(" TODO: subtype 1 (Simple context glyph substitution)\n");
+ return -1;
+ }
+ else if (GET_BE_WORD(ccsf1->SubstFormat) == 2)
+ {
+ FIXME(" TODO: subtype 2 (Class-based Chaining Context Glyph Substitution)\n");
+ return -1;
+ }
+ else if (GET_BE_WORD(ccsf1->SubstFormat) == 3)
+ {
+ int k;
+ int indexGlyphs;
+ const GSUB_ChainContextSubstFormat3_1 *ccsf3_1;
+ const GSUB_ChainContextSubstFormat3_2 *ccsf3_2;
+ const GSUB_ChainContextSubstFormat3_3 *ccsf3_3;
+ const GSUB_ChainContextSubstFormat3_4 *ccsf3_4;
+ int newIndex = glyph_index;
+
+ ccsf3_1 = (const GSUB_ChainContextSubstFormat3_1 *)ccsf1;
+
+ TRACE(" subtype 3 (Coverage-based Chaining Context Glyph Substitution)\n");
+
+ for (k = 0; k < GET_BE_WORD(ccsf3_1->BacktrackGlyphCount); k++)
+ {
+ offset = GET_BE_WORD(ccsf3_1->Coverage[k]);
+ if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirBacktrack * (k+1))]) == -1)
+ break;
+ }
+ if (k != GET_BE_WORD(ccsf3_1->BacktrackGlyphCount))
+ return -1;
+ TRACE("Matched Backtrack\n");
+
+ ccsf3_2 = (const GSUB_ChainContextSubstFormat3_2 *)(((LPBYTE)ccsf1)+sizeof(GSUB_ChainContextSubstFormat3_1) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)-1)));
+
+ indexGlyphs = GET_BE_WORD(ccsf3_2->InputGlyphCount);
+ for (k = 0; k < indexGlyphs; k++)
+ {
+ offset = GET_BE_WORD(ccsf3_2->Coverage[k]);
+ if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (write_dir * k)]) == -1)
+ break;
+ }
+ if (k != indexGlyphs)
+ return -1;
+ TRACE("Matched IndexGlyphs\n");
+
+ ccsf3_3 = (const GSUB_ChainContextSubstFormat3_3 *)(((LPBYTE)ccsf3_2)+sizeof(GSUB_ChainContextSubstFormat3_2) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_2->InputGlyphCount)-1)));
+
+ for (k = 0; k < GET_BE_WORD(ccsf3_3->LookaheadGlyphCount); k++)
+ {
+ offset = GET_BE_WORD(ccsf3_3->Coverage[k]);
+ if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k+1))]) == -1)
+ break;
+ }
+ if (k != GET_BE_WORD(ccsf3_3->LookaheadGlyphCount))
+ return -1;
+ TRACE("Matched LookAhead\n");
+
+ ccsf3_4 = (const GSUB_ChainContextSubstFormat3_4 *)(((LPBYTE)ccsf3_3)+sizeof(GSUB_ChainContextSubstFormat3_3) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)-1)));
+
+ for (k = 0; k < GET_BE_WORD(ccsf3_4->SubstCount); k++)
+ {
+ int lookupIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].LookupListIndex);
+ int SequenceIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].SequenceIndex) * write_dir;
+
+ TRACE("SUBST: %i -> %i %i\n",k, SequenceIndex, lookupIndex);
+ newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count);
+ if (newIndex == -1)
+ {
+ ERR("Chain failed to generate a glyph\n");
+ return -1;
+ }
+ }
+ return newIndex + 1;
+ }
+ }
+ return -1;
+}
+
static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
{
int offset;
@@ -443,6 +574,8 @@ static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WO
return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count);
case 4:
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);
default:
FIXME("We do not handle SubType %i\n",GET_BE_WORD(look->LookupType));
}
More information about the wine-cvs
mailing list