Author: akhaldi
Date: Sun Mar 19 16:53:04 2017
New Revision: 74193
URL:
http://svn.reactos.org/svn/reactos?rev=74193&view=rev
Log:
[USP10] Sync with Wine Staging 2.2. CORE-12823
d00f731 usp10: Itemise ZWSP like ZWNJ and ZWJ.
721fbf6 usp10: Explicitly check for zero-width control characters in
ScriptShapeOpenType().
7e6a4b2 usp10: Fix LB27 rule that should check for prefix, not suffix.
c4626bb usp10: Fixed LB30 condition, breaking after CP class.
0c14195 usp10: Apply 'ccmp' before Arabic contextual shaping.
e2d4cf9 usp10: Fix next index for RTL MultipleSubst.
0401bdf usp10: Change GSUB_E_NOGLYPH value.
10e9adf usp10: Fix Contextual Shaping for Languages with RTL write order.
961e1e6 usp10: Fix ScriptRecordDigitSubstitution spec file entry.
aae5a83 usp10: Implement Chaining Context Substitution Format 2: Class-based Chaining
Context Glyph Substitution.
b98a70a usp10: Implement Contextual Positioning Subtable: Format 2.
5e6b2c0 usp10: Implement GSUB Context Substitution types 1 and 2.
c705eca usp10: A spelling fix in a comment.
Modified:
trunk/reactos/dll/win32/usp10/breaking.c
trunk/reactos/dll/win32/usp10/opentype.c
trunk/reactos/dll/win32/usp10/shape.c
trunk/reactos/dll/win32/usp10/usp10.c
trunk/reactos/dll/win32/usp10/usp10.spec
trunk/reactos/dll/win32/usp10/usp10_internal.h
trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/usp10/breaking.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/breaking.c…
==============================================================================
--- trunk/reactos/dll/win32/usp10/breaking.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/breaking.c [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -371,7 +371,7 @@
if (break_class[i+1] == b_IN || break_class[i+1] == b_PO)
else_break(&break_before[i+1],b_x);
}
- if (break_class[i] == b_PO)
+ if (break_class[i] == b_PR)
{
switch (break_class[i+1])
{
@@ -401,7 +401,7 @@
break_class[i+1] == b_OP)
else_break(&break_before[i+1],b_x);
if (break_class[i] == b_CP &&
- (break_class[i+1] == b_AL || break_class[i] == b_HL || break_class[i] ==
b_NU))
+ (break_class[i+1] == b_AL || break_class[i+1] == b_HL || break_class[i+1]
== b_NU))
else_break(&break_before[i+1],b_x);
/* LB30a */
Modified: trunk/reactos/dll/win32/usp10/opentype.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/opentype.c…
==============================================================================
--- trunk/reactos/dll/win32/usp10/opentype.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/opentype.c [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -228,11 +228,91 @@
}GSUB_SubstLookupRecord;
typedef struct{
+ WORD SubstFormat;
+ WORD Coverage;
+ WORD SubRuleSetCount;
+ WORD SubRuleSet[1];
+}GSUB_ContextSubstFormat1;
+
+typedef struct{
+ WORD SubRuleCount;
+ WORD SubRule[1];
+}GSUB_SubRuleSet;
+
+typedef struct {
+ WORD GlyphCount;
+ WORD SubstCount;
+ WORD Input[1];
+}GSUB_SubRule_1;
+
+typedef struct {
+ GSUB_SubstLookupRecord SubstLookupRecord[1];
+}GSUB_SubRule_2;
+
+typedef struct {
+ WORD SubstFormat;
+ WORD Coverage;
+ WORD ClassDef;
+ WORD SubClassSetCnt;
+ WORD SubClassSet[1];
+}GSUB_ContextSubstFormat2;
+
+typedef struct {
+ WORD SubClassRuleCnt;
+ WORD SubClassRule[1];
+}GSUB_SubClassSet;
+
+typedef struct {
+ WORD GlyphCount;
+ WORD SubstCount;
+ WORD Class[1];
+}GSUB_SubClassRule_1;
+
+typedef struct {
+ GSUB_SubstLookupRecord SubstLookupRecord[1];
+}GSUB_SubClassRule_2;
+
+typedef struct{
WORD SubstFormat; /* = 1 */
WORD Coverage;
WORD ChainSubRuleSetCount;
WORD ChainSubRuleSet[1];
}GSUB_ChainContextSubstFormat1;
+
+typedef struct {
+ WORD SubstFormat; /* = 2 */
+ WORD Coverage;
+ WORD BacktrackClassDef;
+ WORD InputClassDef;
+ WORD LookaheadClassDef;
+ WORD ChainSubClassSetCnt;
+ WORD ChainSubClassSet[1];
+}GSUB_ChainContextSubstFormat2;
+
+typedef struct {
+ WORD ChainSubClassRuleCnt;
+ WORD ChainSubClassRule[1];
+}GSUB_ChainSubClassSet;
+
+typedef struct {
+ WORD BacktrackGlyphCount;
+ WORD Backtrack[1];
+}GSUB_ChainSubClassRule_1;
+
+typedef struct {
+ WORD InputGlyphCount;
+ WORD Input[1];
+}GSUB_ChainSubClassRule_2;
+
+typedef struct {
+ WORD LookaheadGlyphCount;
+ WORD LookAhead[1];
+}GSUB_ChainSubClassRule_3;
+
+typedef struct {
+ WORD SubstCount;
+ GSUB_SubstLookupRecord SubstLookupRecord[1];
+}GSUB_ChainSubClassRule_4;
typedef struct {
WORD SubstFormat; /* = 3 */
@@ -453,6 +533,29 @@
WORD SequenceIndex;
WORD LookupListIndex;
} GPOS_PosLookupRecord;
+
+typedef struct {
+ WORD PosFormat;
+ WORD Coverage;
+ WORD ClassDef;
+ WORD PosClassSetCnt;
+ WORD PosClassSet[1];
+} GPOS_ContextPosFormat2;
+
+typedef struct {
+ WORD PosClassRuleCnt;
+ WORD PosClassRule[1];
+} GPOS_PosClassSet;
+
+typedef struct {
+ WORD GlyphCount;
+ WORD PosCount;
+ WORD Class[1];
+} GPOS_PosClassRule_1;
+
+typedef struct {
+ GPOS_PosLookupRecord PosLookupRecord[1];
+} GPOS_PosClassRule_2;
typedef struct {
WORD PosFormat;
@@ -827,7 +930,10 @@
TRACE("\n");
}
- return glyph_index + (sub_count * write_dir);
+ if (write_dir > 0)
+ return glyph_index + sub_count;
+ else
+ return glyph_index - 1;
}
}
return GSUB_E_NOGLYPH;
@@ -930,6 +1036,151 @@
return GSUB_E_NOGLYPH;
}
+static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupTable
*look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
+{
+ int j;
+ TRACE("Context Substitution Subtable\n");
+ for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
+ {
+ const GSUB_ContextSubstFormat1 *csf1;
+
+ csf1 = (const GSUB_ContextSubstFormat1*)GSUB_get_subtable(look, j);
+ if (GET_BE_WORD(csf1->SubstFormat) == 1)
+ {
+ int offset, index;
+ TRACE("Context Substitution Subtable: Class 1\n");
+ offset = GET_BE_WORD(csf1->Coverage);
+ index = GSUB_is_glyph_covered((const BYTE*)csf1+offset,
glyphs[glyph_index]);
+ TRACE(" Coverage index %i\n",index);
+ if (index != -1)
+ {
+ int k, count;
+ const GSUB_SubRuleSet *srs;
+ offset = GET_BE_WORD(csf1->SubRuleSet[index]);
+ srs = (const GSUB_SubRuleSet*)((const BYTE*)csf1+offset);
+ count = GET_BE_WORD(srs->SubRuleCount);
+ TRACE(" SubRuleSet has %i members\n",count);
+ for (k = 0; k < count; k++)
+ {
+ const GSUB_SubRule_1 *sr;
+ const GSUB_SubRule_2 *sr_2;
+ int g_count, l;
+ int newIndex = glyph_index;
+
+ offset = GET_BE_WORD(srs->SubRule[k]);
+ sr = (const GSUB_SubRule_1*)((const BYTE*)srs+offset);
+ g_count = GET_BE_WORD(sr->GlyphCount);
+ TRACE(" SubRule has %i glyphs\n",g_count);
+ for (l = 0; l < g_count-1; l++)
+ if (glyphs[glyph_index + (write_dir * (l+1))] !=
GET_BE_WORD(sr->Input[l])) break;
+
+ if (l < g_count-1)
+ {
+ TRACE(" Rule does not match\n");
+ continue;
+ }
+
+ TRACE(" Rule matches\n");
+ sr_2 = (const GSUB_SubRule_2*)((const BYTE*)sr+
+ FIELD_OFFSET(GSUB_SubRule_1, Input[g_count-1]));
+
+ for (l = 0; l < GET_BE_WORD(sr->SubstCount); l++)
+ {
+ int lookupIndex =
GET_BE_WORD(sr_2->SubstLookupRecord[l].LookupListIndex);
+ int SequenceIndex =
GET_BE_WORD(sr_2->SubstLookupRecord[l].SequenceIndex) * write_dir;
+
+ TRACE(" SUBST: %i -> %i %i\n",l, SequenceIndex,
lookupIndex);
+ newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs,
glyph_index + SequenceIndex, write_dir, glyph_count);
+ if (newIndex == GSUB_E_NOGLYPH)
+ {
+ ERR(" Chain failed to generate a glyph\n");
+ continue;
+ }
+ }
+ return newIndex;
+ }
+ }
+ }
+ else if (GET_BE_WORD(csf1->SubstFormat) == 2)
+ {
+ const GSUB_ContextSubstFormat2 *csf2;
+ const void *glyph_class_table;
+ int offset, index;
+
+ csf2 = (const GSUB_ContextSubstFormat2*)csf1;
+ TRACE("Context Substitution Subtable: Class 2\n");
+ offset = GET_BE_WORD(csf2->Coverage);
+ index = GSUB_is_glyph_covered((const BYTE*)csf2+offset,
glyphs[glyph_index]);
+ TRACE(" Coverage index %i\n",index);
+ if (index != -1)
+ {
+ int k, count, class;
+ const GSUB_SubClassSet *scs;
+
+ offset = GET_BE_WORD(csf2->ClassDef);
+ glyph_class_table = (const BYTE *)csf2 + offset;
+
+ class = OT_get_glyph_class(glyph_class_table,glyphs[glyph_index]);
+
+ offset = GET_BE_WORD(csf2->SubClassSet[class]);
+ if (offset == 0)
+ {
+ TRACE(" No class rule table for class %i\n",class);
+ continue;
+ }
+ scs = (const GSUB_SubClassSet*)((const BYTE*)csf2+offset);
+ count = GET_BE_WORD(scs->SubClassRuleCnt);
+ TRACE(" SubClassSet has %i members\n",count);
+ for (k = 0; k < count; k++)
+ {
+ const GSUB_SubClassRule_1 *sr;
+ const GSUB_SubClassRule_2 *sr_2;
+ int g_count, l;
+ int newIndex = glyph_index;
+
+ offset = GET_BE_WORD(scs->SubClassRule[k]);
+ sr = (const GSUB_SubClassRule_1*)((const BYTE*)scs+offset);
+ g_count = GET_BE_WORD(sr->GlyphCount);
+ TRACE(" SubClassRule has %i glyphs classes\n",g_count);
+ for (l = 0; l < g_count-1; l++)
+ {
+ int g_class = OT_get_glyph_class(glyph_class_table,
glyphs[glyph_index + (write_dir * (l+1))]);
+ if (g_class != GET_BE_WORD(sr->Class[l])) break;
+ }
+
+ if (l < g_count-1)
+ {
+ TRACE(" Rule does not match\n");
+ continue;
+ }
+
+ TRACE(" Rule matches\n");
+ sr_2 = (const GSUB_SubClassRule_2*)((const BYTE*)sr+
+ FIELD_OFFSET(GSUB_SubClassRule_1, Class[g_count-1]));
+
+ for (l = 0; l < GET_BE_WORD(sr->SubstCount); l++)
+ {
+ int lookupIndex =
GET_BE_WORD(sr_2->SubstLookupRecord[l].LookupListIndex);
+ int SequenceIndex =
GET_BE_WORD(sr_2->SubstLookupRecord[l].SequenceIndex) * write_dir;
+
+ TRACE(" SUBST: %i -> %i %i\n",l, SequenceIndex,
lookupIndex);
+ newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs,
glyph_index + SequenceIndex, write_dir, glyph_count);
+ if (newIndex == GSUB_E_NOGLYPH)
+ {
+ ERR(" Chain failed to generate a glyph\n");
+ continue;
+ }
+ }
+ return newIndex;
+ }
+ }
+ }
+ else
+ FIXME("Unhandled Context Substitution Format %i\n",
GET_BE_WORD(csf1->SubstFormat));
+ }
+ return GSUB_E_NOGLYPH;
+}
+
static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_LookupTable
*look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
{
int j;
@@ -952,10 +1203,122 @@
}
else if (GET_BE_WORD(ccsf1->SubstFormat) == 2)
{
- static int once;
- if (!once++)
- FIXME(" TODO: subtype 2 (Class-based Chaining Context Glyph
Substitution)\n");
- continue;
+ int newIndex = glyph_index;
+ WORD offset, count;
+ const void *backtrack_class_table;
+ const void *input_class_table;
+ const void *lookahead_class_table;
+ int i;
+ WORD class;
+
+ const GSUB_ChainContextSubstFormat2 *ccsf2 = (const
GSUB_ChainContextSubstFormat2*)ccsf1;
+ const GSUB_ChainSubClassSet *csc;
+
+ TRACE(" subtype 2 (Class-based Chaining Context Glyph
Substitution)\n");
+
+ offset = GET_BE_WORD(ccsf2->Coverage);
+
+ if (GSUB_is_glyph_covered((const BYTE*)ccsf2+offset, glyphs[glyph_index]) ==
-1)
+ {
+ TRACE("Glyph not covered\n");
+ continue;
+ }
+ offset = GET_BE_WORD(ccsf2->BacktrackClassDef);
+ backtrack_class_table = (const BYTE*)ccsf2+offset;
+ offset = GET_BE_WORD(ccsf2->InputClassDef);
+ input_class_table = (const BYTE*)ccsf2+offset;
+ offset = GET_BE_WORD(ccsf2->LookaheadClassDef);
+ lookahead_class_table = (const BYTE*)ccsf2+offset;
+ count = GET_BE_WORD(ccsf2->ChainSubClassSetCnt);
+
+ class = OT_get_glyph_class(input_class_table, glyphs[glyph_index]);
+ offset = GET_BE_WORD(ccsf2->ChainSubClassSet[class]);
+
+ if (offset == 0)
+ {
+ TRACE("No rules for class\n");
+ continue;
+ }
+
+ csc = (const GSUB_ChainSubClassSet*)((BYTE*)ccsf2+offset);
+ count = GET_BE_WORD(csc->ChainSubClassRuleCnt);
+
+ TRACE("%i rules to check\n",count);
+
+ for (i = 0; i < count; i++)
+ {
+ int k;
+ int indexGlyphs;
+ const GSUB_ChainSubClassRule_1 *cscr_1;
+ const GSUB_ChainSubClassRule_2 *cscr_2;
+ const GSUB_ChainSubClassRule_3 *cscr_3;
+ const GSUB_ChainSubClassRule_4 *cscr_4;
+
+ offset = GET_BE_WORD(csc->ChainSubClassRule[i]);
+ cscr_1 = (const GSUB_ChainSubClassRule_1*)((BYTE*)csc+offset);
+
+ for (k = 0; k < GET_BE_WORD(cscr_1->BacktrackGlyphCount); k++)
+ {
+ WORD target_class = GET_BE_WORD(cscr_1->Backtrack[k]);
+ WORD glyph_class = OT_get_glyph_class(backtrack_class_table,
glyphs[glyph_index + (dirBacktrack * (k+1))]);
+ if (target_class != glyph_class)
+ break;
+ }
+ if (k != GET_BE_WORD(cscr_1->BacktrackGlyphCount))
+ continue;
+ TRACE("Matched Backtrack\n");
+
+ cscr_2 = (const GSUB_ChainSubClassRule_2*)((BYTE *)cscr_1 +
+ FIELD_OFFSET(GSUB_ChainSubClassRule_1,
Backtrack[GET_BE_WORD(cscr_1->BacktrackGlyphCount)]));
+
+ indexGlyphs = GET_BE_WORD(cscr_2->InputGlyphCount);
+ for (k = 0; k < indexGlyphs - 1; k++)
+ {
+ WORD target_class = GET_BE_WORD(cscr_2->Input[k]);
+ WORD glyph_class = OT_get_glyph_class(input_class_table,
glyphs[glyph_index + (write_dir * (k+1))]);
+ if (target_class != glyph_class)
+ break;
+ }
+ if (k != indexGlyphs-1)
+ continue;
+ TRACE("Matched IndexGlyphs\n");
+
+ cscr_3 = (const GSUB_ChainSubClassRule_3*)((BYTE *)cscr_2 +
+ FIELD_OFFSET(GSUB_ChainSubClassRule_2,
Input[GET_BE_WORD(cscr_2->InputGlyphCount)-1]));
+
+ for (k = 0; k < GET_BE_WORD(cscr_3->LookaheadGlyphCount); k++)
+ {
+ WORD target_class = GET_BE_WORD(cscr_3->LookAhead[k]);
+ WORD glyph_class = OT_get_glyph_class(lookahead_class_table,
glyphs[glyph_index + (dirLookahead * (indexGlyphs+k))]);
+ if (target_class != glyph_class)
+ break;
+ }
+ if (k != GET_BE_WORD(cscr_3->LookaheadGlyphCount))
+ continue;
+ TRACE("Matched LookAhead\n");
+
+ cscr_4 = (const GSUB_ChainSubClassRule_4*)((BYTE *)cscr_3 +
+ FIELD_OFFSET(GSUB_ChainSubClassRule_3,
LookAhead[GET_BE_WORD(cscr_3->LookaheadGlyphCount)]));
+
+ if (GET_BE_WORD(cscr_4->SubstCount))
+ {
+ for (k = 0; k < GET_BE_WORD(cscr_4->SubstCount); k++)
+ {
+ int lookupIndex =
GET_BE_WORD(cscr_4->SubstLookupRecord[k].LookupListIndex);
+ int SequenceIndex =
GET_BE_WORD(cscr_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 == GSUB_E_NOGLYPH)
+ {
+ ERR("Chain failed to generate a glyph\n");
+ continue;
+ }
+ }
+ return newIndex;
+ }
+ else return GSUB_E_NOGLYPH;
+ }
}
else if (GET_BE_WORD(ccsf1->SubstFormat) == 3)
{
@@ -1020,7 +1383,7 @@
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)
+ if (newIndex == GSUB_E_NOGLYPH)
{
ERR("Chain failed to generate a glyph\n");
continue;
@@ -1031,7 +1394,7 @@
else return GSUB_E_NOGLYPH;
}
}
- return -1;
+ return GSUB_E_NOGLYPH;
}
static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs,
INT glyph_index, INT write_dir, INT *glyph_count)
@@ -1074,6 +1437,8 @@
return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir,
glyph_count);
case 4:
return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir,
glyph_count);
+ case 5:
+ return GSUB_apply_ContextSubst(lookup, 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:
@@ -1667,6 +2032,109 @@
return rc;
}
+static INT GPOS_apply_ContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW
lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance,
+ const OT_LookupList *lookup, const OT_LookupTable
*look, const WORD *glyphs, INT glyph_index,
+ INT glyph_count, INT ppem, GOFFSET *pGoffset)
+{
+ int j;
+ int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1;
+
+ TRACE("Contextual Positioning Subtable\n");
+
+ for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
+ {
+ const GPOS_ContextPosFormat2 *cpf2 =
(GPOS_ContextPosFormat2*)GPOS_get_subtable(look, j);
+
+ if (GET_BE_WORD(cpf2->PosFormat) == 1)
+ {
+ static int once;
+ if (!once++)
+ FIXME(" TODO: subtype 1\n");
+ continue;
+ }
+ else if (GET_BE_WORD(cpf2->PosFormat) == 2)
+ {
+ WORD offset = GET_BE_WORD(cpf2->Coverage);
+ int index;
+
+ TRACE("Contextual Positioning Subtable: Format 2\n");
+
+ index = GSUB_is_glyph_covered((const BYTE*)cpf2+offset,
glyphs[glyph_index]);
+ TRACE("Coverage index %i\n",index);
+ if (index != -1)
+ {
+ int k, count, class;
+ const GPOS_PosClassSet *pcs;
+ const void *glyph_class_table = NULL;
+
+ offset = GET_BE_WORD(cpf2->ClassDef);
+ glyph_class_table = (const BYTE *)cpf2 + offset;
+
+ class = OT_get_glyph_class(glyph_class_table,glyphs[glyph_index]);
+
+ offset = GET_BE_WORD(cpf2->PosClassSet[class]);
+ if (offset == 0)
+ {
+ TRACE("No class rule table for class %i\n",class);
+ continue;
+ }
+ pcs = (const GPOS_PosClassSet*)((const BYTE*)cpf2+offset);
+ count = GET_BE_WORD(pcs->PosClassRuleCnt);
+ TRACE("PosClassSet has %i members\n",count);
+ for (k = 0; k < count; k++)
+ {
+ const GPOS_PosClassRule_1 *pr;
+ const GPOS_PosClassRule_2 *pr_2;
+ int g_count, l;
+
+ offset = GET_BE_WORD(pcs->PosClassRule[k]);
+ pr = (const GPOS_PosClassRule_1*)((const BYTE*)pcs+offset);
+ g_count = GET_BE_WORD(pr->GlyphCount);
+ TRACE("PosClassRule has %i glyphs classes\n",g_count);
+ for (l = 0; l < g_count-1; l++)
+ {
+ int g_class = OT_get_glyph_class(glyph_class_table,
glyphs[glyph_index + (write_dir * (l+1))]);
+ if (g_class != GET_BE_WORD(pr->Class[l])) break;
+ }
+
+ if (l < g_count-1)
+ {
+ TRACE("Rule does not match\n");
+ continue;
+ }
+
+ TRACE("Rule matches\n");
+ pr_2 = (const GPOS_PosClassRule_2*)((const BYTE*)pr+
+ FIELD_OFFSET(GPOS_PosClassRule_1, Class[g_count-1]));
+
+ for (l = 0; l < GET_BE_WORD(pr->PosCount); l++)
+ {
+ int lookupIndex =
GET_BE_WORD(pr_2->PosLookupRecord[l].LookupListIndex);
+ int SequenceIndex =
GET_BE_WORD(pr_2->PosLookupRecord[l].SequenceIndex) * write_dir;
+
+ TRACE("Position: %i -> %i %i\n",l, SequenceIndex,
lookupIndex);
+ GPOS_apply_lookup(psc, lpotm, lplogfont, analysis, piAdvance,
lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, glyph_count, pGoffset);
+ }
+ return glyph_index + 1;
+ }
+ }
+
+ TRACE("Not covered\n");
+ continue;
+ }
+ else if (GET_BE_WORD(cpf2->PosFormat) == 3)
+ {
+ static int once;
+ if (!once++)
+ FIXME(" TODO: subtype 3\n");
+ continue;
+ }
+ else
+ FIXME("Unhandled Contextual Positioning Format
%i\n",GET_BE_WORD(cpf2->PosFormat));
+ }
+ return glyph_index + 1;
+}
+
static INT GPOS_apply_ChainContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm,
LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance,
const OT_LookupList *lookup, const OT_LookupTable
*look, const WORD *glyphs, INT glyph_index,
INT glyph_count, INT ppem, GOFFSET *pGoffset)
@@ -1915,6 +2383,8 @@
}
break;
}
+ case 7:
+ return GPOS_apply_ContextPos(psc, lpotm, lplogfont, analysis, piAdvance,
lookup, look, glyphs, glyph_index, glyph_count, ppem, pGoffset);
case 8:
{
return GPOS_apply_ChainContextPos(psc, lpotm, lplogfont, analysis, piAdvance,
lookup, look, glyphs, glyph_index, glyph_count, ppem, pGoffset);
Modified: trunk/reactos/dll/win32/usp10/shape.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/shape.c?re…
==============================================================================
--- trunk/reactos/dll/win32/usp10/shape.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/shape.c [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -1060,6 +1060,8 @@
INT *context_shape;
INT dirR, dirL;
int i;
+ int char_index;
+ int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1103,38 +1105,63 @@
}
/* Contextual Shaping */
- i = 0;
- while(i < *pcGlyphs)
+ if (dirL > 0)
+ char_index = glyph_index = 0;
+ else
+ char_index = glyph_index = cChars-1;
+
+ while(char_index < cChars && char_index >= 0)
{
BOOL shaped = FALSE;
if (psc->GSUB_Table)
{
- INT nextIndex;
+ INT nextIndex, offset = 0;
INT prevCount = *pcGlyphs;
- nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL,
pcGlyphs, contextual_features[context_shape[i]]);
+
+ /* Apply CCMP first */
+ apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL,
pcGlyphs, "ccmp");
+
+ if (prevCount != *pcGlyphs)
+ {
+ offset = *pcGlyphs - prevCount;
+ if (dirL < 0)
+ glyph_index -= offset * dirL;
+ }
+
+ /* Apply the contextual feature */
+ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs,
glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
+
if (nextIndex > GSUB_E_NOGLYPH)
{
- i = nextIndex;
- UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars,
pwLogClust);
+ UpdateClusters(glyph_index, *pcGlyphs - prevCount, dirL, cChars,
pwLogClust);
+ char_index += dirL;
+ if (!offset)
+ glyph_index = nextIndex;
+ else
+ {
+ offset = *pcGlyphs - prevCount;
+ glyph_index += dirL * (offset + 1);
+ }
}
shaped = (nextIndex > GSUB_E_NOGLYPH);
}
if (!shaped)
{
- if (context_shape[i] == Xn)
+ if (context_shape[char_index] == Xn)
{
- WORD newGlyph = pwOutGlyphs[i];
- if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <=
LAST_ARABIC_CHAR)
+ WORD newGlyph = pwOutGlyphs[glyph_index];
+ if (pwcChars[char_index] >= FIRST_ARABIC_CHAR &&
pwcChars[char_index] <= LAST_ARABIC_CHAR)
{
/* fall back to presentation form B */
- WCHAR context_char = wine_shaping_forms[pwcChars[i] -
FIRST_ARABIC_CHAR][context_shape[i]];
- if (context_char != pwcChars[i] && GetGlyphIndicesW(hdc,
&context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000)
- pwOutGlyphs[i] = newGlyph;
+ WCHAR context_char = wine_shaping_forms[pwcChars[char_index] -
FIRST_ARABIC_CHAR][context_shape[char_index]];
+ if (context_char != pwcChars[char_index] &&
GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR &&
newGlyph != 0x0000)
+ pwOutGlyphs[glyph_index] = newGlyph;
}
}
- i++;
+ char_index += dirL;
+ glyph_index += dirL;
}
}
@@ -1281,6 +1308,8 @@
INT *context_shape;
INT dirR, dirL;
int i;
+ int char_index;
+ int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1343,19 +1372,45 @@
}
/* Contextual Shaping */
- i = 0;
- while(i < *pcGlyphs)
- {
- INT nextIndex;
+ if (dirL > 0)
+ char_index = glyph_index = 0;
+ else
+ char_index = glyph_index = cChars-1;
+
+ while(char_index < cChars && char_index >= 0)
+ {
+ INT nextIndex, offset = 0;
INT prevCount = *pcGlyphs;
- nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL,
pcGlyphs, contextual_features[context_shape[i]]);
+
+ /* Apply CCMP first */
+ apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL,
pcGlyphs, "ccmp");
+
+ if (prevCount != *pcGlyphs)
+ {
+ offset = *pcGlyphs - prevCount;
+ if (dirL < 0)
+ glyph_index -= offset * dirL;
+ }
+
+ /* Apply the contextual feature */
+ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index,
dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
- i = nextIndex;
+ char_index += dirL;
+ if (!offset)
+ glyph_index = nextIndex;
+ else
+ {
+ offset = *pcGlyphs - prevCount;
+ glyph_index += dirL * (offset + 1);
+ }
}
else
- i++;
+ {
+ char_index += dirL;
+ glyph_index += dirL;
+ }
}
HeapFree(GetProcessHeap(),0,context_shape);
@@ -1415,6 +1470,8 @@
INT *context_shape;
INT dirR, dirL;
int i;
+ int char_index;
+ int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1463,24 +1520,36 @@
}
/* Contextual Shaping */
- i = 0;
- while(i < *pcGlyphs)
- {
- if (context_shape[i] >= 0)
+ if (dirL > 0)
+ char_index = glyph_index = 0;
+ else
+ char_index = glyph_index = cChars-1;
+
+ while(char_index < cChars && char_index >= 0)
+ {
+ if (context_shape[char_index] >= 0)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
- nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL,
pcGlyphs, contextual_features[context_shape[i]]);
+ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs,
glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
+
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars,
pwLogClust);
- i = nextIndex;
+ glyph_index = nextIndex;
+ char_index += dirL;
}
else
- i++;
+ {
+ char_index += dirL;
+ glyph_index += dirL;
+ }
}
else
- i++;
+ {
+ char_index += dirL;
+ glyph_index += dirL;
+ }
}
HeapFree(GetProcessHeap(),0,context_shape);
@@ -2143,7 +2212,7 @@
switch( type )
{
case 0x0d07: /* Unknown */
- case 0x0e07: /* Unknwon */
+ case 0x0e07: /* Unknown */
default: return lex_Generic;
case 0x0001:
case 0x0002:
@@ -2757,6 +2826,8 @@
INT *context_shape;
INT dirL;
int i;
+ int char_index;
+ int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -2793,19 +2864,28 @@
}
/* Contextual Shaping */
- i = 0;
- while(i < *pcGlyphs)
+ if (dirL > 0)
+ char_index = glyph_index = 0;
+ else
+ char_index = glyph_index = cChars-1;
+
+ while(char_index < cChars && char_index >= 0)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
- nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL,
pcGlyphs, contextual_features[context_shape[i]]);
+ nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index,
dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
+
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
- i = nextIndex;
+ glyph_index = nextIndex;
+ char_index += dirL;
}
else
- i++;
+ {
+ char_index += dirL;
+ glyph_index += dirL;
+ }
}
HeapFree(GetProcessHeap(),0,context_shape);
Modified: trunk/reactos/dll/win32/usp10/usp10.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10.c?re…
==============================================================================
--- trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -1352,7 +1352,7 @@
for (i = 0; i < cInChars; i++)
{
/* Joiners get merged preferencially right */
- if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ))
+ if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ ||
pwcInChars[i] == ZWSP))
{
int j;
if (i+1 == cInChars)
@@ -1361,7 +1361,8 @@
{
for (j = i+1; j < cInChars; j++)
{
- if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ &&
pwcInChars[j] != Numeric_space)
+ if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
+ && pwcInChars[j] != ZWSP && pwcInChars[j] !=
Numeric_space)
{
scripts[i] = scripts[j];
break;
@@ -1486,14 +1487,15 @@
}
/* Joiners get merged preferencially right */
- if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ))
+ if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ ||
pwcInChars[i] == ZWSP))
{
int j;
if (i+1 == cInChars && levels[i-1] == levels[i])
strength[i] = strength[i-1];
else
for (j = i+1; j < cInChars && levels[i] == levels[j];
j++)
- if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
&& pwcInChars[j] != Numeric_space)
+ if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
+ && pwcInChars[j] != ZWSP &&
pwcInChars[j] != Numeric_space)
{
strength[i] = strength[j];
break;
@@ -3112,9 +3114,6 @@
chInput = mirror_char(pwcChars[idx]);
else
chInput = pwcChars[idx];
- /* special case for tabs */
- if (chInput == 0x0009)
- chInput = 0x0020;
rChars[i] = chInput;
}
else
@@ -3154,6 +3153,20 @@
SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars,
pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust);
SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs,
pcGlyphs, cMaxGlyphs, cChars, pwLogClust);
SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs,
*pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps);
+
+ for (i = 0; i < cChars; ++i)
+ {
+ /* Special case for tabs and joiners. As control characters, ZWNJ
+ * and ZWJ would in principle get handled by the corresponding
+ * shaping functions. However, since ZWNJ and ZWJ can get merged
+ * into adjoining runs during itemisation, these don't generally
+ * get classified as Script_Control. */
+ if (pwcChars[i] == 0x0009 || pwcChars[i] == ZWSP || pwcChars[i] == ZWNJ ||
pwcChars[i] == ZWJ)
+ {
+ pwOutGlyphs[pwLogClust[i]] = ((ScriptCache *)*psc)->sfp.wgBlank;
+ pOutGlyphProps[pwLogClust[i]].sva.fZeroWidth = 1;
+ }
+ }
heap_free(rChars);
}
else
@@ -3178,7 +3191,8 @@
pOutGlyphProps[i].sva.fZeroWidth = 1;
}
}
- else if (psa->eScript == Script_Control)
+ else if (psa->eScript == Script_Control || pwcChars[idx] == ZWSP
+ || pwcChars[idx] == ZWNJ || pwcChars[idx] == ZWJ)
{
if (pwcChars[idx] == 0x0009 || pwcChars[idx] == 0x000A ||
pwcChars[idx] == 0x000D || pwcChars[idx] >= 0x001C)
Modified: trunk/reactos/dll/win32/usp10/usp10.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10.spec…
==============================================================================
--- trunk/reactos/dll/win32/usp10/usp10.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/usp10.spec [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -22,7 +22,7 @@
@ stdcall ScriptPlace(ptr ptr ptr long ptr ptr ptr ptr ptr)
@ stdcall ScriptPlaceOpenType(ptr ptr ptr long long ptr ptr long wstr ptr ptr long ptr
ptr long ptr ptr ptr)
@ stub ScriptPositionSingleGlyph
-@ stdcall ScriptRecordDigitSubstitution(ptr ptr)
+@ stdcall ScriptRecordDigitSubstitution(long ptr)
@ stdcall ScriptShape(ptr ptr ptr long long ptr ptr ptr ptr ptr)
@ stdcall ScriptShapeOpenType(ptr ptr ptr long long ptr ptr long wstr long long ptr ptr
ptr ptr ptr)
@ stdcall ScriptStringAnalyse(ptr ptr long long long long long ptr ptr ptr ptr ptr ptr)
Modified: trunk/reactos/dll/win32/usp10/usp10_internal.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10_inte…
==============================================================================
--- trunk/reactos/dll/win32/usp10/usp10_internal.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/usp10_internal.h [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -147,8 +147,8 @@
#define NUM_PAGES 17
-#define GSUB_E_NOFEATURE -2
-#define GSUB_E_NOGLYPH -1
+#define GSUB_E_NOFEATURE -20
+#define GSUB_E_NOGLYPH -10
#define FEATURE_ALL_TABLES 0
#define FEATURE_GSUB_TABLE 1
Modified: trunk/reactos/media/doc/README.WINE
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
==============================================================================
--- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original)
+++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Mar 19 16:53:04 2017
@@ -189,7 +189,7 @@
reactos/dll/win32/updspapi # Synced to WineStaging-1.9.11
reactos/dll/win32/url # Synced to WineStaging-1.9.11
reactos/dll/win32/urlmon # Synced to WineStaging-1.9.23
-reactos/dll/win32/usp10 # Synced to WineStaging-1.9.23
+reactos/dll/win32/usp10 # Synced to WineStaging-2.2
reactos/dll/win32/uxtheme # Forked
reactos/dll/win32/vbscript # Synced to WineStaging-1.9.23
reactos/dll/win32/version # Synced to WineStaging-1.9.11