[USP10] Sync with Wine Staging 2.9. CORE-13362
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 4 Jun 2017 01:46:51 +0000 (01:46 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 4 Jun 2017 01:46:51 +0000 (01:46 +0000)
30e8768 usp10: Validate substition record sequence indices in GSUB_apply_ContextSubst().
ebe75cb usp10: Simplify the "sr_2" assignments in GSUB_apply_ContextSubst().
6c13170 usp10: Range check glyph counts in GSUB_apply_ContextSubst().
c5619be usp10: Validate positioning record sequence indices in GPOS_apply_ContextPos().
82d36ba usp10: Simplify the "pr_2" assignment in GPOS_apply_ContextPos().
1b02c1a usp10: Range check glyph counts in GPOS_apply_ContextPos().
d1ca880 usp10: Validate substition record sequence indices in GSUB_apply_ChainContextSubst().
34a9400 usp10: Validate positioning record sequence indices in GPOS_apply_ChainContextPos().
9694aeb usp10: Avoid special handling if the substitution count is 0 in GSUB_apply_ChainContextSubst().
f7b943e usp10: Range check glyph counts in GSUB_apply_ChainContextSubst().
24943fe usp10: Simplify the chaining context table assignments in GSUB_apply_ChainContextSubst().
02316e6 usp10: Rename the chaining context tables in GSUB_apply_ChainContextSubst() to something more descriptive.
0389768 usp10: Return early if the number of positioning operations is 0 in GPOS_apply_ChainContextPos().
7dfe9b9 usp10: Range check glyph counts in GPOS_apply_ChainContextPos().
f6c0146 usp10: Simplify the chaining context table assignments in GPOS_apply_ChainContextPos().
fb3ea0a usp10: Rename the chaining context tables in GPOS_apply_ChainContextPos() to something more descriptive.
04e5466 usp10: Handle invalid arguments in ScriptIsComplex().
4553871 usp10: Check if corresponding headers are present before accessing their feature lists in _initialize_feature_cache.
63bcfa3 usp10: Get rid of the code duplication between GSUB_initialize_feature_cache() and GPOS_expand_feature_cache().
9b0f3f1 usp10: Get rid of some code duplication in GPOS_expand_feature_cache().
0ffd5b4 usp10: Double the languages array size when growing it in GPOS_expand_language_cache().
218be44 usp10: Double the scripts array size when growing it in GPOS_expand_script_cache().
9a15753 usp10: Introduce a helper function to lookup a language in a LoadedScript structure.
2a0ffc9 usp10: Introduce a helper function to lookup a script in the script cache.
213d358 usp10: Avoid LPVOID.
1403087 usp10: Avoid LPCVOID.
a204e58 usp10: Avoid LPWSTR.
cdd47c3 usp10: Avoid LPCWSTR.
af617aa usp10: Avoid LPBYTE.
34c2f74 usp10: Avoid LPWORD.
ab8ec60 usp10: Avoid LPPOINT.
ba66b62 usp10: Avoid LPOUTLINETEXTMETRICW.
df21247 usp10: Make the script cache parameter to get_opentype_script() const.
c8f87ad usp10: Make the script cache parameter to GPOS_apply_MarkToBase() const.
cd9db34 usp10: Pass const metrics to GPOS_convert_design_units_to_device().
c3dc9ed usp10: Use heap_free() instead of HeapFree().
6a0e5bb usp10: Use heap_alloc() instead of HeapAlloc().
77e5a2f usp10: Use heap_alloc_zero() instead of HeapAlloc() with HEAP_ZERO_MEMORY.
3c704c2 usp10: Use bsearch() to lookup the script range in get_char_script().
a523b46 usp10: Introduce an enumeration for script types.
502d239 usp10: Do not fall back to presentation form B if the contextual feature exists in ContextualShape_Arabic().
f13dea5 usp10: Properly determine the glyph run direction when shaping Script_Arabic.
c94a5fd usp10: Take the script direction into account when applying OpenType features.
1727dd4 usp10: Use USP10_FindGlyphInLogClust() in UpdateClusters().
bab506e usp10: Use memmove() in GSUB_apply_LigatureSubst().
66df220 usp10: Make feature tables const.
b32fb23 usp10: Fix ScriptGetProperties spec file entry.
1a42ee3 usp10: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions.
892393b usp10: Filter out DeltaFormat == 0 too, valid range is [1, 3].
66dce1e usp10: Introduce an enumeration for GSUB lookup types.
fefd151 usp10: Ignore device tables with invalid delta format.
b6d541c usp10: Iterate in visual order in GPOS_apply_feature().
6fec9b1 usp10: Return the logical offset in GPOS_apply_lookup().
8d15667 usp10: Return the logical offset in GPOS_apply_ChainContextPos().
2210196 usp10: Return the logical offset in GPOS_apply_ContextPos().
6e84358 usp10: Return the logical offset in GPOS_apply_PairAdjustment().
61e8a38 usp10: Introduce an enumeration for GPOS lookup types.
4b22953 usp10: Properly get glyph widths for OpenType fonts in ScriptPlaceOpenType().

svn path=/trunk/; revision=74851

reactos/dll/win32/usp10/bidi.c
reactos/dll/win32/usp10/breaking.c
reactos/dll/win32/usp10/indic.c
reactos/dll/win32/usp10/opentype.c
reactos/dll/win32/usp10/shape.c
reactos/dll/win32/usp10/usp10.c
reactos/dll/win32/usp10/usp10.spec
reactos/dll/win32/usp10/usp10_internal.h
reactos/media/doc/README.WINE

index 37b09ba..a06ff8c 100644 (file)
@@ -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;
index a46b1e3..b6e3151 100644 (file)
@@ -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);
 }
index 380a635..fae5f43 100644 (file)
 
 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;
 
index b836803..018813d 100644 (file)
@@ -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);
+
+                        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: %i -> %i %i\n",l, SequenceIndex, lookupIndex);
-                        newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count);
+                        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)
+    if (searchingFor)
+    {
+        if (!(script = usp10_script_cache_get_script(psc, searchingFor)))
+            return USP_E_SCRIPT_NOT_IN_FONT;
+
+        *pScriptTags = script->tag;
+        *pcTags = 1;
+        return S_OK;
+    }
+
+    if (cMaxTags < *pcTags)
         rc = E_OUTOFMEMORY;
-    else if (searchingFor)
-        rc = USP_E_SCRIPT_NOT_IN_FONT;
 
-    for (i = 0; i < psc->script_count; i++)
+    cMaxTags = min(cMaxTags, psc->script_count);
+    for (i = 0; i < cMaxTags; ++i)
     {
-        if (i < cMaxTags)
-            pScriptTags[i] = psc->scripts[i].tag;
-
-        if (searchingFor)
-        {
-            if (searchingFor == psc->scripts[i].tag)
-            {
-                pScriptTags[0] = psc->scripts[i].tag;
-                *pcTags = 1;
-                rc = S_OK;
-                break;
-            }
-        }
+        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;
+    TRACE("table_type %#x, %u features.\n", table_type, count);
 
-        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);
+    if (!count)
+        return;
 
-            feature_list = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
+    if (!language->feature_count)
+        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 < 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;
-            }
-        }
+    for (i = 0; i < count; ++i)
+    {
+        const OT_FeatureRecord *record;
+        LoadedFeature *loaded_feature;
+        const OT_Feature *feature;
+
+        record = &feature_list->FeatureRecord[GET_BE_WORD(lang->FeatureIndex[i])];
+        feature = (const OT_Feature *)((const BYTE *)feature_list + GET_BE_WORD(record->Feature));
+
+        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 GPOS_expand_feature_cache(LPCVOID table, LoadedLanguage *language)
+static void _initialize_feature_cache(ScriptCache *psc, LoadedLanguage *language)
 {
-    int i, count;
-    const OT_LangSys *lang = language->gpos_table;
-    const GPOS_Header *header = (const GPOS_Header *)table;
+    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 (!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);
-
-    if (!count)
+    if (language->features_initialized)
         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;
-            }
-        }
-    }
-    else
+    if ((lang = language->gsub_table))
     {
-        language->features = HeapReAlloc(GetProcessHeap(),0,language->features, sizeof(LoadedFeature)*(language->feature_count + count));
-
-        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;
-
-            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;
+        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);
     }
-}
 
-static void _initialize_feature_cache(ScriptCache *psc, LoadedLanguage *language)
-{
-    if (!language->features_initialized)
+    if ((lang = language->gpos_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 *)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)
     {
index 74c7a38..169cf80 100644 (file)
@@ -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)
+    if (psa->fLogicalOrder && psa->fRTL)
     {
-        dirR = 1;
-        dirL = -1;
+        dirR = -1;
+        dirL = 1;
     }
     else
     {
-        dirR = -1;
-        dirL = 1;
+        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;
index f56d2a0..a563b85 100644 (file)
 
 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 (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);
+    if (!(range = bsearch(&ch, script_ranges, ARRAY_SIZE(script_ranges),
+            sizeof(*script_ranges), usp10_compare_script_range)))
+        return Script_Undefined;
 
-    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;
             }
index 7ffef41..4eb9e96 100644 (file)
@@ -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)
index fa14e51..da5f3fe 100644 (file)
             ( (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)
 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;
index 6d30be1..4d3a706 100644 (file)
@@ -189,7 +189,7 @@ reactos/dll/win32/twain_32            # Synced to WineStaging-1.9.11
 reactos/dll/win32/updspapi            # Synced to WineStaging-1.9.11
 reactos/dll/win32/url                 # Synced to WineStaging-1.9.11
 reactos/dll/win32/urlmon              # Synced to WineStaging-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