mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 04:13:31 +00:00
[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:
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user