diff --git a/reactos/dll/win32/usp10/bidi.c b/reactos/dll/win32/usp10/bidi.c index 37b09ba053c..a06ff8c65bd 100644 --- a/reactos/dll/win32/usp10/bidi.c +++ b/reactos/dll/win32/usp10/bidi.c @@ -150,7 +150,7 @@ static inline void dump_types(const char* header, WORD *types, int start, int en } /* Convert the libwine information to the direction enum */ -static void classify(LPCWSTR lpString, WORD *chartype, DWORD uCount, const SCRIPT_CONTROL *c) +static void classify(const WCHAR *string, WORD *chartype, DWORD count, const SCRIPT_CONTROL *c) { static const enum directions dir_map[16] = { @@ -174,14 +174,14 @@ static void classify(LPCWSTR lpString, WORD *chartype, DWORD uCount, const SCRIP unsigned i; - for (i = 0; i < uCount; ++i) + for (i = 0; i < count; ++i) { - chartype[i] = dir_map[get_char_typeW(lpString[i]) >> 12]; + chartype[i] = dir_map[get_char_typeW(string[i]) >> 12]; switch (chartype[i]) { case ES: if (!c->fLegacyBidiClass) break; - switch (lpString[i]) + switch (string[i]) { case '-': case '+': chartype[i] = NI; break; @@ -189,7 +189,7 @@ static void classify(LPCWSTR lpString, WORD *chartype, DWORD uCount, const SCRIP } break; case PDF: - switch (lpString[i]) + switch (string[i]) { case 0x202A: chartype[i] = LRE; break; case 0x202B: chartype[i] = RLE; break; @@ -686,8 +686,8 @@ static BracketPair *computeBracketPairs(IsolatedRun *iso_run) int pair_count = 0; int i; - open_stack = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * iso_run->length); - stack_index = HeapAlloc(GetProcessHeap(), 0, sizeof(int) * iso_run->length); + open_stack = heap_alloc(iso_run->length * sizeof(*open_stack)); + stack_index = heap_alloc(iso_run->length * sizeof(*stack_index)); for (i = 0; i < iso_run->length; i++) { @@ -696,7 +696,7 @@ static BracketPair *computeBracketPairs(IsolatedRun *iso_run) { if (!out) { - out = HeapAlloc(GetProcessHeap(),0,sizeof(BracketPair)); + out = heap_alloc(sizeof(*out)); out[0].start = -1; } @@ -733,14 +733,14 @@ static BracketPair *computeBracketPairs(IsolatedRun *iso_run) } if (pair_count == 0) { - HeapFree(GetProcessHeap(),0,out); + heap_free(out); out = NULL; } else if (pair_count > 1) qsort(out, pair_count, sizeof(BracketPair), compr); - HeapFree(GetProcessHeap(), 0, open_stack); - HeapFree(GetProcessHeap(), 0, stack_index); + heap_free(open_stack); + heap_free(stack_index); return out; } @@ -839,7 +839,7 @@ static void resolveNeutrals(IsolatedRun *iso_run) i++; p = &pairs[i]; } - HeapFree(GetProcessHeap(),0,pairs); + heap_free(pairs); } /* N1 */ @@ -979,15 +979,16 @@ static void resolveResolved(unsigned baselevel, const WORD * pcls, WORD *plevel, } } -static void computeIsolatingRunsSet(unsigned baselevel, WORD *pcls, WORD *pLevel, LPCWSTR lpString, int uCount, struct list *set) +static void computeIsolatingRunsSet(unsigned baselevel, WORD *pcls, const WORD *pLevel, + const WCHAR *string, unsigned int uCount, struct list *set) { int run_start, run_end, i; int run_count = 0; Run *runs; IsolatedRun *current_isolated; - runs = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(Run)); - if (!runs) return; + if (!(runs = heap_alloc(uCount * sizeof(*runs)))) + return; list_init(set); @@ -1014,8 +1015,9 @@ static void computeIsolatingRunsSet(unsigned baselevel, WORD *pcls, WORD *pLevel { int type_fence, real_end; int j; - current_isolated = HeapAlloc(GetProcessHeap(), 0, sizeof(IsolatedRun) + sizeof(RunChar)*uCount); - if (!current_isolated) break; + + if (!(current_isolated = heap_alloc(FIELD_OFFSET(IsolatedRun, item[uCount])))) + break; run_start = runs[k].start; current_isolated->e = runs[k].e; @@ -1024,7 +1026,7 @@ static void computeIsolatingRunsSet(unsigned baselevel, WORD *pcls, WORD *pLevel for (j = 0; j < current_isolated->length; j++) { current_isolated->item[j].pcls = &pcls[runs[k].start+j]; - current_isolated->item[j].ch = lpString[runs[k].start+j]; + current_isolated->item[j].ch = string[runs[k].start + j]; } run_end = runs[k].end; @@ -1054,7 +1056,7 @@ search: for (m = 0; l < current_isolated->length; l++, m++) { current_isolated->item[l].pcls = &pcls[runs[j].start+m]; - current_isolated->item[l].ch = lpString[runs[j].start+m]; + current_isolated->item[l].ch = string[runs[j].start + m]; } TRACE("[%i -- %i]",runs[j].start, runs[j].end); @@ -1110,15 +1112,15 @@ search: i++; } - HeapFree(GetProcessHeap(), 0, runs); + heap_free(runs); } /************************************************************* * BIDI_DeterminLevels */ BOOL BIDI_DetermineLevels( - LPCWSTR lpString, /* [in] The string for which information is to be returned */ - INT uCount, /* [in] Number of WCHARs in string. */ + const WCHAR *lpString, /* [in] The string for which information is to be returned */ + unsigned int uCount, /* [in] Number of WCHARs in string. */ const SCRIPT_STATE *s, const SCRIPT_CONTROL *c, WORD *lpOutLevels, /* [out] final string levels */ @@ -1132,8 +1134,7 @@ BOOL BIDI_DetermineLevels( TRACE("%s, %d\n", debugstr_wn(lpString, uCount), uCount); - chartype = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)); - if (!chartype) + if (!(chartype = heap_alloc(uCount * sizeof(*chartype)))) { WARN("Out of memory\n"); return FALSE; @@ -1166,7 +1167,7 @@ BOOL BIDI_DetermineLevels( if (TRACE_ON(bidi)) iso_dump_types("After Neutrals", iso_run); list_remove(&iso_run->entry); - HeapFree(GetProcessHeap(),0,iso_run); + heap_free(iso_run); } if (TRACE_ON(bidi)) dump_types("Before Implicit", chartype, 0, uCount); @@ -1177,7 +1178,7 @@ BOOL BIDI_DetermineLevels( classify(lpString, chartype, uCount, c); resolveResolved(baselevel, chartype, lpOutLevels, 0, uCount-1); - HeapFree(GetProcessHeap(), 0, chartype); + heap_free(chartype); return TRUE; } @@ -1278,15 +1279,14 @@ int BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, B return ich; } -BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, - WORD* lpStrength) +BOOL BIDI_GetStrengths(const WCHAR *string, unsigned int count, const SCRIPT_CONTROL *c, WORD *strength) { - int i; - classify(lpString, lpStrength, uCount, c); + unsigned int i; - for ( i = 0; i < uCount; i++) + classify(string, strength, count, c); + for (i = 0; i < count; i++) { - switch(lpStrength[i]) + switch (strength[i]) { case L: case LRE: @@ -1295,7 +1295,7 @@ BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, case AL: case RLE: case RLO: - lpStrength[i] = BIDI_STRONG; + strength[i] = BIDI_STRONG; break; case PDF: case EN: @@ -1304,14 +1304,14 @@ BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, case AN: case CS: case BN: - lpStrength[i] = BIDI_WEAK; + strength[i] = BIDI_WEAK; break; case B: case S: case WS: case ON: default: /* Neutrals and NSM */ - lpStrength[i] = BIDI_NEUTRAL; + strength[i] = BIDI_NEUTRAL; } } return TRUE; diff --git a/reactos/dll/win32/usp10/breaking.c b/reactos/dll/win32/usp10/breaking.c index a46b1e3981e..b6e31517443 100644 --- a/reactos/dll/win32/usp10/breaking.c +++ b/reactos/dll/win32/usp10/breaking.c @@ -68,8 +68,8 @@ void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT TRACE("In %s\n",debugstr_wn(chars,count)); - break_class = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); - break_before = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); + break_class = heap_alloc(count * sizeof(*break_class)); + break_before = heap_alloc(count * sizeof(*break_before)); for (i = 0; i < count; i++) { @@ -425,6 +425,6 @@ void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT } } - HeapFree(GetProcessHeap(), 0, break_before); - HeapFree(GetProcessHeap(), 0, break_class); + heap_free(break_before); + heap_free(break_class); } diff --git a/reactos/dll/win32/usp10/indic.c b/reactos/dll/win32/usp10/indic.c index 380a6358ee1..fae5f43c61e 100644 --- a/reactos/dll/win32/usp10/indic.c +++ b/reactos/dll/win32/usp10/indic.c @@ -23,12 +23,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); -static void debug_output_string(LPCWSTR str, int cChar, lexical_function f) +static void debug_output_string(const WCHAR *str, unsigned int char_count, lexical_function f) { int i; if (TRACE_ON(uniscribe)) { - for (i = 0; i < cChar; i++) + for (i = 0; i < char_count; ++i) { switch (f(str[i])) { @@ -67,8 +67,8 @@ static inline BOOL is_joiner( int type ) return (type == lex_ZWJ || type == lex_ZWNJ); } -static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next, - lexical_function lex) +static int consonant_header(const WCHAR *input, unsigned int cChar, + unsigned int start, unsigned int next, lexical_function lex) { if (!is_consonant( lex(input[next]) )) return -1; next++; @@ -91,8 +91,8 @@ static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next, return -1; } -static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start, - INT *main, INT next, lexical_function lex) +static int parse_consonant_syllable(const WCHAR *input, unsigned int cChar, + unsigned int start, unsigned int *main, unsigned int next, lexical_function lex) { int check; int headers = 0; @@ -139,8 +139,8 @@ static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start, return next; } -static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start, - INT next, lexical_function lex) +static int parse_vowel_syllable(const WCHAR *input, unsigned int cChar, + unsigned int start, unsigned int next, lexical_function lex) { if ((next < cChar) && lex(input[next]) == lex_Nukta) next++; @@ -168,7 +168,8 @@ static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start, return next; } -static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT* main, INT next, lexical_function lex ) +static int Indic_process_next_syllable(const WCHAR *input, unsigned int cChar, + unsigned int start, unsigned int *main, unsigned int next, lexical_function lex) { if (lex(input[next])==lex_Vowel) { @@ -195,7 +196,8 @@ static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT return parse_consonant_syllable(input, cChar, start, main, next, lex); } -static BOOL Consonant_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +static BOOL Consonant_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, + const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern) { if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) { @@ -212,7 +214,8 @@ static BOOL Consonant_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCac return FALSE; } -static BOOL Consonant_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +static BOOL Consonant_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, + const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern) { if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) { @@ -229,7 +232,8 @@ static BOOL Consonant_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCa return FALSE; } -static BOOL Consonant_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +static BOOL Consonant_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, + const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical, BOOL modern) { if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) { @@ -246,14 +250,16 @@ static BOOL Consonant_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCach return FALSE; } -static BOOL Consonant_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static BOOL Consonant_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, + const WCHAR *pwChar, const IndicSyllable *s, lexical_function lexical) { if ((lexical(pwChar[s->start])==lex_Ra) && s->end > s->start && lexical(pwChar[s->start+1]) == lex_Halant) return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->start], 1, 2, "rphf") > 0); return FALSE; } -static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, IndicSyllable *s, lexical_function lex, BOOL modern) +static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, + const WCHAR *input, IndicSyllable *s, lexical_function lex, BOOL modern) { int i; BOOL blwf = FALSE; @@ -301,11 +307,12 @@ static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LP return s->base; } -void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) +void Indic_ParseSyllables(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const WCHAR *input, unsigned int cChar, + IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) { + unsigned int center = 0; int index = 0; int next = 0; - int center = 0; *syllable_count = 0; @@ -329,7 +336,7 @@ void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCW if (*syllable_count) *syllables = HeapReAlloc(GetProcessHeap(),0,*syllables, sizeof(IndicSyllable)*(*syllable_count+1)); else - *syllables = HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable)); + *syllables = heap_alloc(sizeof(**syllables)); (*syllables)[*syllable_count].start = index; (*syllables)[*syllable_count].base = center; (*syllables)[*syllable_count].ralf = -1; @@ -349,7 +356,8 @@ void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCW TRACE("Processed %i of %i characters into %i syllables\n",index,cChar,*syllable_count); } -void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern) +void Indic_ReorderCharacters(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, WCHAR *input, unsigned int cChar, + IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern) { int i; diff --git a/reactos/dll/win32/usp10/opentype.c b/reactos/dll/win32/usp10/opentype.c index b8368031ed4..018813d9ef0 100644 --- a/reactos/dll/win32/usp10/opentype.c +++ b/reactos/dll/win32/usp10/opentype.c @@ -38,6 +38,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); /* These are all structures needed for the cmap format 12 table */ #define CMAP_TAG MS_MAKE_TAG('c', 'm', 'a', 'p') +enum gpos_lookup_type +{ + GPOS_LOOKUP_ADJUST_SINGLE = 0x1, + GPOS_LOOKUP_ADJUST_PAIR = 0x2, + GPOS_LOOKUP_ATTACH_CURSIVE = 0x3, + GPOS_LOOKUP_ATTACH_MARK_TO_BASE = 0x4, + GPOS_LOOKUP_ATTACH_MARK_TO_LIGATURE = 0x5, + GPOS_LOOKUP_ATTACH_MARK_TO_MARK = 0x6, + GPOS_LOOKUP_POSITION_CONTEXT = 0x7, + GPOS_LOOKUP_POSITION_CONTEXT_CHAINED = 0x8, + GPOS_LOOKUP_POSITION_EXTENSION = 0x9, +}; + +enum gsub_lookup_type +{ + GSUB_LOOKUP_SINGLE = 0x1, + GSUB_LOOKUP_MULTIPLE = 0x2, + GSUB_LOOKUP_ALTERNATE = 0x3, + GSUB_LOOKUP_LIGATURE = 0x4, + GSUB_LOOKUP_CONTEXT = 0x5, + GSUB_LOOKUP_CONTEXT_CHAINED = 0x6, + GSUB_LOOKUP_EXTENSION = 0x7, + GSUB_LOOKUP_CONTEXT_CHAINED_REVERSE = 0x8, +}; + typedef struct { WORD platformID; WORD encodingID; @@ -599,7 +624,7 @@ static VOID *load_CMAP_format12_table(HDC hdc, ScriptCache *psc) length = GetFontData(hdc, CMAP_TAG , 0, NULL, 0); if (length != GDI_ERROR) { - psc->CMAP_Table = HeapAlloc(GetProcessHeap(),0,length); + psc->CMAP_Table = heap_alloc(length); GetFontData(hdc, CMAP_TAG , 0, psc->CMAP_Table, length); TRACE("Loaded cmap table of %i bytes\n",length); } @@ -634,22 +659,22 @@ static int compare_group(const void *a, const void* b) return 0; } -DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) +DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, WORD *glyph_index, DWORD flags) { /* BMP: use gdi32 for ease */ if (utf32c < 0x10000) { WCHAR ch = utf32c; - return GetGlyphIndicesW(hdc,&ch, 1, pgi, flags); + return GetGlyphIndicesW(hdc, &ch, 1, glyph_index, flags); } if (!psc->CMAP_format12_Table) psc->CMAP_format12_Table = load_CMAP_format12_table(hdc, psc); if (flags & GGI_MARK_NONEXISTING_GLYPHS) - *pgi = 0xffff; + *glyph_index = 0xffffu; else - *pgi = 0; + *glyph_index = 0u; if (psc->CMAP_format12_Table) { @@ -664,7 +689,7 @@ DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWOR if (group) { DWORD offset = utf32c - GET_BE_DWORD(group->startCharCode); - *pgi = GET_BE_DWORD(group->startGlyphID) + offset; + *glyph_index = GET_BE_DWORD(group->startGlyphID) + offset; return 0; } } @@ -780,7 +805,7 @@ void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, cons **********/ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count); -static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) +static int GSUB_is_glyph_covered(const void *table, unsigned int glyph) { const OT_CoverageFormat1* cf1; @@ -828,7 +853,7 @@ static const BYTE *GSUB_get_subtable(const OT_LookupTable *look, int index) { int offset = GET_BE_WORD(look->SubTable[index]); - if (GET_BE_WORD(look->LookupType) == 7) + if (GET_BE_WORD(look->LookupType) == GSUB_LOOKUP_EXTENSION) { const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)look + offset); if (GET_BE_WORD(ext->SubstFormat) == 1) @@ -1023,9 +1048,8 @@ static INT GSUB_apply_LigatureSubst(const OT_LookupTable *look, WORD *glyphs, IN TRACE("0x%x\n",glyphs[replaceIdx]); if (CompCount > 0) { - int j; - for (j = replaceIdx + 1; j < *glyph_count; j++) - glyphs[j] =glyphs[j+CompCount]; + unsigned int j = replaceIdx + 1; + memmove(&glyphs[j], &glyphs[j + CompCount], (*glyph_count - j) * sizeof(*glyphs)); *glyph_count = *glyph_count - CompCount; } return replaceIdx + write_dir; @@ -1064,6 +1088,7 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT { const GSUB_SubRule_1 *sr; const GSUB_SubRule_2 *sr_2; + unsigned int g; int g_count, l; int newIndex = glyph_index; @@ -1071,6 +1096,11 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT sr = (const GSUB_SubRule_1*)((const BYTE*)srs+offset); g_count = GET_BE_WORD(sr->GlyphCount); TRACE(" SubRule has %i glyphs\n",g_count); + + g = glyph_index + write_dir * (g_count - 1); + if (g >= *glyph_count) + continue; + for (l = 0; l < g_count-1; l++) if (glyphs[glyph_index + (write_dir * (l+1))] != GET_BE_WORD(sr->Input[l])) break; @@ -1081,16 +1111,23 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT } TRACE(" Rule matches\n"); - sr_2 = (const GSUB_SubRule_2*)((const BYTE*)sr+ - FIELD_OFFSET(GSUB_SubRule_1, Input[g_count-1])); + sr_2 = (const GSUB_SubRule_2 *)&sr->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; + unsigned int lookup_index = GET_BE_WORD(sr_2->SubstLookupRecord[l].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(sr_2->SubstLookupRecord[l].SequenceIndex); - TRACE(" SUBST: %i -> %i %i\n",l, SequenceIndex, lookupIndex); - newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count); + g = glyph_index + write_dir * sequence_index; + if (g >= *glyph_count) + { + WARN("Invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; + } + + TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); + newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1135,6 +1172,7 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT { const GSUB_SubClassRule_1 *sr; const GSUB_SubClassRule_2 *sr_2; + unsigned int g; int g_count, l; int newIndex = glyph_index; @@ -1142,6 +1180,11 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT 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); + + g = glyph_index + write_dir * (g_count - 1); + if (g >= *glyph_count) + continue; + 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))]); @@ -1155,16 +1198,23 @@ static INT GSUB_apply_ContextSubst(const OT_LookupList* lookup, const OT_LookupT } TRACE(" Rule matches\n"); - sr_2 = (const GSUB_SubClassRule_2*)((const BYTE*)sr+ - FIELD_OFFSET(GSUB_SubClassRule_1, Class[g_count-1])); + sr_2 = (const GSUB_SubClassRule_2 *)&sr->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; + unsigned int lookup_index = GET_BE_WORD(sr_2->SubstLookupRecord[l].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(sr_2->SubstLookupRecord[l].SequenceIndex); - TRACE(" SUBST: %i -> %i %i\n",l, SequenceIndex, lookupIndex); - newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count); + g = glyph_index + write_dir * sequence_index; + if (g >= *glyph_count) + { + WARN("Invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; + } + + TRACE(" SUBST: %u -> %u %u.\n", l, sequence_index, lookup_index); + newIndex = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); if (newIndex == GSUB_E_NOGLYPH) { ERR(" Chain failed to generate a glyph\n"); @@ -1203,7 +1253,6 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo } else if (GET_BE_WORD(ccsf1->SubstFormat) == 2) { - int newIndex = glyph_index; WORD offset, count; const void *backtrack_class_table; const void *input_class_table; @@ -1247,151 +1296,176 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo for (i = 0; i < count; i++) { + WORD backtrack_count, input_count, lookahead_count, substitute_count; 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; + const GSUB_ChainSubClassRule_1 *backtrack; + const GSUB_ChainSubClassRule_2 *input; + const GSUB_ChainSubClassRule_3 *lookahead; + const GSUB_ChainSubClassRule_4 *substitute; + int new_index = GSUB_E_NOGLYPH; offset = GET_BE_WORD(csc->ChainSubClassRule[i]); - cscr_1 = (const GSUB_ChainSubClassRule_1*)((BYTE*)csc+offset); + backtrack = (const GSUB_ChainSubClassRule_1 *)((BYTE *)csc + offset); + backtrack_count = GET_BE_WORD(backtrack->BacktrackGlyphCount); + k = glyph_index + dirBacktrack * backtrack_count; + if (k < 0 || k >= *glyph_count) + continue; - for (k = 0; k < GET_BE_WORD(cscr_1->BacktrackGlyphCount); k++) + input = (const GSUB_ChainSubClassRule_2 *)&backtrack->Backtrack[backtrack_count]; + input_count = GET_BE_WORD(input->InputGlyphCount) - 1; + k = glyph_index + write_dir * input_count; + if (k < 0 || k >= *glyph_count) + continue; + + lookahead = (const GSUB_ChainSubClassRule_3 *)&input->Input[input_count]; + lookahead_count = GET_BE_WORD(lookahead->LookaheadGlyphCount); + k = glyph_index + dirLookahead * (input_count + lookahead_count); + if (k < 0 || k >= *glyph_count) + continue; + + substitute = (const GSUB_ChainSubClassRule_4 *)&lookahead->LookAhead[lookahead_count]; + + for (k = 0; k < backtrack_count; ++k) { - WORD target_class = GET_BE_WORD(cscr_1->Backtrack[k]); + WORD target_class = GET_BE_WORD(backtrack->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)) + if (k != backtrack_count) 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++) + for (k = 0; k < input_count; ++k) { - WORD target_class = GET_BE_WORD(cscr_2->Input[k]); + WORD target_class = GET_BE_WORD(input->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) + if (k != input_count) 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++) + for (k = 0; k < lookahead_count; ++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))]); + WORD target_class = GET_BE_WORD(lookahead->LookAhead[k]); + WORD glyph_class = OT_get_glyph_class(lookahead_class_table, + glyphs[glyph_index + (dirLookahead * (input_count + k + 1))]); if (target_class != glyph_class) break; } - if (k != GET_BE_WORD(cscr_3->LookaheadGlyphCount)) + if (k != lookahead_count) 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)) + substitute_count = GET_BE_WORD(substitute->SubstCount); + for (k = 0; k < substitute_count; ++k) { - 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; + unsigned int lookup_index = GET_BE_WORD(substitute->SubstLookupRecord[k].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(substitute->SubstLookupRecord[k].SequenceIndex); + unsigned int g = glyph_index + write_dir * sequence_index; - 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; - } + if (g >= *glyph_count) + { + WARN("Skipping invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; } - return newIndex; + + TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); + new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + if (new_index == GSUB_E_NOGLYPH) + ERR("Chain failed to generate a glyph.\n"); } - else return GSUB_E_NOGLYPH; + return new_index; } } else if (GET_BE_WORD(ccsf1->SubstFormat) == 3) { + WORD backtrack_count, input_count, lookahead_count, substitution_count; int k; - int indexGlyphs; - const GSUB_ChainContextSubstFormat3_1 *ccsf3_1; - const GSUB_ChainContextSubstFormat3_2 *ccsf3_2; - const GSUB_ChainContextSubstFormat3_3 *ccsf3_3; - const GSUB_ChainContextSubstFormat3_4 *ccsf3_4; - int newIndex = glyph_index; - - ccsf3_1 = (const GSUB_ChainContextSubstFormat3_1 *)ccsf1; + const GSUB_ChainContextSubstFormat3_1 *backtrack; + const GSUB_ChainContextSubstFormat3_2 *input; + const GSUB_ChainContextSubstFormat3_3 *lookahead; + const GSUB_ChainContextSubstFormat3_4 *substitute; + int new_index = GSUB_E_NOGLYPH; TRACE(" subtype 3 (Coverage-based Chaining Context Glyph Substitution)\n"); - for (k = 0; k < GET_BE_WORD(ccsf3_1->BacktrackGlyphCount); k++) + backtrack = (const GSUB_ChainContextSubstFormat3_1 *)ccsf1; + backtrack_count = GET_BE_WORD(backtrack->BacktrackGlyphCount); + k = glyph_index + dirBacktrack * backtrack_count; + if (k < 0 || k >= *glyph_count) + continue; + + input = (const GSUB_ChainContextSubstFormat3_2 *)&backtrack->Coverage[backtrack_count]; + input_count = GET_BE_WORD(input->InputGlyphCount); + k = glyph_index + write_dir * (input_count - 1); + if (k < 0 || k >= *glyph_count) + continue; + + lookahead = (const GSUB_ChainContextSubstFormat3_3 *)&input->Coverage[input_count]; + lookahead_count = GET_BE_WORD(lookahead->LookaheadGlyphCount); + k = glyph_index + dirLookahead * (input_count + lookahead_count - 1); + if (k < 0 || k >= *glyph_count) + continue; + + substitute = (const GSUB_ChainContextSubstFormat3_4 *)&lookahead->Coverage[lookahead_count]; + + for (k = 0; k < backtrack_count; ++k) { - offset = GET_BE_WORD(ccsf3_1->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirBacktrack * (k+1))]) == -1) + offset = GET_BE_WORD(backtrack->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)ccsf1 + offset, + glyphs[glyph_index + (dirBacktrack * (k + 1))]) == -1) break; } - if (k != GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)) + if (k != backtrack_count) continue; TRACE("Matched Backtrack\n"); - ccsf3_2 = (const GSUB_ChainContextSubstFormat3_2 *)((BYTE *)ccsf1 + - FIELD_OFFSET(GSUB_ChainContextSubstFormat3_1, Coverage[GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)])); - - indexGlyphs = GET_BE_WORD(ccsf3_2->InputGlyphCount); - for (k = 0; k < indexGlyphs; k++) + for (k = 0; k < input_count; ++k) { - offset = GET_BE_WORD(ccsf3_2->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (write_dir * k)]) == -1) + offset = GET_BE_WORD(input->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)ccsf1 + offset, + glyphs[glyph_index + (write_dir * k)]) == -1) break; } - if (k != indexGlyphs) + if (k != input_count) continue; TRACE("Matched IndexGlyphs\n"); - ccsf3_3 = (const GSUB_ChainContextSubstFormat3_3 *)((BYTE *)ccsf3_2 + - FIELD_OFFSET(GSUB_ChainContextSubstFormat3_2, Coverage[GET_BE_WORD(ccsf3_2->InputGlyphCount)])); - - for (k = 0; k < GET_BE_WORD(ccsf3_3->LookaheadGlyphCount); k++) + for (k = 0; k < lookahead_count; ++k) { - offset = GET_BE_WORD(ccsf3_3->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k))]) == -1) + offset = GET_BE_WORD(lookahead->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)ccsf1 + offset, + glyphs[glyph_index + (dirLookahead * (input_count + k))]) == -1) break; } - if (k != GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)) + if (k != lookahead_count) continue; TRACE("Matched LookAhead\n"); - ccsf3_4 = (const GSUB_ChainContextSubstFormat3_4 *)((BYTE *)ccsf3_3 + - FIELD_OFFSET(GSUB_ChainContextSubstFormat3_3, Coverage[GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)])); - - if (GET_BE_WORD(ccsf3_4->SubstCount)) + substitution_count = GET_BE_WORD(substitute->SubstCount); + for (k = 0; k < substitution_count; ++k) { - for (k = 0; k < GET_BE_WORD(ccsf3_4->SubstCount); k++) - { - int lookupIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].LookupListIndex); - int SequenceIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].SequenceIndex) * write_dir; + unsigned int lookup_index = GET_BE_WORD(substitute->SubstLookupRecord[k].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(substitute->SubstLookupRecord[k].SequenceIndex); + unsigned int g = glyph_index + write_dir * sequence_index; - 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; - } + if (g >= *glyph_count) + { + WARN("Skipping invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; } - return newIndex; + + TRACE("SUBST: %u -> %u %u.\n", k, sequence_index, lookup_index); + new_index = GSUB_apply_lookup(lookup, lookup_index, glyphs, g, write_dir, glyph_count); + if (new_index == GSUB_E_NOGLYPH) + ERR("Chain failed to generate a glyph.\n"); } - else return GSUB_E_NOGLYPH; + return new_index; } } return GSUB_E_NOGLYPH; @@ -1400,14 +1474,16 @@ static INT GSUB_apply_ChainContextSubst(const OT_LookupList* lookup, const OT_Lo static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) { int offset; - int type; + enum gsub_lookup_type type; const OT_LookupTable *look; offset = GET_BE_WORD(lookup->Lookup[lookup_index]); look = (const OT_LookupTable*)((const BYTE*)lookup + offset); type = GET_BE_WORD(look->LookupType); - TRACE("type %i, flag %x, subtables %i\n",type,GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount)); - if (type == 7) + TRACE("type %#x, flag %#x, subtables %u.\n", type, + GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount)); + + if (type == GSUB_LOOKUP_EXTENSION) { if (GET_BE_WORD(look->SubTableCount)) { @@ -1429,28 +1505,29 @@ static INT GSUB_apply_lookup(const OT_LookupList* lookup, INT lookup_index, WORD } switch(type) { - case 1: + case GSUB_LOOKUP_SINGLE: return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count); - case 2: + case GSUB_LOOKUP_MULTIPLE: return GSUB_apply_MultipleSubst(look, glyphs, glyph_index, write_dir, glyph_count); - case 3: + case GSUB_LOOKUP_ALTERNATE: return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir, glyph_count); - case 4: + case GSUB_LOOKUP_LIGATURE: return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir, glyph_count); - case 5: + case GSUB_LOOKUP_CONTEXT: return GSUB_apply_ContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count); - case 6: + case GSUB_LOOKUP_CONTEXT_CHAINED: return GSUB_apply_ChainContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count); - case 7: + case GSUB_LOOKUP_EXTENSION: FIXME("Extension Substitution types not valid here\n"); break; default: - FIXME("We do not handle SubType %i\n",type); + FIXME("Unhandled GSUB lookup type %#x.\n", type); } return GSUB_E_NOGLYPH; } -INT OpenType_apply_GSUB_lookup(LPCVOID table, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +int OpenType_apply_GSUB_lookup(const void *table, unsigned int lookup_index, WORD *glyphs, + unsigned int glyph_index, int write_dir, int *glyph_count) { const GSUB_Header *header = (const GSUB_Header *)table; const OT_LookupList *lookup = (const OT_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList)); @@ -1461,18 +1538,28 @@ INT OpenType_apply_GSUB_lookup(LPCVOID table, INT lookup_index, WORD *glyphs, IN /********** * GPOS **********/ -static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, - const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset); +static unsigned int GPOS_apply_lookup(const ScriptCache *script_cache, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, const OT_LookupList *lookup, + unsigned int lookup_index, const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, + GOFFSET *goffset); static INT GPOS_get_device_table_value(const OT_DeviceTable *DeviceTable, WORD ppem) { static const WORD mask[3] = {3,0xf,0xff}; if (DeviceTable && ppem >= GET_BE_WORD(DeviceTable->StartSize) && ppem <= GET_BE_WORD(DeviceTable->EndSize)) { - int format = GET_BE_WORD(DeviceTable->DeltaFormat); + WORD format = GET_BE_WORD(DeviceTable->DeltaFormat); int index = ppem - GET_BE_WORD(DeviceTable->StartSize); int value; - TRACE("device table, format %i, index %i\n",format, index); + + TRACE("device table, format %#x, index %i\n", format, index); + + if (format < 1 || format > 3) + { + WARN("invalid delta format %#x\n", format); + return 0; + } + index = index << format; value = (DeviceTable->DeltaValue[index/sizeof(WORD)] << (index%sizeof(WORD)))&mask[format-1]; TRACE("offset %i, value %i\n",index, value); @@ -1483,7 +1570,7 @@ static INT GPOS_get_device_table_value(const OT_DeviceTable *DeviceTable, WORD p return 0; } -static VOID GPOS_get_anchor_values(LPCVOID table, LPPOINT pt, WORD ppem) +static void GPOS_get_anchor_values(const void *table, POINT *pt, WORD ppem) { const GPOS_AnchorFormat1* anchor1 = (const GPOS_AnchorFormat1*)table; @@ -1535,15 +1622,16 @@ static VOID GPOS_get_anchor_values(LPCVOID table, LPPOINT pt, WORD ppem) } } -static void GPOS_convert_design_units_to_device(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, int desX, int desY, double *devX, double *devY) +static void GPOS_convert_design_units_to_device(const OUTLINETEXTMETRICW *otm, const LOGFONTW *logfont, + int desX, int desY, double *devX, double *devY) { - int emHeight = lpotm->otmTextMetrics.tmAscent + lpotm->otmTextMetrics.tmDescent - lpotm->otmTextMetrics.tmInternalLeading; + int emHeight = otm->otmTextMetrics.tmAscent + otm->otmTextMetrics.tmDescent - otm->otmTextMetrics.tmInternalLeading; - TRACE("emHeight %i lfWidth %i\n",emHeight, lplogfont->lfWidth); - *devX = (desX * emHeight) / (double)lpotm->otmEMSquare; - *devY = (desY * emHeight) / (double)lpotm->otmEMSquare; - if (lplogfont->lfWidth) - FIXME("Font with lfWidth set not handled properly\n"); + TRACE("emHeight %i lfWidth %i\n",emHeight, logfont->lfWidth); + *devX = (desX * emHeight) / (double)otm->otmEMSquare; + *devY = (desY * emHeight) / (double)otm->otmEMSquare; + if (logfont->lfWidth) + FIXME("Font with lfWidth set not handled properly.\n"); } static INT GPOS_get_value_record(WORD ValueFormat, const WORD data[], GPOS_ValueRecord *record) @@ -1560,7 +1648,8 @@ static INT GPOS_get_value_record(WORD ValueFormat, const WORD data[], GPOS_Value return offset; } -static VOID GPOS_get_value_record_offsets(const BYTE* head, GPOS_ValueRecord *ValueRecord, WORD ValueFormat, INT ppem, LPPOINT ptPlacement, LPPOINT ptAdvance) +static void GPOS_get_value_record_offsets(const BYTE *head, GPOS_ValueRecord *ValueRecord, + WORD ValueFormat, unsigned int ppem, POINT *ptPlacement, POINT *ptAdvance) { if (ValueFormat & 0x0001) ptPlacement->x += (short)ValueRecord->XPlacement; if (ValueFormat & 0x0002) ptPlacement->y += (short)ValueRecord->YPlacement; @@ -1577,7 +1666,7 @@ static const BYTE *GPOS_get_subtable(const OT_LookupTable *look, int index) { int offset = GET_BE_WORD(look->SubTable[index]); - if (GET_BE_WORD(look->LookupType) == 9) + if (GET_BE_WORD(look->LookupType) == GPOS_LOOKUP_POSITION_EXTENSION) { const GPOS_ExtensionPosFormat1 *ext = (const GPOS_ExtensionPosFormat1 *)((const BYTE *)look + offset); if (GET_BE_WORD(ext->PosFormat) == 1) @@ -1592,8 +1681,9 @@ static const BYTE *GPOS_get_subtable(const OT_LookupTable *look, int index) return (const BYTE *)look + offset; } -static VOID GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, - INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) +static void GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, unsigned int ppem, + POINT *adjust, POINT *advance) { int j; @@ -1611,7 +1701,7 @@ static VOID GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const SCRIPT GPOS_ValueRecord ValueRecord = {0,0,0,0,0,0,0,0}; WORD ValueFormat = GET_BE_WORD(spf1->ValueFormat); GPOS_get_value_record(ValueFormat, spf1->Value, &ValueRecord); - GPOS_get_value_record_offsets((const BYTE*)spf1, &ValueRecord, ValueFormat, ppem, ptAdjust, ptAdvance); + GPOS_get_value_record_offsets((const BYTE *)spf1, &ValueRecord, ValueFormat, ppem, adjust, advance); TRACE("Glyph Adjusted by %i,%i\n",ValueRecord.XPlacement,ValueRecord.YPlacement); } } @@ -1633,7 +1723,7 @@ static VOID GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const SCRIPT offset = size * index; GPOS_get_value_record(ValueFormat, &spf2->Value[offset], &ValueRecord); } - GPOS_get_value_record_offsets((const BYTE*)spf2, &ValueRecord, ValueFormat, ppem, ptAdjust, ptAdvance); + GPOS_get_value_record_offsets((const BYTE *)spf2, &ValueRecord, ValueFormat, ppem, adjust, advance); TRACE("Glyph Adjusted by %i,%i\n",ValueRecord.XPlacement,ValueRecord.YPlacement); } } @@ -1666,13 +1756,15 @@ static void apply_pair_value( const void *pos_table, WORD val_fmt1, WORD val_fmt } } -static INT GPOS_apply_PairAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, - INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) +static int GPOS_apply_PairAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, unsigned int ppem, + POINT *adjust, POINT *advance) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; - if (glyph_index + write_dir < 0 || glyph_index + write_dir >= glyph_count) return glyph_index + 1; + if (glyph_index + write_dir >= glyph_count) + return 1; TRACE("Pair Adjustment Positioning Subtable\n"); @@ -1706,9 +1798,10 @@ static INT GPOS_apply_PairAdjustment(const OT_LookupTable *look, const SCRIPT_AN { int next = 1; TRACE("Format 1: Found Pair %x,%x\n",glyphs[glyph_index],glyphs[glyph_index+write_dir]); - apply_pair_value( ppf1, ValueFormat1, ValueFormat2, pair_val_rec->Value1, ppem, ptAdjust, ptAdvance ); + apply_pair_value(ppf1, ValueFormat1, ValueFormat2, + pair_val_rec->Value1, ppem, adjust, advance); if (ValueFormat2) next++; - return glyph_index + next; + return next; } pair_val_rec = (const GPOS_PairValueRecord *)(pair_val_rec->Value1 + val_fmt1_size + val_fmt2_size); } @@ -1739,25 +1832,26 @@ static INT GPOS_apply_PairAdjustment(const OT_LookupTable *look, const SCRIPT_AN TRACE( "Format 2: Found Pair %x,%x\n", glyphs[glyph_index], glyphs[glyph_index + write_dir] ); - apply_pair_value( ppf2, ValueFormat1, ValueFormat2, pair_val, ppem, ptAdjust, ptAdvance ); + apply_pair_value(ppf2, ValueFormat1, ValueFormat2, pair_val, ppem, adjust, advance); if (ValueFormat2) next++; - return glyph_index + next; + return next; } } } else FIXME("Pair Adjustment Positioning: Format %i Unhandled\n",GET_BE_WORD(ppf1->PosFormat)); } - return glyph_index+1; + return 1; } -static VOID GPOS_apply_CursiveAttachment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, - INT glyph_count, INT ppem, LPPOINT pt) +static void GPOS_apply_CursiveAttachment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, unsigned int ppem, POINT *pt) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; - if (glyph_index + write_dir < 0 || glyph_index + write_dir >= glyph_count) return; + if (glyph_index + write_dir >= glyph_count) + return; TRACE("Cursive Attachment Positioning Subtable\n"); @@ -1792,19 +1886,21 @@ static VOID GPOS_apply_CursiveAttachment(const OT_LookupTable *look, const SCRIP return; } -static int GPOS_apply_MarkToBase(ScriptCache *psc, const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, INT glyph_count, INT ppem, LPPOINT pt) +static int GPOS_apply_MarkToBase(const ScriptCache *script_cache, const OT_LookupTable *look, + const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, unsigned int glyph_index, + unsigned int glyph_count, unsigned int ppem, POINT *pt) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; - void *glyph_class_table = NULL; + const void *glyph_class_table = NULL; int rc = -1; - if (psc->GDEF_Table) + if (script_cache->GDEF_Table) { - const GDEF_Header *header = psc->GDEF_Table; + const GDEF_Header *header = script_cache->GDEF_Table; WORD offset = GET_BE_WORD( header->GlyphClassDef ); if (offset) - glyph_class_table = (BYTE *)psc->GDEF_Table + offset; + glyph_class_table = (const BYTE *)script_cache->GDEF_Table + offset; } TRACE("MarkToBase Attachment Positioning Subtable\n"); @@ -1875,8 +1971,8 @@ static int GPOS_apply_MarkToBase(ScriptCache *psc, const OT_LookupTable *look, c return rc; } -static VOID GPOS_apply_MarkToLigature(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, - INT glyph_count, INT ppem, LPPOINT pt) +static void GPOS_apply_MarkToLigature(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, unsigned int ppem, POINT *pt) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; @@ -1965,8 +2061,8 @@ static VOID GPOS_apply_MarkToLigature(const OT_LookupTable *look, const SCRIPT_A } } -static BOOL GPOS_apply_MarkToMark(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, - INT glyph_count, INT ppem, LPPOINT pt) +static BOOL GPOS_apply_MarkToMark(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, unsigned int ppem, POINT *pt) { int j; BOOL rc = FALSE; @@ -2032,9 +2128,10 @@ 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) +static unsigned int GPOS_apply_ContextPos(const ScriptCache *script_cache, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, const OT_LookupList *lookup, + const OT_LookupTable *look, const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, + GOFFSET *goffset) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; @@ -2085,12 +2182,18 @@ static INT GPOS_apply_ContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, L { const GPOS_PosClassRule_1 *pr; const GPOS_PosClassRule_2 *pr_2; + unsigned int g; 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); + + g = glyph_index + write_dir * (g_count - 1); + if (g >= glyph_count) + continue; + 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))]); @@ -2104,18 +2207,27 @@ static INT GPOS_apply_ContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, L } TRACE("Rule matches\n"); - pr_2 = (const GPOS_PosClassRule_2*)((const BYTE*)pr+ - FIELD_OFFSET(GPOS_PosClassRule_1, Class[g_count-1])); + pr_2 = (const GPOS_PosClassRule_2 *)&pr->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; + unsigned int lookup_index = GET_BE_WORD(pr_2->PosLookupRecord[l].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(pr_2->PosLookupRecord[l].SequenceIndex); - 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); + g = glyph_index + write_dir * sequence_index; + if (g >= glyph_count) + { + WARN("Invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; + } + + TRACE("Position: %u -> %u %u.\n", l, sequence_index, lookup_index); + + GPOS_apply_lookup(script_cache, otm, logfont, analysis, advance, + lookup, lookup_index, glyphs, g, glyph_count, goffset); } - return glyph_index + 1; + return 1; } } @@ -2132,12 +2244,13 @@ static INT GPOS_apply_ContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, L else FIXME("Unhandled Contextual Positioning Format %i\n",GET_BE_WORD(cpf2->PosFormat)); } - return glyph_index + 1; + return 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) +static unsigned int GPOS_apply_ChainContextPos(const ScriptCache *script_cache, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, const OT_LookupList *lookup, + const OT_LookupTable *look, const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, + GOFFSET *goffset) { int j; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; @@ -2147,106 +2260,131 @@ static INT GPOS_apply_ChainContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpo for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++) { int offset; - const GPOS_ChainContextPosFormat3_1 *ccpf3 = (GPOS_ChainContextPosFormat3_1 *)GPOS_get_subtable(look, j); + const GPOS_ChainContextPosFormat3_1 *backtrack = (GPOS_ChainContextPosFormat3_1 *)GPOS_get_subtable(look, j); int dirLookahead = write_dir; int dirBacktrack = -1 * write_dir; - if (GET_BE_WORD(ccpf3->PosFormat) == 1) + if (GET_BE_WORD(backtrack->PosFormat) == 1) { static int once; if (!once++) FIXME(" TODO: subtype 1 (Simple Chaining Context Glyph Positioning)\n"); continue; } - else if (GET_BE_WORD(ccpf3->PosFormat) == 2) + else if (GET_BE_WORD(backtrack->PosFormat) == 2) { static int once; if (!once++) FIXME(" TODO: subtype 2 (Class-based Chaining Context Glyph Positioning)\n"); continue; } - else if (GET_BE_WORD(ccpf3->PosFormat) == 3) + else if (GET_BE_WORD(backtrack->PosFormat) == 3) { + WORD backtrack_count, input_count, lookahead_count, positioning_count; int k; - int indexGlyphs; - const GPOS_ChainContextPosFormat3_2 *ccpf3_2; - const GPOS_ChainContextPosFormat3_3 *ccpf3_3; - const GPOS_ChainContextPosFormat3_4 *ccpf3_4; + const GPOS_ChainContextPosFormat3_2 *input; + const GPOS_ChainContextPosFormat3_3 *lookahead; + const GPOS_ChainContextPosFormat3_4 *positioning; TRACE(" subtype 3 (Coverage-based Chaining Context Glyph Positioning)\n"); - for (k = 0; k < GET_BE_WORD(ccpf3->BacktrackGlyphCount); k++) + backtrack_count = GET_BE_WORD(backtrack->BacktrackGlyphCount); + k = glyph_index + dirBacktrack * backtrack_count; + if (k < 0 || k >= glyph_count) + continue; + + input = (const GPOS_ChainContextPosFormat3_2 *)&backtrack->Coverage[backtrack_count]; + input_count = GET_BE_WORD(input->InputGlyphCount); + k = glyph_index + write_dir * (input_count - 1); + if (k < 0 || k >= glyph_count) + continue; + + lookahead = (const GPOS_ChainContextPosFormat3_3 *)&input->Coverage[input_count]; + lookahead_count = GET_BE_WORD(lookahead->LookaheadGlyphCount); + k = glyph_index + dirLookahead * (input_count + lookahead_count - 1); + if (k < 0 || k >= glyph_count) + continue; + + positioning = (const GPOS_ChainContextPosFormat3_4 *)&lookahead->Coverage[lookahead_count]; + + for (k = 0; k < backtrack_count; ++k) { - offset = GET_BE_WORD(ccpf3->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccpf3+offset, glyphs[glyph_index + (dirBacktrack * (k+1))]) == -1) + offset = GET_BE_WORD(backtrack->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)backtrack + offset, + glyphs[glyph_index + (dirBacktrack * (k + 1))]) == -1) break; } - if (k != GET_BE_WORD(ccpf3->BacktrackGlyphCount)) + if (k != backtrack_count) continue; TRACE("Matched Backtrack\n"); - ccpf3_2 = (const GPOS_ChainContextPosFormat3_2*)((BYTE *)ccpf3 + - FIELD_OFFSET(GPOS_ChainContextPosFormat3_1, Coverage[GET_BE_WORD(ccpf3->BacktrackGlyphCount)])); - - indexGlyphs = GET_BE_WORD(ccpf3_2->InputGlyphCount); - for (k = 0; k < indexGlyphs; k++) + for (k = 0; k < input_count; ++k) { - offset = GET_BE_WORD(ccpf3_2->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccpf3+offset, glyphs[glyph_index + (write_dir * k)]) == -1) + offset = GET_BE_WORD(input->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)backtrack + offset, + glyphs[glyph_index + (write_dir * k)]) == -1) break; } - if (k != indexGlyphs) + if (k != input_count) continue; TRACE("Matched IndexGlyphs\n"); - ccpf3_3 = (const GPOS_ChainContextPosFormat3_3*)((BYTE *)ccpf3_2 + - FIELD_OFFSET(GPOS_ChainContextPosFormat3_2, Coverage[GET_BE_WORD(ccpf3_2->InputGlyphCount)])); - - for (k = 0; k < GET_BE_WORD(ccpf3_3->LookaheadGlyphCount); k++) + for (k = 0; k < lookahead_count; ++k) { - offset = GET_BE_WORD(ccpf3_3->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccpf3+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k))]) == -1) + offset = GET_BE_WORD(lookahead->Coverage[k]); + if (GSUB_is_glyph_covered((const BYTE *)backtrack + offset, + glyphs[glyph_index + (dirLookahead * (input_count + k))]) == -1) break; } - if (k != GET_BE_WORD(ccpf3_3->LookaheadGlyphCount)) + if (k != lookahead_count) continue; TRACE("Matched LookAhead\n"); - ccpf3_4 = (const GPOS_ChainContextPosFormat3_4*)((BYTE *)ccpf3_3 + - FIELD_OFFSET(GPOS_ChainContextPosFormat3_3, Coverage[GET_BE_WORD(ccpf3_3->LookaheadGlyphCount)])); + if (!(positioning_count = GET_BE_WORD(positioning->PosCount))) + return 1; - if (GET_BE_WORD(ccpf3_4->PosCount)) + for (k = 0; k < positioning_count; ++k) { - for (k = 0; k < GET_BE_WORD(ccpf3_4->PosCount); k++) - { - int lookupIndex = GET_BE_WORD(ccpf3_4->PosLookupRecord[k].LookupListIndex); - int SequenceIndex = GET_BE_WORD(ccpf3_4->PosLookupRecord[k].SequenceIndex) * write_dir; + unsigned int lookup_index = GET_BE_WORD(positioning->PosLookupRecord[k].LookupListIndex); + unsigned int sequence_index = GET_BE_WORD(positioning->PosLookupRecord[k].SequenceIndex); + unsigned int g = glyph_index + write_dir * sequence_index; - TRACE("Position: %i -> %i %i\n",k, SequenceIndex, lookupIndex); - GPOS_apply_lookup(psc, lpotm, lplogfont, analysis, piAdvance, lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, glyph_count, pGoffset); + if (g >= glyph_count) + { + WARN("Skipping invalid sequence index %u (glyph index %u, write dir %d).\n", + sequence_index, glyph_index, write_dir); + continue; } - return glyph_index + indexGlyphs + GET_BE_WORD(ccpf3_3->LookaheadGlyphCount); + + TRACE("Position: %u -> %u %u.\n", k, sequence_index, lookup_index); + GPOS_apply_lookup(script_cache, otm, logfont, analysis, advance, lookup, lookup_index, + glyphs, g, glyph_count, goffset); } - else return glyph_index + 1; + return input_count + lookahead_count; } else - FIXME("Unhandled Chaining Contextual Positioning Format %i\n",GET_BE_WORD(ccpf3->PosFormat)); + FIXME("Unhandled Chaining Contextual Positioning Format %#x.\n", GET_BE_WORD(backtrack->PosFormat)); } - return glyph_index + 1; + return 1; } -static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) +static unsigned int GPOS_apply_lookup(const ScriptCache *script_cache, const OUTLINETEXTMETRICW *lpotm, + const LOGFONTW *lplogfont, const SCRIPT_ANALYSIS *analysis, int *piAdvance, const OT_LookupList *lookup, + unsigned int lookup_index, const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, + GOFFSET *pGoffset) { int offset; const OT_LookupTable *look; int ppem = lpotm->otmTextMetrics.tmAscent + lpotm->otmTextMetrics.tmDescent - lpotm->otmTextMetrics.tmInternalLeading; - WORD type; + enum gpos_lookup_type type; offset = GET_BE_WORD(lookup->Lookup[lookup_index]); look = (const OT_LookupTable*)((const BYTE*)lookup + offset); type = GET_BE_WORD(look->LookupType); - TRACE("type %i, flag %x, subtables %i\n",type,GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount)); - if (type == 9) + TRACE("type %#x, flag %#x, subtables %u.\n", type, + GET_BE_WORD(look->LookupFlag), GET_BE_WORD(look->SubTableCount)); + + if (type == GPOS_LOOKUP_POSITION_EXTENSION) { if (GET_BE_WORD(look->SubTableCount)) { @@ -2268,7 +2406,7 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG } switch (type) { - case 1: + case GPOS_LOOKUP_ADJUST_SINGLE: { double devX, devY; POINT adjust = {0,0}; @@ -2289,16 +2427,18 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG } break; } - case 2: + + case GPOS_LOOKUP_ADJUST_PAIR: { POINT advance[2]= {{0,0},{0,0}}; POINT adjust[2]= {{0,0},{0,0}}; double devX, devY; - int index; + int index_offset; int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; int offset_sign = (analysis->fRTL && analysis->fLogicalOrder) ? -1 : 1; - index = GPOS_apply_PairAdjustment(look, analysis, glyphs, glyph_index, glyph_count, ppem, adjust, advance); + index_offset = GPOS_apply_PairAdjustment(look, analysis, glyphs, + glyph_index, glyph_count, ppem, adjust, advance); if (adjust[0].x || adjust[0].y) { GPOS_convert_design_units_to_device(lpotm, lplogfont, adjust[0].x, adjust[0].y, &devX, &devY); @@ -2321,9 +2461,10 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG GPOS_convert_design_units_to_device(lpotm, lplogfont, advance[1].x, advance[1].y, &devX, &devY); piAdvance[glyph_index + write_dir] += round(devX); } - return index; + return index_offset; } - case 3: + + case GPOS_LOOKUP_ATTACH_CURSIVE: { POINT desU = {0,0}; double devX, devY; @@ -2338,11 +2479,13 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG } break; } - case 4: + + case GPOS_LOOKUP_ATTACH_MARK_TO_BASE: { double devX, devY; POINT desU = {0,0}; - int base_index = GPOS_apply_MarkToBase(psc, look, analysis, glyphs, glyph_index, glyph_count, ppem, &desU); + int base_index = GPOS_apply_MarkToBase(script_cache, look, analysis, + glyphs, glyph_index, glyph_count, ppem, &desU); if (base_index != -1) { GPOS_convert_design_units_to_device(lpotm, lplogfont, desU.x, desU.y, &devX, &devY); @@ -2356,7 +2499,8 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG } break; } - case 5: + + case GPOS_LOOKUP_ATTACH_MARK_TO_LIGATURE: { double devX, devY; POINT desU = {0,0}; @@ -2369,7 +2513,8 @@ static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOG } break; } - case 6: + + case GPOS_LOOKUP_ATTACH_MARK_TO_MARK: { double devX, devY; POINT desU = {0,0}; @@ -2383,24 +2528,43 @@ 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); - } + + case GPOS_LOOKUP_POSITION_CONTEXT: + return GPOS_apply_ContextPos(script_cache, lpotm, lplogfont, analysis, piAdvance, + lookup, look, glyphs, glyph_index, glyph_count, pGoffset); + + case GPOS_LOOKUP_POSITION_CONTEXT_CHAINED: + return GPOS_apply_ChainContextPos(script_cache, lpotm, lplogfont, analysis, piAdvance, + lookup, look, glyphs, glyph_index, glyph_count, pGoffset); + default: - FIXME("We do not handle SubType %i\n",type); + FIXME("Unhandled GPOS lookup type %#x.\n", type); } - return glyph_index+1; + return 1; } -INT OpenType_apply_GPOS_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) +unsigned int OpenType_apply_GPOS_lookup(const ScriptCache *script_cache, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, unsigned int lookup_index, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, GOFFSET *goffset) { - const GPOS_Header *header = (const GPOS_Header *)psc->GPOS_Table; + const GPOS_Header *header = (const GPOS_Header *)script_cache->GPOS_Table; const OT_LookupList *lookup = (const OT_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList)); - return GPOS_apply_lookup(psc, lpotm, lplogfont, analysis, piAdvance, lookup, lookup_index, glyphs, glyph_index, glyph_count, pGoffset); + return GPOS_apply_lookup(script_cache, otm, logfont, analysis, advance, lookup, + lookup_index, glyphs, glyph_index, glyph_count, goffset); +} + +static LoadedScript *usp10_script_cache_get_script(ScriptCache *script_cache, OPENTYPE_TAG tag) +{ + size_t i; + + for (i = 0; i < script_cache->script_count; ++i) + { + if (script_cache->scripts[i].tag == tag) + return &script_cache->scripts[i]; + } + + return NULL; } static void GSUB_initialize_script_cache(ScriptCache *psc) @@ -2413,10 +2577,10 @@ static void GSUB_initialize_script_cache(ScriptCache *psc) const GSUB_Header* header = (const GSUB_Header*)psc->GSUB_Table; script = (const OT_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList)); psc->script_count = GET_BE_WORD(script->ScriptCount); - TRACE("initializing %i scripts in this font\n",psc->script_count); + TRACE("initializing %li scripts in this font\n",psc->script_count); if (psc->script_count) { - psc->scripts = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LoadedScript) * psc->script_count); + psc->scripts = heap_alloc_zero(psc->script_count * sizeof(*psc->scripts)); for (i = 0; i < psc->script_count; i++) { int offset = GET_BE_WORD(script->ScriptRecord[i].Script); @@ -2432,6 +2596,7 @@ static void GPOS_expand_script_cache(ScriptCache *psc) int i, count; const OT_ScriptList *script; const GPOS_Header* header = (const GPOS_Header*)psc->GPOS_Table; + LoadedScript *loaded_script; if (!header) return; @@ -2445,10 +2610,10 @@ static void GPOS_expand_script_cache(ScriptCache *psc) if (!psc->script_count) { psc->script_count = count; - TRACE("initializing %i scripts in this font\n",psc->script_count); + TRACE("initializing %li scripts in this font\n",psc->script_count); if (psc->script_count) { - psc->scripts = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(LoadedScript) * psc->script_count); + psc->scripts = heap_alloc_zero(psc->script_count * sizeof(*psc->scripts)); for (i = 0; i < psc->script_count; i++) { int offset = GET_BE_WORD(script->ScriptRecord[i].Script); @@ -2461,24 +2626,23 @@ static void GPOS_expand_script_cache(ScriptCache *psc) { for (i = 0; i < count; i++) { - int j; int offset = GET_BE_WORD(script->ScriptRecord[i].Script); OPENTYPE_TAG tag = MS_MAKE_TAG(script->ScriptRecord[i].ScriptTag[0], script->ScriptRecord[i].ScriptTag[1], script->ScriptRecord[i].ScriptTag[2], script->ScriptRecord[i].ScriptTag[3]); - for (j = 0; j < psc->script_count; j++) + + if (!(loaded_script = usp10_script_cache_get_script(psc, tag))) { - if (psc->scripts[j].tag == tag) + if (!usp10_array_reserve((void **)&psc->scripts, &psc->scripts_size, + psc->script_count + 1, sizeof(*psc->scripts))) { - psc->scripts[j].gpos_table = ((const BYTE*)script + offset); - break; + ERR("Failed grow scripts array.\n"); + return; } + + loaded_script = &psc->scripts[psc->script_count]; + ++psc->script_count; + loaded_script->tag = tag; } - if (j == psc->script_count) - { - psc->script_count++; - psc->scripts = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,psc->scripts, sizeof(LoadedScript) * psc->script_count); - psc->scripts[j].tag = tag; - psc->scripts[j].gpos_table = ((const BYTE*)script + offset); - } + loaded_script->gpos_table = (const BYTE *)script + offset; } } } @@ -2496,36 +2660,47 @@ static void _initialize_script_cache(ScriptCache *psc) HRESULT OpenType_GetFontScriptTags(ScriptCache *psc, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags) { int i; + const LoadedScript *script; HRESULT rc = S_OK; _initialize_script_cache(psc); *pcTags = psc->script_count; - if (!searchingFor && cMaxTags < *pcTags) - rc = E_OUTOFMEMORY; - else if (searchingFor) - rc = USP_E_SCRIPT_NOT_IN_FONT; - - for (i = 0; i < psc->script_count; i++) + if (searchingFor) { - if (i < cMaxTags) - pScriptTags[i] = psc->scripts[i].tag; + if (!(script = usp10_script_cache_get_script(psc, searchingFor))) + return USP_E_SCRIPT_NOT_IN_FONT; - if (searchingFor) - { - if (searchingFor == psc->scripts[i].tag) - { - pScriptTags[0] = psc->scripts[i].tag; - *pcTags = 1; - rc = S_OK; - break; - } - } + *pScriptTags = script->tag; + *pcTags = 1; + return S_OK; + } + + if (cMaxTags < *pcTags) + rc = E_OUTOFMEMORY; + + cMaxTags = min(cMaxTags, psc->script_count); + for (i = 0; i < cMaxTags; ++i) + { + pScriptTags[i] = psc->scripts[i].tag; } return rc; } +static LoadedLanguage *usp10_script_get_language(LoadedScript *script, OPENTYPE_TAG tag) +{ + size_t i; + + for (i = 0; i < script->language_count; ++i) + { + if (script->languages[i].tag == tag) + return &script->languages[i]; + } + + return NULL; +} + static void GSUB_initialize_language_cache(LoadedScript *script) { int i; @@ -2544,9 +2719,9 @@ static void GSUB_initialize_language_cache(LoadedScript *script) if (script->language_count) { - TRACE("Deflang %p, LangCount %i\n",script->default_language.gsub_table, script->language_count); + TRACE("Deflang %p, LangCount %li\n",script->default_language.gsub_table, script->language_count); - script->languages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LoadedLanguage) * script->language_count); + script->languages = heap_alloc_zero(script->language_count * sizeof(*script->languages)); for (i = 0; i < script->language_count; i++) { @@ -2562,6 +2737,7 @@ static void GPOS_expand_language_cache(LoadedScript *script) { int count; const OT_Script* table = script->gpos_table; + LoadedLanguage *language; DWORD offset; if (!table) @@ -2583,7 +2759,7 @@ static void GPOS_expand_language_cache(LoadedScript *script) int i; script->language_count = count; - script->languages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LoadedLanguage) * script->language_count); + script->languages = heap_alloc_zero(script->language_count * sizeof(*script->languages)); for (i = 0; i < script->language_count; i++) { @@ -2594,27 +2770,26 @@ static void GPOS_expand_language_cache(LoadedScript *script) } else if (count) { - int i,j; + int i; for (i = 0; i < count; i++) { int offset = GET_BE_WORD(table->LangSysRecord[i].LangSys); OPENTYPE_TAG tag = MS_MAKE_TAG(table->LangSysRecord[i].LangSysTag[0], table->LangSysRecord[i].LangSysTag[1], table->LangSysRecord[i].LangSysTag[2], table->LangSysRecord[i].LangSysTag[3]); - for (j = 0; j < script->language_count; j++) + if (!(language = usp10_script_get_language(script, tag))) { - if (script->languages[j].tag == tag) + if (!usp10_array_reserve((void **)&script->languages, &script->languages_size, + script->language_count + 1, sizeof(*script->languages))) { - script->languages[j].gpos_table = ((const BYTE*)table + offset); - break; + ERR("Failed grow languages array.\n"); + return; } + + language = &script->languages[script->language_count]; + ++script->language_count; + language->tag = tag; } - if (j == script->language_count) - { - script->language_count++; - script->languages = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,script->languages, sizeof(LoadedLanguage) * script->language_count); - script->languages[j].tag = tag; - script->languages[j].gpos_table = ((const BYTE*)table + offset); - } + language->gpos_table = (const BYTE *)table + offset; } } } @@ -2636,17 +2811,7 @@ HRESULT OpenType_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_tag, LoadedScript *script = NULL; _initialize_script_cache(psc); - - for (i = 0; i < psc->script_count; i++) - { - if (psc->scripts[i].tag == script_tag) - { - script = &psc->scripts[i]; - break; - } - } - - if (!script) + if (!(script = usp10_script_cache_get_script(psc, script_tag))) return E_INVALIDARG; _initialize_language_cache(script); @@ -2691,141 +2856,79 @@ HRESULT OpenType_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_tag, return rc; } - -static void GSUB_initialize_feature_cache(LPCVOID table, LoadedLanguage *language) +static void usp10_language_add_feature_list(LoadedLanguage *language, char table_type, + const OT_LangSys *lang, const OT_FeatureList *feature_list) { - int i; + unsigned int count = GET_BE_WORD(lang->FeatureCount); + unsigned int i, j; - if (language->gsub_table) - { - const OT_LangSys *lang = language->gsub_table; - const GSUB_Header *header = (const GSUB_Header *)table; - const OT_FeatureList *feature_list; - - language->feature_count = GET_BE_WORD(lang->FeatureCount); - TRACE("%i features\n",language->feature_count); - - if (language->feature_count) - { - language->features = HeapAlloc(GetProcessHeap(),0,sizeof(LoadedFeature)*language->feature_count); - - feature_list = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList)); - - for (i = 0; i < language->feature_count; i++) - { - const OT_Feature *feature; - int j; - int index = GET_BE_WORD(lang->FeatureIndex[i]); - - language->features[i].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[i].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[i].feature; - language->features[i].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); - for (j = 0; j < language->features[i].lookup_count; j++) - language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[i].tableType = FEATURE_GSUB_TABLE; - } - } - } -} - -static void GPOS_expand_feature_cache(LPCVOID table, LoadedLanguage *language) -{ - int i, count; - const OT_LangSys *lang = language->gpos_table; - const GPOS_Header *header = (const GPOS_Header *)table; - const OT_FeatureList *feature_list; - - if (!lang) - return; - - count = GET_BE_WORD(lang->FeatureCount); - feature_list = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList)); - - TRACE("%i features\n",count); + TRACE("table_type %#x, %u features.\n", table_type, count); if (!count) return; if (!language->feature_count) - { - language->feature_count = count; - - if (language->feature_count) - { - language->features = HeapAlloc(GetProcessHeap(),0,sizeof(LoadedFeature)*language->feature_count); - - for (i = 0; i < language->feature_count; i++) - { - const OT_Feature *feature; - int j; - int index = GET_BE_WORD(lang->FeatureIndex[i]); - - language->features[i].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[i].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[i].feature; - language->features[i].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); - for (j = 0; j < language->features[i].lookup_count; j++) - language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[i].tableType = FEATURE_GPOS_TABLE; - } - } - } + language->features = heap_alloc(count * sizeof(*language->features)); else + language->features = HeapReAlloc(GetProcessHeap(), 0, language->features, + (language->feature_count + count) * sizeof(*language->features)); + + for (i = 0; i < count; ++i) { - language->features = HeapReAlloc(GetProcessHeap(),0,language->features, sizeof(LoadedFeature)*(language->feature_count + count)); + const OT_FeatureRecord *record; + LoadedFeature *loaded_feature; + const OT_Feature *feature; - for (i = 0; i < count; i++) - { - const OT_Feature *feature; - int j; - int index = GET_BE_WORD(lang->FeatureIndex[i]); - int idx = language->feature_count + i; + record = &feature_list->FeatureRecord[GET_BE_WORD(lang->FeatureIndex[i])]; + feature = (const OT_Feature *)((const BYTE *)feature_list + GET_BE_WORD(record->Feature)); - language->features[idx].tag = MS_MAKE_TAG(feature_list->FeatureRecord[index].FeatureTag[0], feature_list->FeatureRecord[index].FeatureTag[1], feature_list->FeatureRecord[index].FeatureTag[2], feature_list->FeatureRecord[index].FeatureTag[3]); - language->features[idx].feature = ((const BYTE*)feature_list + GET_BE_WORD(feature_list->FeatureRecord[index].Feature)); - feature = (const OT_Feature*)language->features[idx].feature; - language->features[idx].lookup_count = GET_BE_WORD(feature->LookupCount); - language->features[idx].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[idx].lookup_count); - for (j = 0; j < language->features[idx].lookup_count; j++) - language->features[idx].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - language->features[idx].tableType = FEATURE_GPOS_TABLE; - } - language->feature_count += count; + loaded_feature = &language->features[language->feature_count + i]; + loaded_feature->tag = MS_MAKE_TAG(record->FeatureTag[0], record->FeatureTag[1], + record->FeatureTag[2], record->FeatureTag[3]); + loaded_feature->tableType = table_type; + loaded_feature->feature = feature; + loaded_feature->lookup_count = GET_BE_WORD(feature->LookupCount); + loaded_feature->lookups = heap_alloc(loaded_feature->lookup_count * sizeof(*loaded_feature->lookups)); + for (j = 0; j < loaded_feature->lookup_count; ++j) + loaded_feature->lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); } + language->feature_count += count; } static void _initialize_feature_cache(ScriptCache *psc, LoadedLanguage *language) { - if (!language->features_initialized) + const GSUB_Header *gsub_header = psc->GSUB_Table; + const GPOS_Header *gpos_header = psc->GPOS_Table; + const OT_FeatureList *feature_list; + const OT_LangSys *lang; + + if (language->features_initialized) + return; + + if ((lang = language->gsub_table)) { - GSUB_initialize_feature_cache(psc->GSUB_Table, language); - GPOS_expand_feature_cache(psc->GPOS_Table, language); - language->features_initialized = TRUE; + feature_list = (const OT_FeatureList *)((const BYTE *)gsub_header + GET_BE_WORD(gsub_header->FeatureList)); + usp10_language_add_feature_list(language, FEATURE_GSUB_TABLE, lang, feature_list); } + + if ((lang = language->gpos_table)) + { + feature_list = (const OT_FeatureList *)((const BYTE *)gpos_header + GET_BE_WORD(gpos_header->FeatureList)); + usp10_language_add_feature_list(language, FEATURE_GPOS_TABLE, lang, feature_list); + } + + language->features_initialized = TRUE; } HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, char tableType, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) { int i; + LoadedScript *script; HRESULT rc = S_OK; - LoadedScript *script = NULL; LoadedLanguage *language = NULL; _initialize_script_cache(psc); - - for (i = 0; i < psc->script_count; i++) - { - if (psc->scripts[i].tag == script_tag) - { - script = &psc->scripts[i]; - break; - } - } - - if (!script) + if (!(script = usp10_script_cache_get_script(psc, script_tag))) { *pcTags = 0; if (!filtered) @@ -2839,16 +2942,7 @@ HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, O if ((script->default_language.gsub_table || script->default_language.gpos_table) && script->default_language.tag == language_tag) language = &script->default_language; else - { - for (i = 0; i < script->language_count; i++) - { - if (script->languages[i].tag == language_tag) - { - language = &script->languages[i]; - break; - } - } - } + language = usp10_script_get_language(script, language_tag); if (!language) { diff --git a/reactos/dll/win32/usp10/shape.c b/reactos/dll/win32/usp10/shape.c index 74c7a387847..169cf801544 100644 --- a/reactos/dll/win32/usp10/shape.c +++ b/reactos/dll/win32/usp10/shape.c @@ -108,12 +108,13 @@ typedef struct tagConsonantComponents WCHAR output; } ConsonantComponents; -typedef void (*second_reorder_function)(LPWSTR pwChar, IndicSyllable *syllable,WORD* pwGlyphs, IndicSyllable* glyph_index, lexical_function lex); +typedef void (*second_reorder_function)(const WCHAR *chars, const IndicSyllable *syllable, + WORD *glyphs, const IndicSyllable *glyph_index, lexical_function lex); typedef int (*combining_lexical_function)(WCHAR c); /* the orders of joined_forms and contextual_features need to line up */ -static const char* contextual_features[] = +static const char *const contextual_features[] = { "isol", "fina", @@ -156,7 +157,7 @@ static OPENTYPE_FEATURE_RECORD arabic_features[] = { MS_MAKE_TAG('m','s','e','t'), 1}, }; -static const char* required_arabic_features[] = +static const char *const required_arabic_features[] = { "fina", "init", @@ -193,7 +194,7 @@ static OPENTYPE_FEATURE_RECORD syriac_features[] = { MS_MAKE_TAG('d','l','i','g'), 1}, }; -static const char* required_syriac_features[] = +static const char *const required_syriac_features[] = { "fina", "fin2", @@ -251,13 +252,13 @@ static OPENTYPE_FEATURE_RECORD thai_gpos_features[] = { MS_MAKE_TAG('m','k','m','k'), 1}, }; -static const char* required_lao_features[] = +static const char *const required_lao_features[] = { "ccmp", NULL }; -static const char* required_devanagari_features[] = +static const char *const required_devanagari_features[] = { "nukt", "akhn", @@ -297,7 +298,7 @@ static OPENTYPE_FEATURE_RECORD myanmar_features[] = { MS_MAKE_TAG('c','l','i','g'), 1}, }; -static const char* required_bengali_features[] = +static const char *const required_bengali_features[] = { "nukt", "akhn", @@ -314,7 +315,7 @@ static const char* required_bengali_features[] = NULL }; -static const char* required_gurmukhi_features[] = +static const char *const required_gurmukhi_features[] = { "nukt", "akhn", @@ -333,7 +334,7 @@ static const char* required_gurmukhi_features[] = NULL }; -static const char* required_oriya_features[] = +static const char *const required_oriya_features[] = { "nukt", "akhn", @@ -350,7 +351,7 @@ static const char* required_oriya_features[] = NULL }; -static const char* required_tamil_features[] = +static const char *const required_tamil_features[] = { "nukt", "akhn", @@ -366,7 +367,7 @@ static const char* required_tamil_features[] = NULL }; -static const char* required_telugu_features[] = +static const char *const required_telugu_features[] = { "nukt", "akhn", @@ -393,7 +394,7 @@ static OPENTYPE_FEATURE_RECORD khmer_features[] = { MS_MAKE_TAG('c','l','i','g'), 1}, }; -static const char* required_khmer_features[] = +static const char *const required_khmer_features[] = { "pref", "blwf", @@ -434,7 +435,7 @@ static OPENTYPE_FEATURE_RECORD mongolian_features[] = typedef struct ScriptShapeDataTag { TEXTRANGE_PROPERTIES defaultTextRange; TEXTRANGE_PROPERTIES defaultGPOSTextRange; - const char** requiredFeatures; + const char *const *requiredFeatures; OPENTYPE_TAG newOtTag; ContextualShapingProc contextProc; ShapeCharGlyphPropProc charGlyphPropProc; @@ -529,7 +530,8 @@ static const ScriptShapeData ShapingData[] = extern scriptData scriptInformation[]; -static INT GSUB_apply_feature_all_lookups(LPCVOID header, LoadedFeature *feature, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static int GSUB_apply_feature_all_lookups(const void *header, LoadedFeature *feature, + WORD *glyphs, unsigned int glyph_index, int write_dir, int *glyph_count) { int i; int out_index = GSUB_E_NOGLYPH; @@ -553,19 +555,21 @@ static INT GSUB_apply_feature_all_lookups(LPCVOID header, LoadedFeature *feature return out_index; } -static OPENTYPE_TAG get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, BOOL tryNew) +static OPENTYPE_TAG get_opentype_script(HDC hdc, const SCRIPT_ANALYSIS *psa, + const ScriptCache *script_cache, BOOL try_new) { UINT charset; - if (psc->userScript != 0) + if (script_cache->userScript) { - if (tryNew && ShapingData[psa->eScript].newOtTag != 0 && psc->userScript == scriptInformation[psa->eScript].scriptTag) + if (try_new && ShapingData[psa->eScript].newOtTag + && script_cache->userScript == scriptInformation[psa->eScript].scriptTag) return ShapingData[psa->eScript].newOtTag; - else - return psc->userScript; + + return script_cache->userScript; } - if (tryNew && ShapingData[psa->eScript].newOtTag != 0) + if (try_new && ShapingData[psa->eScript].newOtTag) return ShapingData[psa->eScript].newOtTag; if (scriptInformation[psa->eScript].scriptTag) @@ -648,7 +652,7 @@ static VOID *load_gsub_table(HDC hdc) int length = GetFontData(hdc, MS_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, 0); if (length != GDI_ERROR) { - GSUB_Table = HeapAlloc(GetProcessHeap(),0,length); + GSUB_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'S', 'U', 'B'), 0, GSUB_Table, length); TRACE("Loaded GSUB table of %i bytes\n",length); } @@ -661,7 +665,7 @@ static VOID *load_gpos_table(HDC hdc) int length = GetFontData(hdc, MS_MAKE_TAG('G', 'P', 'O', 'S'), 0, NULL, 0); if (length != GDI_ERROR) { - GPOS_Table = HeapAlloc(GetProcessHeap(),0,length); + GPOS_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'P', 'O', 'S'), 0, GPOS_Table, length); TRACE("Loaded GPOS table of %i bytes\n",length); } @@ -674,7 +678,7 @@ static VOID *load_gdef_table(HDC hdc) int length = GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, NULL, 0); if (length != GDI_ERROR) { - GDEF_Table = HeapAlloc(GetProcessHeap(),0,length); + GDEF_Table = heap_alloc(length); GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, GDEF_Table, length); TRACE("Loaded GDEF table of %i bytes\n",length); } @@ -697,7 +701,7 @@ INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, Script INT glyph_count = count; INT rc; - glyphs = HeapAlloc(GetProcessHeap(),0,sizeof(WORD)*(count*2)); + glyphs = heap_alloc(2 * count * sizeof(*glyphs)); GetGlyphIndicesW(hdc, chars, count, glyphs, 0); rc = apply_GSUB_feature_to_glyph(hdc, psa, psc, glyphs, 0, write_dir, &glyph_count, feature); if (rc > GSUB_E_NOGLYPH) @@ -705,7 +709,7 @@ INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, Script else rc = 0; - HeapFree(GetProcessHeap(),0,glyphs); + heap_free(glyphs); return rc; } @@ -739,13 +743,12 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch return; else { + int cluster_dir = pwLogClust[0] < pwLogClust[chars-1] ? 1 : -1; int i; int target_glyph = nextIndex - write_dir; - int seeking_glyph; int target_index = -1; int replacing_glyph = -1; int changed = 0; - int top_logclust = 0; if (changeCount > 0) { @@ -755,35 +758,7 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch target_glyph = nextIndex + (changeCount + 1); } - seeking_glyph = target_glyph; - for (i = 0; i < chars; i++) - if (pwLogClust[i] > top_logclust) - top_logclust = pwLogClust[i]; - - do { - if (write_dir > 0) - for (i = 0; i < chars; i++) - { - if (pwLogClust[i] == seeking_glyph) - { - target_index = i; - break; - } - } - else - for (i = chars - 1; i >= 0; i--) - { - if (pwLogClust[i] == seeking_glyph) - { - target_index = i; - break; - } - } - if (target_index == -1) - seeking_glyph ++; - } - while (target_index == -1 && seeking_glyph <= top_logclust); - + target_index = USP10_FindGlyphInLogClust(pwLogClust, chars, target_glyph); if (target_index == -1) { ERR("Unable to find target glyph\n"); @@ -793,7 +768,7 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch if (changeCount < 0) { /* merge glyphs */ - for(i = target_index; i < chars && i >= 0; i+=write_dir) + for (i = target_index; i < chars && i >= 0; i += cluster_dir) { if (pwLogClust[i] == target_glyph) continue; @@ -812,8 +787,8 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch } } - /* renumber trailing indexes*/ - for(i = target_index; i < chars && i >= 0; i+=write_dir) + /* renumber trailing indexes */ + for (i = target_index; i < chars && i >= 0; i += cluster_dir) { if (pwLogClust[i] != target_glyph) pwLogClust[i] += changeCount; @@ -821,8 +796,8 @@ static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int ch } else { - for(i = target_index; i < chars && i >= 0; i+=write_dir) - pwLogClust[i] += changeCount; + for (i = target_index; i < chars && i >= 0; i += cluster_dir) + pwLogClust[i] += changeCount; } } } @@ -868,16 +843,21 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W return GSUB_E_NOFEATURE; } -static VOID GPOS_apply_feature(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, LoadedFeature *feature, const WORD *glyphs, INT glyph_count, GOFFSET *pGoffset) +static void GPOS_apply_feature(const ScriptCache *psc, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, + const LoadedFeature *feature, const WORD *glyphs, int glyph_count, GOFFSET *goffset) { - int i; + int dir = analysis->fLogicalOrder && analysis->fRTL ? -1 : 1; + unsigned int start_idx, i, j; TRACE("%i lookups\n", feature->lookup_count); + + start_idx = dir < 0 ? glyph_count - 1 : 0; for (i = 0; i < feature->lookup_count; i++) { - int j; for (j = 0; j < glyph_count; ) - j = OpenType_apply_GPOS_lookup(psc, lpotm, lplogfont, analysis, piAdvance, feature->lookups[i], glyphs, j, glyph_count, pGoffset); + j += OpenType_apply_GPOS_lookup(psc, otm, logfont, analysis, advance, + feature->lookups[i], glyphs, start_idx + dir * j, glyph_count, goffset); } } @@ -912,7 +892,7 @@ static void mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars WCHAR invalid = 0x25cc; WORD invalid_glyph; - context_type = HeapAlloc(GetProcessHeap(),0,cChars); + context_type = heap_alloc(cChars); /* Mark invalid combinations */ for (i = 0; i < cChars; i++) @@ -928,7 +908,7 @@ static void mark_invalid_combinations(HDC hdc, const WCHAR* pwcChars, INT cChars } } - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_type); } static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) @@ -1069,21 +1049,21 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p return; } - if (!psa->fLogicalOrder && psa->fRTL) - { - dirR = 1; - dirL = -1; - } - else + if (psa->fLogicalOrder && psa->fRTL) { dirR = -1; dirL = 1; } + else + { + dirR = 1; + dirL = -1; + } load_ot_tables(hdc, psc); - context_type = HeapAlloc(GetProcessHeap(),0,cChars); - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_type = heap_alloc(cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); @@ -1143,8 +1123,14 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p offset = *pcGlyphs - prevCount; glyph_index += dirL * (offset + 1); } + shaped = TRUE; + } + else if (nextIndex == GSUB_E_NOGLYPH) + { + char_index += dirL; + glyph_index += dirL; + shaped = TRUE; } - shaped = (nextIndex > GSUB_E_NOGLYPH); } if (!shaped) @@ -1165,8 +1151,8 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p } } - HeapFree(GetProcessHeap(),0,context_shape); - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_shape); + heap_free(context_type); mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Arabic); } @@ -1333,8 +1319,8 @@ static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p if (!psc->GSUB_Table) return; - context_type = HeapAlloc(GetProcessHeap(),0,cChars); - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_type = heap_alloc(cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); @@ -1413,8 +1399,8 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) } } - HeapFree(GetProcessHeap(),0,context_shape); - HeapFree(GetProcessHeap(),0,context_type); + heap_free(context_shape); + heap_free(context_type); mark_invalid_combinations(hdc, pwcChars, cChars, pwOutGlyphs, pcGlyphs, dirL, pwLogClust, combining_lexical_Syriac); } @@ -1495,7 +1481,7 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS if (!psc->GSUB_Table) return; - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) { @@ -1552,7 +1538,7 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } } - HeapFree(GetProcessHeap(),0,context_shape); + heap_free(context_shape); } static int combining_lexical_Thai(WCHAR c) @@ -1721,7 +1707,7 @@ static void ComposeConsonants(HDC hdc, WCHAR *pwOutChars, INT *pcChars, const Co } } -static void Reorder_Ra_follows_base(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Ra_follows_base(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { if (s->ralf >= 0) { @@ -1740,7 +1726,7 @@ static void Reorder_Ra_follows_base(LPWSTR pwChar, IndicSyllable *s, lexical_fun } } -static void Reorder_Ra_follows_matra(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Ra_follows_matra(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { if (s->ralf >= 0) { @@ -1765,7 +1751,7 @@ static void Reorder_Ra_follows_matra(LPWSTR pwChar, IndicSyllable *s, lexical_fu } } -static void Reorder_Ra_follows_syllable(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Ra_follows_syllable(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { if (s->ralf >= 0) { @@ -1786,7 +1772,7 @@ static void Reorder_Ra_follows_syllable(LPWSTR pwChar, IndicSyllable *s, lexical } } -static void Reorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Matra_precede_base(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { int i; @@ -1813,7 +1799,7 @@ static void Reorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, lexical_ } } -static void Reorder_Matra_precede_syllable(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Matra_precede_syllable(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { int i; @@ -1840,14 +1826,16 @@ static void Reorder_Matra_precede_syllable(LPWSTR pwChar, IndicSyllable *s, lexi } } -static void SecondReorder_Blwf_follows_matra(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +static void SecondReorder_Blwf_follows_matra(const WCHAR *chars, const IndicSyllable *s, + WORD *glyphs, const IndicSyllable *g, lexical_function lexical) { if (s->blwf >= 0 && g->blwf > g->base) { int j,loc; int g_offset; for (loc = s->end; loc > s->blwf; loc--) - if (lexical(pwChar[loc]) == lex_Matra_below || lexical(pwChar[loc]) == lex_Matra_above || lexical(pwChar[loc]) == lex_Matra_post) + if (lexical(chars[loc]) == lex_Matra_below || lexical(chars[loc]) == lex_Matra_above + || lexical(chars[loc]) == lex_Matra_post) break; g_offset = (loc - s->blwf) - 1; @@ -1864,14 +1852,15 @@ static void SecondReorder_Blwf_follows_matra(LPWSTR pwChar, IndicSyllable *s, WO } } -static void SecondReorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +static void SecondReorder_Matra_precede_base(const WCHAR *chars, const IndicSyllable *s, + WORD *glyphs, const IndicSyllable *g, lexical_function lexical) { int i; /* reorder previously moved Matras to correct position*/ for (i = s->start; i < s->base; i++) { - if (lexical(pwChar[i]) == lex_Matra_pre) + if (lexical(chars[i]) == lex_Matra_pre) { int j; int g_start = g->start + i - s->start; @@ -1887,7 +1876,8 @@ static void SecondReorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, WO } } -static void SecondReorder_Pref_precede_base(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +static void SecondReorder_Pref_precede_base(const IndicSyllable *s, + WORD *glyphs, const IndicSyllable *g, lexical_function lexical) { if (s->pref >= 0 && g->pref > g->base) { @@ -1900,7 +1890,7 @@ static void SecondReorder_Pref_precede_base(LPWSTR pwChar, IndicSyllable *s, WOR } } -static void Reorder_Like_Sinhala(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Like_Sinhala(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); if (s->start == s->base && s->base == s->end) return; @@ -1910,7 +1900,7 @@ static void Reorder_Like_Sinhala(LPWSTR pwChar, IndicSyllable *s, lexical_functi Reorder_Matra_precede_base(pwChar, s, lexical); } -static void Reorder_Like_Devanagari(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Like_Devanagari(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); if (s->start == s->base && s->base == s->end) return; @@ -1920,7 +1910,7 @@ static void Reorder_Like_Devanagari(LPWSTR pwChar, IndicSyllable *s, lexical_fun Reorder_Matra_precede_syllable(pwChar, s, lexical); } -static void Reorder_Like_Bengali(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Like_Bengali(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); if (s->start == s->base && s->base == s->end) return; @@ -1930,7 +1920,7 @@ static void Reorder_Like_Bengali(LPWSTR pwChar, IndicSyllable *s, lexical_functi Reorder_Matra_precede_syllable(pwChar, s, lexical); } -static void Reorder_Like_Kannada(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +static void Reorder_Like_Kannada(WCHAR *pwChar, IndicSyllable *s, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); if (s->start == s->base && s->base == s->end) return; @@ -1940,25 +1930,27 @@ static void Reorder_Like_Kannada(LPWSTR pwChar, IndicSyllable *s, lexical_functi Reorder_Matra_precede_syllable(pwChar, s, lexical); } -static void SecondReorder_Like_Telugu(LPWSTR pwChar, IndicSyllable *s, WORD* pwGlyphs, IndicSyllable *g, lexical_function lexical) +static void SecondReorder_Like_Telugu(const WCHAR *chars, const IndicSyllable *s, + WORD *glyphs, const IndicSyllable *g, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); TRACE("Glyphs (%i..%i..%i)\n",g->start,g->base,g->end); if (s->start == s->base && s->base == s->end) return; - if (lexical(pwChar[s->base]) == lex_Vowel) return; + if (lexical(chars[s->base]) == lex_Vowel) return; - SecondReorder_Blwf_follows_matra(pwChar, s, pwGlyphs, g, lexical); + SecondReorder_Blwf_follows_matra(chars, s, glyphs, g, lexical); } -static void SecondReorder_Like_Tamil(LPWSTR pwChar, IndicSyllable *s, WORD* pwGlyphs, IndicSyllable *g, lexical_function lexical) +static void SecondReorder_Like_Tamil(const WCHAR *chars, const IndicSyllable *s, + WORD *glyphs, const IndicSyllable *g, lexical_function lexical) { TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); TRACE("Glyphs (%i..%i..%i)\n",g->start,g->base,g->end); if (s->start == s->base && s->base == s->end) return; - if (lexical(pwChar[s->base]) == lex_Vowel) return; + if (lexical(chars[s->base]) == lex_Vowel) return; - SecondReorder_Matra_precede_base(pwChar, s, pwGlyphs, g, lexical); - SecondReorder_Pref_precede_base(pwChar, s, pwGlyphs, g, lexical); + SecondReorder_Matra_precede_base(chars, s, glyphs, g, lexical); + SecondReorder_Pref_precede_base(s, glyphs, g, lexical); } @@ -2283,7 +2275,7 @@ static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * return; } - input = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * (cChars * 3)); + input = heap_alloc(3 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); @@ -2309,8 +2301,8 @@ static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * *pcGlyphs = cCount; ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int devanagari_lex(WCHAR c) @@ -2350,7 +2342,7 @@ static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Compose Consonant and Nukta */ @@ -2366,8 +2358,8 @@ static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, devanagari_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int bengali_lex(WCHAR c) @@ -2406,7 +2398,7 @@ static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars * 2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2436,8 +2428,8 @@ static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * /* Step 4: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, bengali_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int gurmukhi_lex(WCHAR c) @@ -2470,7 +2462,7 @@ static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Compose Consonants */ @@ -2486,8 +2478,8 @@ static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int gujarati_lex(WCHAR c) @@ -2514,7 +2506,7 @@ static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Reorder within Syllables */ @@ -2526,8 +2518,8 @@ static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS /* Step 2: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gujarati_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int oriya_lex(WCHAR c) @@ -2565,7 +2557,7 @@ static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2582,8 +2574,8 @@ static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, oriya_lex, NULL, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int tamil_lex(WCHAR c) @@ -2615,7 +2607,7 @@ static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels and Compose Consonants */ @@ -2632,8 +2624,8 @@ static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int telugu_lex(WCHAR c) @@ -2665,7 +2657,7 @@ static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2681,8 +2673,8 @@ static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int kannada_lex(WCHAR c) @@ -2717,7 +2709,7 @@ static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*3) * sizeof(WCHAR)); + input = heap_alloc(3 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2733,8 +2725,8 @@ static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int malayalam_lex(WCHAR c) @@ -2762,7 +2754,7 @@ static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS return; } - input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + input = heap_alloc(2 * cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Decompose Vowels */ @@ -2778,8 +2770,8 @@ static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS /* Step 3: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static int khmer_lex(WCHAR c) @@ -2800,7 +2792,7 @@ static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps return; } - input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + input = heap_alloc(cChars * sizeof(*input)); memcpy(input, pwcChars, cChars * sizeof(WCHAR)); /* Step 1: Reorder within Syllables */ @@ -2812,8 +2804,8 @@ static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps /* Step 2: Base Form application to syllables */ ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, khmer_lex, NULL, FALSE); - HeapFree(GetProcessHeap(),0,input); - HeapFree(GetProcessHeap(),0,syllables); + heap_free(input); + heap_free(syllables); } static inline BOOL mongolian_wordbreak(WCHAR chr) @@ -2843,7 +2835,7 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS if (!psc->GSUB_Table) return; - context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + context_shape = heap_alloc(cChars * sizeof(*context_shape)); for (i = 0; i < cChars; i++) { @@ -2888,7 +2880,7 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS } } - HeapFree(GetProcessHeap(),0,context_shape); + heap_free(context_shape); } static void ShapeCharGlyphProp_Default( ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) @@ -2957,23 +2949,23 @@ static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI INT dirR, dirL; BYTE *spaces; - spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs); + spaces = heap_alloc(cGlyphs); memset(spaces,0,cGlyphs); - if (!psa->fLogicalOrder && psa->fRTL) - { - initGlyph = cGlyphs-1; - finaGlyph = 0; - dirR = 1; - dirL = -1; - } - else + if (psa->fLogicalOrder && psa->fRTL) { initGlyph = 0; finaGlyph = cGlyphs-1; dirR = -1; dirL = 1; } + else + { + initGlyph = cGlyphs-1; + finaGlyph = 0; + dirR = 1; + dirL = -1; + } for (i = 0; i < cGlyphs; i++) { @@ -3057,7 +3049,7 @@ static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSI OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); - HeapFree(GetProcessHeap(),0,spaces); + heap_free(spaces); } static void ShapeCharGlyphProp_Hebrew( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) @@ -3305,7 +3297,7 @@ static void ShapeCharGlyphProp_BaseIndic( HDC hdc, ScriptCache *psc, SCRIPT_ANAL } } - HeapFree(GetProcessHeap(), 0, syllables); + heap_free(syllables); } UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); @@ -3397,7 +3389,7 @@ static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYS if (!psc->GSUB_Table) return; - if (!psa->fLogicalOrder && psa->fRTL) + if (scriptInformation[psa->eScript].a.fRTL && (!psa->fLogicalOrder || !psa->fRTL)) dirL = -1; else dirL = 1; diff --git a/reactos/dll/win32/usp10/usp10.c b/reactos/dll/win32/usp10/usp10.c index f56d2a09096..a563b8500d8 100644 --- a/reactos/dll/win32/usp10/usp10.c +++ b/reactos/dll/win32/usp10/usp10.c @@ -32,16 +32,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); -typedef struct _scriptRange +static const struct usp10_script_range { - WORD script; + enum usp10_script script; DWORD rangeFirst; DWORD rangeLast; - WORD numericScript; - WORD punctScript; -} scriptRange; - -static const scriptRange scriptRanges[] = { + enum usp10_script numericScript; + enum usp10_script punctScript; +} +script_ranges[] = +{ /* Basic Latin: U+0000–U+007A */ { Script_Latin, 0x00, 0x07a , Script_Numeric, Script_Punctuation}, /* Latin-1 Supplement: U+0080–U+00FF */ @@ -285,8 +285,6 @@ static const scriptRange scriptRanges[] = { { Script_Osmanya, 0x10480, 0x104AF, Script_Osmanya_Numeric, 0}, /* Mathematical Alphanumeric Symbols: U+1D400–U+1D7FF */ { Script_MathAlpha, 0x1D400, 0x1D7FF, 0, 0}, - /* END */ - { SCRIPT_UNDEFINED, 0, 0, 0} }; /* this must be in order so that the index matches the Script value */ @@ -699,19 +697,34 @@ typedef struct { WORD target; } FindGlyph_struct; -static inline void *heap_alloc(SIZE_T size) +BOOL usp10_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) { - return HeapAlloc(GetProcessHeap(), 0, size); -} + SIZE_T max_capacity, new_capacity; + void *new_elements; -static inline void *heap_alloc_zero(SIZE_T size) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); -} + if (count <= *capacity) + return TRUE; -static inline BOOL heap_free(LPVOID mem) -{ - return HeapFree(GetProcessHeap(), 0, mem); + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(1, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = count; + + if (!*elements) + new_elements = heap_alloc_zero(new_capacity * size); + else + new_elements = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *elements, new_capacity * size); + if (!new_elements) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; } /* TODO Fix font properties on Arabic locale */ @@ -866,7 +879,7 @@ static WCHAR mirror_char( WCHAR ch ) return ch + wine_mirror_map[wine_mirror_map[ch >> 8] + (ch & 0xff)]; } -static inline DWORD decode_surrogate_pair(LPCWSTR str, INT index, INT end) +static DWORD decode_surrogate_pair(const WCHAR *str, unsigned int index, unsigned int end) { if (index < end-1 && IS_SURROGATE_PAIR(str[index],str[index+1])) { @@ -877,12 +890,25 @@ static inline DWORD decode_surrogate_pair(LPCWSTR str, INT index, INT end) return 0; } -static WORD get_char_script( LPCWSTR str, INT index, INT end, INT *consumed) +static int usp10_compare_script_range(const void *key, const void *value) +{ + const struct usp10_script_range *range = value; + const DWORD *ch = key; + + if (*ch < range->rangeFirst) + return -1; + if (*ch > range->rangeLast) + return 1; + return 0; +} + +static enum usp10_script get_char_script(const WCHAR *str, unsigned int index, + unsigned int end, unsigned int *consumed) { static const WCHAR latin_punc[] = {'#','$','&','\'',',',';','<','>','?','@','\\','^','_','`','{','|','}','~', 0x00a0, 0}; + struct usp10_script_range *range; WORD type = 0, type2 = 0; DWORD ch; - int i; *consumed = 1; @@ -924,24 +950,15 @@ static WORD get_char_script( LPCWSTR str, INT index, INT end, INT *consumed) else ch = str[index]; - i = 0; - do - { - if (ch < scriptRanges[i].rangeFirst || scriptRanges[i].script == SCRIPT_UNDEFINED) - break; + if (!(range = bsearch(&ch, script_ranges, ARRAY_SIZE(script_ranges), + sizeof(*script_ranges), usp10_compare_script_range))) + return Script_Undefined; - if (ch >= scriptRanges[i].rangeFirst && ch <= scriptRanges[i].rangeLast) - { - if (scriptRanges[i].numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER)) - return scriptRanges[i].numericScript; - if (scriptRanges[i].punctScript && type & C1_PUNCT) - return scriptRanges[i].punctScript; - return scriptRanges[i].script; - } - i++; - } while (1); - - return SCRIPT_UNDEFINED; + if (range->numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER)) + return range->numericScript; + if (range->punctScript && type & C1_PUNCT) + return range->punctScript; + return range->script; } static int compare_FindGlyph(const void *a, const void* b) @@ -1140,7 +1157,8 @@ HRESULT WINAPI ScriptRecordDigitSubstitution(LCID locale, SCRIPT_DIGITSUBSTITUTE sds->NationalDigitLanguage = LANG_ENGLISH; if (!GetLocaleInfoW(locale, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, - (LPWSTR)&sub, sizeof(sub)/sizeof(WCHAR))) return E_INVALIDARG; + (WCHAR *)&sub, sizeof(sub) / sizeof(WCHAR))) + return E_INVALIDARG; switch (sub) { @@ -1209,12 +1227,12 @@ HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds, } } -static inline BOOL is_indic(WORD script) +static inline BOOL is_indic(enum usp10_script script) { return (script >= Script_Devanagari && script <= Script_Malayalam_Numeric); } -static inline WORD base_indic(WORD script) +static inline enum usp10_script base_indic(enum usp10_script script) { switch (script) { @@ -1239,11 +1257,11 @@ static inline WORD base_indic(WORD script) case Script_Malayalam: case Script_Malayalam_Numeric: return Script_Malayalam; default: - return -1; + return Script_Undefined; }; } -static BOOL script_is_numeric(WORD script) +static BOOL script_is_numeric(enum usp10_script script) { return scriptInformation[script].props.fNumeric; } @@ -1259,21 +1277,21 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, #define ZWNJ 0x200C #define ZWJ 0x200D + enum usp10_script last_indic = Script_Undefined; int cnt = 0, index = 0, str = 0; - int New_Script = -1; + enum usp10_script New_Script = -1; int i; WORD *levels = NULL; WORD *layout_levels = NULL; WORD *overrides = NULL; WORD *strength = NULL; - WORD *scripts = NULL; + enum usp10_script *scripts; WORD baselevel = 0; WORD baselayout = 0; BOOL new_run; - WORD last_indic = -1; WORD layoutRTL = 0; BOOL forceLevels = FALSE; - INT consumed = 0; + unsigned int consumed = 0; HRESULT res = E_OUTOFMEMORY; TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, @@ -1282,13 +1300,12 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2) return E_INVALIDARG; - scripts = heap_alloc(cInChars * sizeof(WORD)); - if (!scripts) + if (!(scripts = heap_alloc(cInChars * sizeof(*scripts)))) return E_OUTOFMEMORY; for (i = 0; i < cInChars; i++) { - if (consumed <= 0) + if (!consumed) { scripts[i] = get_char_script(pwcInChars,i,cInChars,&consumed); consumed --; @@ -1300,7 +1317,7 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, } /* Devanagari danda (U+0964) and double danda (U+0965) are used for all Indic scripts */ - if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic > 0) + if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic != Script_Undefined) scripts[i] = last_indic; else if (is_indic(scripts[i])) last_indic = base_indic(scripts[i]); @@ -1327,10 +1344,10 @@ static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, { int j; BOOL asian = FALSE; - WORD first_script = scripts[i-1]; + enum usp10_script first_script = scripts[i-1]; for (j = i-1; j >= 0 && scripts[j] == first_script && pwcInChars[j] != Numeric_space; j--) { - WORD original = scripts[j]; + enum usp10_script original = scripts[j]; if (original == Script_Ideograph || original == Script_Kana || original == Script_Yi || original == Script_CJK_Han || original == Script_Bopomofo) { asian = TRUE; @@ -1866,7 +1883,7 @@ static BOOL requires_fallback(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, return FALSE; } -static void find_fallback_font(DWORD scriptid, LPWSTR FaceName) +static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName) { HKEY hkey; @@ -1878,7 +1895,7 @@ static void find_fallback_font(DWORD scriptid, LPWSTR FaceName) DWORD type; sprintfW(value, szFmt, scriptInformation[scriptid].scriptTag); - if (RegQueryValueExW(hkey, value, 0, &type, (LPBYTE)FaceName, &count)) + if (RegQueryValueExW(hkey, value, 0, &type, (BYTE *)FaceName, &count)) lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont); RegCloseKey(hkey); } @@ -1966,7 +1983,9 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, if ((analysis->logattrs = heap_alloc(sizeof(SCRIPT_LOGATTR) * cString))) { for (i = 0; i < analysis->numItems; i++) - ScriptBreak(&((LPWSTR)pString)[analysis->pItem[i].iCharPos], analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos, &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]); + ScriptBreak(&((WCHAR *)pString)[analysis->pItem[i].iCharPos], + analysis->pItem[i + 1].iCharPos - analysis->pItem[i].iCharPos, + &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]); } else goto error; @@ -2984,14 +3003,16 @@ HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS */ HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag) { - int i; - INT consumed = 0; + enum usp10_script script; + unsigned int i, consumed; TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag); + if (!chars || len < 0) + return E_INVALIDARG; + for (i = 0; i < len; i+=consumed) { - int script; if (i >= len) break; @@ -3336,15 +3357,24 @@ HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS } else if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc)) { + BOOL ret; if (!hdc) return E_PENDING; - if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) + if (get_cache_pitch_family(psc) & TMPF_TRUETYPE) { - if (!GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc)) return S_FALSE; + if (psa->fNoGlyphIndex) + ret = GetCharABCWidthsW(hdc, pwGlyphs[i], pwGlyphs[i], &abc); + else + ret = GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc); + if (!ret) return S_FALSE; } else { INT width; - if (!GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return S_FALSE; + if (psa->fNoGlyphIndex) + ret = GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width); + else + ret = GetCharWidthI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &width); + if (!ret) return S_FALSE; abc.abcB = width; abc.abcA = abc.abcC = 0; } diff --git a/reactos/dll/win32/usp10/usp10.spec b/reactos/dll/win32/usp10/usp10.spec index 7ffef413d77..4eb9e9666a8 100644 --- a/reactos/dll/win32/usp10/usp10.spec +++ b/reactos/dll/win32/usp10/usp10.spec @@ -13,7 +13,7 @@ @ stdcall ScriptGetFontScriptTags(long ptr ptr long ptr ptr) @ stdcall ScriptGetGlyphABCWidth(ptr ptr long ptr) @ stdcall ScriptGetLogicalWidths(ptr long long ptr ptr ptr ptr) -@ stdcall ScriptGetProperties(ptr long) +@ stdcall ScriptGetProperties(ptr ptr) @ stdcall ScriptIsComplex(wstr long long) @ stdcall ScriptItemize(wstr long long ptr ptr ptr ptr) @ stdcall ScriptItemizeOpenType(wstr long long ptr ptr ptr ptr ptr) diff --git a/reactos/dll/win32/usp10/usp10_internal.h b/reactos/dll/win32/usp10/usp10_internal.h index fa14e51f084..da5f3fe8ebe 100644 --- a/reactos/dll/win32/usp10/usp10_internal.h +++ b/reactos/dll/win32/usp10/usp10_internal.h @@ -44,101 +44,108 @@ ( (ULONG)_x2 << 8 ) | \ (ULONG)_x1 ) +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif -#define Script_Latin 1 -#define Script_CR 2 -#define Script_Numeric 3 -#define Script_Control 4 -#define Script_Punctuation 5 -#define Script_Arabic 6 -#define Script_Arabic_Numeric 7 -#define Script_Hebrew 8 -#define Script_Syriac 9 -#define Script_Persian 10 -#define Script_Thaana 11 -#define Script_Greek 12 -#define Script_Cyrillic 13 -#define Script_Armenian 14 -#define Script_Georgian 15 -/* Unicode Chapter 10 */ -#define Script_Sinhala 16 -#define Script_Tibetan 17 -#define Script_Tibetan_Numeric 18 -#define Script_Phags_pa 19 -/* Unicode Chapter 11 */ -#define Script_Thai 20 -#define Script_Thai_Numeric 21 -#define Script_Lao 22 -#define Script_Lao_Numeric 23 -/* Unicode Chapter 9 */ -#define Script_Devanagari 24 -#define Script_Devanagari_Numeric 25 -#define Script_Bengali 26 -#define Script_Bengali_Numeric 27 -#define Script_Bengali_Currency 28 -#define Script_Gurmukhi 29 -#define Script_Gurmukhi_Numeric 30 -#define Script_Gujarati 31 -#define Script_Gujarati_Numeric 32 -#define Script_Gujarati_Currency 33 -#define Script_Oriya 34 -#define Script_Oriya_Numeric 35 -#define Script_Tamil 36 -#define Script_Tamil_Numeric 37 -#define Script_Telugu 38 -#define Script_Telugu_Numeric 39 -#define Script_Kannada 40 -#define Script_Kannada_Numeric 41 -#define Script_Malayalam 42 -#define Script_Malayalam_Numeric 43 -/* More supplemental */ -#define Script_Diacritical 44 -#define Script_Punctuation2 45 -#define Script_Numeric2 46 -/* Unicode Chapter 11 continued */ -#define Script_Myanmar 47 -#define Script_Myanmar_Numeric 48 -#define Script_Tai_Le 49 -#define Script_New_Tai_Lue 50 -#define Script_New_Tai_Lue_Numeric 51 -#define Script_Khmer 52 -#define Script_Khmer_Numeric 53 -/* Unicode Chapter 12 */ -#define Script_CJK_Han 54 -#define Script_Ideograph 55 -#define Script_Bopomofo 56 -#define Script_Kana 57 -#define Script_Hangul 58 -#define Script_Yi 59 -/* Unicode Chapter 13 */ -#define Script_Ethiopic 60 -#define Script_Ethiopic_Numeric 61 -#define Script_Mongolian 62 -#define Script_Mongolian_Numeric 63 -#define Script_Tifinagh 64 -#define Script_NKo 65 -#define Script_Vai 66 -#define Script_Vai_Numeric 67 -#define Script_Cherokee 68 -#define Script_Canadian 69 -/* Unicode Chapter 14 */ -#define Script_Ogham 70 -#define Script_Runic 71 -/* Unicode Chapter 15 */ -#define Script_Braille 72 -/* Unicode Chapter 16 */ -#define Script_Surrogates 73 -#define Script_Private 74 -/* Unicode Chapter 13 : Plane 1 */ -#define Script_Deseret 75 -#define Script_Osmanya 76 -#define Script_Osmanya_Numeric 77 -/* Unicode Chapter 15 : Plane 1 */ -#define Script_MathAlpha 78 -/* Additional Currency Scripts */ -#define Script_Hebrew_Currency 79 -#define Script_Vietnamese_Currency 80 -#define Script_Thai_Currency 81 +enum usp10_script +{ + Script_Undefined = 0x00, + Script_Latin = 0x01, + Script_CR = 0x02, + Script_Numeric = 0x03, + Script_Control = 0x04, + Script_Punctuation = 0x05, + Script_Arabic = 0x06, + Script_Arabic_Numeric = 0x07, + Script_Hebrew = 0x08, + Script_Syriac = 0x09, + Script_Persian = 0x0a, + Script_Thaana = 0x0b, + Script_Greek = 0x0c, + Script_Cyrillic = 0x0d, + Script_Armenian = 0x0e, + Script_Georgian = 0x0f, + /* Unicode Chapter 10 */ + Script_Sinhala = 0x10, + Script_Tibetan = 0x11, + Script_Tibetan_Numeric = 0x12, + Script_Phags_pa = 0x13, + /* Unicode Chapter 11 */ + Script_Thai = 0x14, + Script_Thai_Numeric = 0x15, + Script_Lao = 0x16, + Script_Lao_Numeric = 0x17, + /* Unicode Chapter 9 */ + Script_Devanagari = 0x18, + Script_Devanagari_Numeric = 0x19, + Script_Bengali = 0x1a, + Script_Bengali_Numeric = 0x1b, + Script_Bengali_Currency = 0x1c, + Script_Gurmukhi = 0x1d, + Script_Gurmukhi_Numeric = 0x1e, + Script_Gujarati = 0x1f, + Script_Gujarati_Numeric = 0x20, + Script_Gujarati_Currency = 0x21, + Script_Oriya = 0x22, + Script_Oriya_Numeric = 0x23, + Script_Tamil = 0x24, + Script_Tamil_Numeric = 0x25, + Script_Telugu = 0x26, + Script_Telugu_Numeric = 0x27, + Script_Kannada = 0x28, + Script_Kannada_Numeric = 0x29, + Script_Malayalam = 0x2a, + Script_Malayalam_Numeric = 0x2b, + /* More supplemental */ + Script_Diacritical = 0x2c, + Script_Punctuation2 = 0x2d, + Script_Numeric2 = 0x2e, + /* Unicode Chapter 11 continued */ + Script_Myanmar = 0x2f, + Script_Myanmar_Numeric = 0x30, + Script_Tai_Le = 0x31, + Script_New_Tai_Lue = 0x32, + Script_New_Tai_Lue_Numeric = 0x33, + Script_Khmer = 0x34, + Script_Khmer_Numeric = 0x35, + /* Unicode Chapter 12 */ + Script_CJK_Han = 0x36, + Script_Ideograph = 0x37, + Script_Bopomofo = 0x38, + Script_Kana = 0x39, + Script_Hangul = 0x3a, + Script_Yi = 0x3b, + /* Unicode Chapter 13 */ + Script_Ethiopic = 0x3c, + Script_Ethiopic_Numeric = 0x3d, + Script_Mongolian = 0x3e, + Script_Mongolian_Numeric = 0x3f, + Script_Tifinagh = 0x40, + Script_NKo = 0x41, + Script_Vai = 0x42, + Script_Vai_Numeric = 0x43, + Script_Cherokee = 0x44, + Script_Canadian = 0x45, + /* Unicode Chapter 14 */ + Script_Ogham = 0x46, + Script_Runic = 0x47, + /* Unicode Chapter 15 */ + Script_Braille = 0x48, + /* Unicode Chapter 16 */ + Script_Surrogates = 0x49, + Script_Private = 0x4a, + /* Unicode Chapter 13 : Plane 1 */ + Script_Deseret = 0x4b, + Script_Osmanya = 0x4c, + Script_Osmanya_Numeric = 0x4d, + /* Unicode Chapter 15 : Plane 1 */ + Script_MathAlpha = 0x4e, + /* Additional Currency Scripts */ + Script_Hebrew_Currency = 0x4f, + Script_Vietnamese_Currency = 0x50, + Script_Thai_Currency = 0x51, +}; #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT) @@ -157,15 +164,15 @@ typedef struct { OPENTYPE_TAG tag; CHAR tableType; - LPCVOID feature; + const void *feature; INT lookup_count; WORD *lookups; } LoadedFeature; typedef struct { OPENTYPE_TAG tag; - LPCVOID gsub_table; - LPCVOID gpos_table; + const void *gsub_table; + const void *gpos_table; BOOL features_initialized; INT feature_count; LoadedFeature *features; @@ -173,12 +180,13 @@ typedef struct { typedef struct { OPENTYPE_TAG tag; - LPCVOID gsub_table; - LPCVOID gpos_table; + const void *gsub_table; + const void *gpos_table; LoadedLanguage default_language; BOOL languages_initialized; - INT language_count; LoadedLanguage *languages; + SIZE_T languages_size; + SIZE_T language_count; } LoadedScript; typedef struct { @@ -193,14 +201,15 @@ typedef struct { BOOL sfnt; CacheGlyphPage *page[NUM_PAGES]; ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE]; - LPVOID GSUB_Table; - LPVOID GDEF_Table; - LPVOID CMAP_Table; - LPVOID CMAP_format12_Table; - LPVOID GPOS_Table; + void *GSUB_Table; + void *GDEF_Table; + void *CMAP_Table; + void *CMAP_format12_Table; + void *GPOS_Table; BOOL scripts_initialized; - INT script_count; LoadedScript *scripts; + SIZE_T scripts_size; + SIZE_T script_count; OPENTYPE_TAG userScript; OPENTYPE_TAG userLang; @@ -225,6 +234,21 @@ typedef struct { enum {lex_Halant, lex_Composed_Vowel, lex_Matra_post, lex_Matra_pre, lex_Matra_above, lex_Matra_below, lex_ZWJ, lex_ZWNJ, lex_NBSP, lex_Modifier, lex_Vowel, lex_Consonant, lex_Generic, lex_Ra, lex_Vedic, lex_Anudatta, lex_Nukta}; +static inline void * __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) +{ + return HeapAlloc(GetProcessHeap(), 0, size); +} + +static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t size) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); +} + +static inline BOOL heap_free(void *mem) +{ + return HeapFree(GetProcessHeap(), 0, mem); +} + static inline BOOL is_consonant( int type ) { return (type == lex_Ra || type == lex_Consonant); @@ -236,19 +260,20 @@ static inline unsigned short get_table_entry( const unsigned short *table, WCHAR } typedef int (*lexical_function)(WCHAR c); -typedef void (*reorder_function)(LPWSTR pwChar, IndicSyllable *syllable, lexical_function lex); +typedef void (*reorder_function)(WCHAR *chars, IndicSyllable *syllable, lexical_function lex); #define odd(x) ((x) & 1) #define BIDI_STRONG 1 #define BIDI_WEAK 2 #define BIDI_NEUTRAL 0 +BOOL usp10_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) DECLSPEC_HIDDEN; int USP10_FindGlyphInLogClust(const WORD* pwLogClust, int cChars, WORD target) DECLSPEC_HIDDEN; -BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s, - const SCRIPT_CONTROL *c, WORD *lpOutLevels, WORD *lpOutOverrides ) DECLSPEC_HIDDEN; -BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, - WORD* lpStrength) DECLSPEC_HIDDEN; +BOOL BIDI_DetermineLevels(const WCHAR *string, unsigned int count, const SCRIPT_STATE *s, + const SCRIPT_CONTROL *c, WORD *levels, WORD *overrides) DECLSPEC_HIDDEN; +BOOL BIDI_GetStrengths(const WCHAR *string, unsigned int count, + const SCRIPT_CONTROL *c, WORD *strength) DECLSPEC_HIDDEN; INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse) DECLSPEC_HIDDEN; INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse) DECLSPEC_HIDDEN; void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) DECLSPEC_HIDDEN; @@ -261,15 +286,21 @@ HRESULT SHAPE_GetFontScriptTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa HRESULT SHAPE_GetFontLanguageTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags) DECLSPEC_HIDDEN; HRESULT SHAPE_GetFontFeatureTags( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags) DECLSPEC_HIDDEN; -void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChars, IndicSyllable **syllables, int *syllable_count, lexical_function lexical_f, reorder_function reorder_f, BOOL modern) DECLSPEC_HIDDEN; -void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) DECLSPEC_HIDDEN; +void Indic_ReorderCharacters(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, WCHAR *input, unsigned int cChars, + IndicSyllable **syllables, int *syllable_count, lexical_function lexical_f, + reorder_function reorder_f, BOOL modern) DECLSPEC_HIDDEN; +void Indic_ParseSyllables(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *input, unsigned int cChar, + IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) DECLSPEC_HIDDEN; void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) DECLSPEC_HIDDEN; DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) DECLSPEC_HIDDEN; void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; -INT OpenType_apply_GSUB_lookup(LPCVOID table, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) DECLSPEC_HIDDEN; -INT OpenType_apply_GPOS_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) DECLSPEC_HIDDEN; +int OpenType_apply_GSUB_lookup(const void *table, unsigned int lookup_index, WORD *glyphs, + unsigned int glyph_index, int write_dir, int *glyph_count) DECLSPEC_HIDDEN; +unsigned int OpenType_apply_GPOS_lookup(const ScriptCache *psc, const OUTLINETEXTMETRICW *otm, + const LOGFONTW *logfont, const SCRIPT_ANALYSIS *analysis, int *advance, unsigned int lookup_index, + const WORD *glyphs, unsigned int glyph_index, unsigned int glyph_count, GOFFSET *goffset) DECLSPEC_HIDDEN; HRESULT OpenType_GetFontScriptTags(ScriptCache *psc, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags) DECLSPEC_HIDDEN; HRESULT OpenType_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pLanguageTags, int *pcTags) DECLSPEC_HIDDEN; HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, char tableType, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) DECLSPEC_HIDDEN; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 6d30be18b54..4d3a706bc5c 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -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-2.9 -reactos/dll/win32/usp10 # Synced to WineStaging-2.2 +reactos/dll/win32/usp10 # Synced to WineStaging-2.9 reactos/dll/win32/uxtheme # Forked reactos/dll/win32/vbscript # Synced to WineStaging-1.9.23 reactos/dll/win32/version # Synced to WineStaging-2.2