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?rev... ============================================================================== --- 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?rev... ============================================================================== --- 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_inter... ============================================================================== --- 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=7... ============================================================================== --- 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