[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.

svn path=/trunk/; revision=74193
This commit is contained in:
Amine Khaldi
2017-03-19 16:53:04 +00:00
parent 29e234b3a2
commit e210d0be7d
7 changed files with 617 additions and 53 deletions
+2 -2
View File
@@ -371,7 +371,7 @@ void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT
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 @@ void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT
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 */
+477 -7
View File
@@ -227,6 +227,51 @@ typedef struct{
}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;
@@ -234,6 +279,41 @@ typedef struct{
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 */
WORD BacktrackGlyphCount;
@@ -454,6 +534,29 @@ typedef struct {
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;
WORD BacktrackGlyphCount;
@@ -827,7 +930,10 @@ static INT GSUB_apply_MultipleSubst(const OT_LookupTable *look, WORD *glyphs, IN
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 @@ static INT GSUB_apply_LigatureSubst(const OT_LookupTable *look, WORD *glyphs, IN
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 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo
}
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 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo
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 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo
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 @@ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD
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 @@ static BOOL GPOS_apply_MarkToMark(const OT_LookupTable *look, const SCRIPT_ANALY
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 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG
}
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);
+112 -32
View File
@@ -1060,6 +1060,8 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1103,38 +1105,63 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
}
/* 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 @@ static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1343,19 +1372,45 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
}
/* 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 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 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -1463,24 +1520,36 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
}
/* 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)
{
if (context_shape[i] >= 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 @@ static inline int unicode_lex(WCHAR c)
switch( type )
{
case 0x0d07: /* Unknown */
case 0x0e07: /* Unknwon */
case 0x0e07: /* Unknown */
default: return lex_Generic;
case 0x0001:
case 0x0002:
@@ -2757,6 +2826,8 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
INT *context_shape;
INT dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@@ -2793,19 +2864,28 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
}
/* 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);
+22 -8
View File
@@ -1352,7 +1352,7 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars,
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 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars,
{
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 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars,
}
/* 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 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc,
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 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc,
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 @@ HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc,
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)
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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
+1 -1
View File
@@ -189,7 +189,7 @@ reactos/dll/win32/twain_32 # Synced to WineStaging-1.9.11
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