usp10: Add Oriya script.
[wine] / dlls / usp10 / shape.c
1 /*
2  * Implementation of Shaping for the Uniscribe Script Processor (usp10.dll)
3  *
4  * Copyright 2010 CodeWeavers, Aric Stewart
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "usp10.h"
29 #include "winternl.h"
30
31 #include "usp10_internal.h"
32
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
36
37 #define FIRST_ARABIC_CHAR 0x0600
38 #define LAST_ARABIC_CHAR  0x06ff
39
40 typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*,
41                                       WCHAR*, INT, WORD*, INT*, INT, WORD*);
42
43 static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
44 static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
45 static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
46 static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
47 static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
48 static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
49 static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
50 static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
51 static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust);
52
53
54 typedef VOID (*ShapeCharGlyphPropProc)( HDC , ScriptCache*, SCRIPT_ANALYSIS*, const WCHAR*, const INT, const WORD*, const INT, WORD*, SCRIPT_CHARPROP*, SCRIPT_GLYPHPROP*);
55
56 static void ShapeCharGlyphProp_Default( 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);
57 static void ShapeCharGlyphProp_Arabic( 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 );
58 static void ShapeCharGlyphProp_Thai( 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 );
59 static void ShapeCharGlyphProp_None( 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 );
60 static void ShapeCharGlyphProp_Tibet( 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 );
61 static void ShapeCharGlyphProp_Devanagari( 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 );
62 static void ShapeCharGlyphProp_Bengali( 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 );
63 static void ShapeCharGlyphProp_Gurmukhi( 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 );
64 static void ShapeCharGlyphProp_Gujarati( 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 );
65 static void ShapeCharGlyphProp_Oriya( 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 );
66
67 extern const unsigned short wine_shaping_table[];
68 extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4];
69
70 enum joining_types {
71     jtU,
72     jtT,
73     jtR,
74     jtL,
75     jtD,
76     jtC
77 };
78
79 enum joined_forms {
80     Xn=0,
81     Xr,
82     Xl,
83     Xm,
84     /* Syriac Alaph */
85     Afj,
86     Afn,
87     Afx
88 };
89
90 #ifdef WORDS_BIGENDIAN
91 #define GET_BE_WORD(x) (x)
92 #else
93 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
94 #endif
95
96 /* These are all structures needed for the GSUB table */
97 #define GSUB_TAG MS_MAKE_TAG('G', 'S', 'U', 'B')
98 #define GSUB_E_NOFEATURE -2
99 #define GSUB_E_NOGLYPH -1
100
101 typedef struct {
102     DWORD version;
103     WORD ScriptList;
104     WORD FeatureList;
105     WORD LookupList;
106 } GSUB_Header;
107
108 typedef struct {
109     CHAR ScriptTag[4];
110     WORD Script;
111 } GSUB_ScriptRecord;
112
113 typedef struct {
114     WORD ScriptCount;
115     GSUB_ScriptRecord ScriptRecord[1];
116 } GSUB_ScriptList;
117
118 typedef struct {
119     CHAR LangSysTag[4];
120     WORD LangSys;
121 } GSUB_LangSysRecord;
122
123 typedef struct {
124     WORD DefaultLangSys;
125     WORD LangSysCount;
126     GSUB_LangSysRecord LangSysRecord[1];
127 } GSUB_Script;
128
129 typedef struct {
130     WORD LookupOrder; /* Reserved */
131     WORD ReqFeatureIndex;
132     WORD FeatureCount;
133     WORD FeatureIndex[1];
134 } GSUB_LangSys;
135
136 typedef struct {
137     CHAR FeatureTag[4];
138     WORD Feature;
139 } GSUB_FeatureRecord;
140
141 typedef struct {
142     WORD FeatureCount;
143     GSUB_FeatureRecord FeatureRecord[1];
144 } GSUB_FeatureList;
145
146 typedef struct {
147     WORD FeatureParams; /* Reserved */
148     WORD LookupCount;
149     WORD LookupListIndex[1];
150 } GSUB_Feature;
151
152 typedef struct {
153     WORD LookupCount;
154     WORD Lookup[1];
155 } GSUB_LookupList;
156
157 typedef struct {
158     WORD LookupType;
159     WORD LookupFlag;
160     WORD SubTableCount;
161     WORD SubTable[1];
162 } GSUB_LookupTable;
163
164 typedef struct {
165     WORD CoverageFormat;
166     WORD GlyphCount;
167     WORD GlyphArray[1];
168 } GSUB_CoverageFormat1;
169
170 typedef struct {
171     WORD Start;
172     WORD End;
173     WORD StartCoverageIndex;
174 } GSUB_RangeRecord;
175
176 typedef struct {
177     WORD CoverageFormat;
178     WORD RangeCount;
179     GSUB_RangeRecord RangeRecord[1];
180 } GSUB_CoverageFormat2;
181
182 typedef struct {
183     WORD SubstFormat; /* = 1 */
184     WORD Coverage;
185     WORD DeltaGlyphID;
186 } GSUB_SingleSubstFormat1;
187
188 typedef struct {
189     WORD SubstFormat; /* = 2 */
190     WORD Coverage;
191     WORD GlyphCount;
192     WORD Substitute[1];
193 }GSUB_SingleSubstFormat2;
194
195 typedef struct {
196     WORD SubstFormat; /* = 1 */
197     WORD Coverage;
198     WORD LigSetCount;
199     WORD LigatureSet[1];
200 }GSUB_LigatureSubstFormat1;
201
202 typedef struct {
203     WORD LigatureCount;
204     WORD Ligature[1];
205 }GSUB_LigatureSet;
206
207 typedef struct{
208     WORD LigGlyph;
209     WORD CompCount;
210     WORD Component[1];
211 }GSUB_Ligature;
212
213 typedef struct{
214     WORD SequenceIndex;
215     WORD LookupListIndex;
216
217 }GSUB_SubstLookupRecord;
218
219 typedef struct{
220     WORD SubstFormat; /* = 1 */
221     WORD Coverage;
222     WORD ChainSubRuleSetCount;
223     WORD ChainSubRuleSet[1];
224 }GSUB_ChainContextSubstFormat1;
225
226 typedef struct {
227     WORD SubstFormat; /* = 3 */
228     WORD BacktrackGlyphCount;
229     WORD Coverage[1];
230 }GSUB_ChainContextSubstFormat3_1;
231
232 typedef struct{
233     WORD InputGlyphCount;
234     WORD Coverage[1];
235 }GSUB_ChainContextSubstFormat3_2;
236
237 typedef struct{
238     WORD LookaheadGlyphCount;
239     WORD Coverage[1];
240 }GSUB_ChainContextSubstFormat3_3;
241
242 typedef struct{
243     WORD SubstCount;
244     GSUB_SubstLookupRecord SubstLookupRecord[1];
245 }GSUB_ChainContextSubstFormat3_4;
246
247 typedef struct {
248     WORD SubstFormat; /* = 1 */
249     WORD Coverage;
250     WORD AlternateSetCount;
251     WORD AlternateSet[1];
252 } GSUB_AlternateSubstFormat1;
253
254 typedef struct{
255     WORD GlyphCount;
256     WORD Alternate[1];
257 } GSUB_AlternateSet;
258
259 /* These are all structures needed for the GDEF table */
260 #define GDEF_TAG MS_MAKE_TAG('G', 'D', 'E', 'F')
261
262 enum {BaseGlyph=1, LigatureGlyph, MarkGlyph, ComponentGlyph};
263
264 typedef struct {
265     DWORD Version;
266     WORD GlyphClassDef;
267     WORD AttachList;
268     WORD LigCaretList;
269     WORD MarkAttachClassDef;
270 } GDEF_Header;
271
272 typedef struct {
273     WORD ClassFormat;
274     WORD StartGlyph;
275     WORD GlyphCount;
276     WORD ClassValueArray[1];
277 } GDEF_ClassDefFormat1;
278
279 typedef struct {
280     WORD Start;
281     WORD End;
282     WORD Class;
283 } GDEF_ClassRangeRecord;
284
285 typedef struct {
286     WORD ClassFormat;
287     WORD ClassRangeCount;
288     GDEF_ClassRangeRecord ClassRangeRecord[1];
289 } GDEF_ClassDefFormat2;
290
291 static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count);
292
293 typedef struct tagVowelComponents
294 {
295     WCHAR base;
296     WCHAR parts[3];
297 } VowelComponents;
298
299 typedef struct tagConsonantComponents
300 {
301     WCHAR parts[3];
302     WCHAR output;
303 } ConsonantComponents;
304
305 /* the orders of joined_forms and contextual_features need to line up */
306 static const char* contextual_features[] =
307 {
308     "isol",
309     "fina",
310     "init",
311     "medi",
312     /* Syriac Alaph */
313     "med2",
314     "fin2",
315     "fin3"
316 };
317
318 static OPENTYPE_FEATURE_RECORD standard_features[] =
319 {
320     { MS_MAKE_TAG('l','i','g','a'), 1},
321     { MS_MAKE_TAG('c','l','i','g'), 1},
322 };
323
324 static OPENTYPE_FEATURE_RECORD arabic_features[] =
325 {
326     { MS_MAKE_TAG('r','l','i','g'), 1},
327     { MS_MAKE_TAG('c','a','l','t'), 1},
328     { MS_MAKE_TAG('l','i','g','a'), 1},
329     { MS_MAKE_TAG('d','l','i','g'), 1},
330     { MS_MAKE_TAG('c','s','w','h'), 1},
331     { MS_MAKE_TAG('m','s','e','t'), 1},
332 };
333
334 static const char* required_arabic_features[] =
335 {
336     "fina",
337     "init",
338     "medi",
339     "rlig",
340     NULL
341 };
342
343 static OPENTYPE_FEATURE_RECORD hebrew_features[] =
344 {
345     { MS_MAKE_TAG('d','l','i','g'), 1},
346 };
347
348 static OPENTYPE_FEATURE_RECORD syriac_features[] =
349 {
350     { MS_MAKE_TAG('r','l','i','g'), 1},
351     { MS_MAKE_TAG('c','a','l','t'), 1},
352     { MS_MAKE_TAG('l','i','g','a'), 1},
353     { MS_MAKE_TAG('d','l','i','g'), 1},
354 };
355
356 static const char* required_syriac_features[] =
357 {
358     "fina",
359     "fin2",
360     "fin3",
361     "init",
362     "medi",
363     "med2",
364     "rlig",
365     NULL
366 };
367
368 static OPENTYPE_FEATURE_RECORD sinhala_features[] =
369 {
370     /* Base forms */
371     { MS_MAKE_TAG('a','k','h','n'), 1},
372     { MS_MAKE_TAG('r','p','h','f'), 1},
373     { MS_MAKE_TAG('v','a','t','u'), 1},
374     { MS_MAKE_TAG('p','s','t','f'), 1},
375     /* Presentation forms */
376     { MS_MAKE_TAG('b','l','w','s'), 1},
377     { MS_MAKE_TAG('a','b','v','s'), 1},
378     { MS_MAKE_TAG('p','s','t','s'), 1},
379 };
380
381 static OPENTYPE_FEATURE_RECORD tibetan_features[] =
382 {
383     { MS_MAKE_TAG('a','b','v','s'), 1},
384     { MS_MAKE_TAG('b','l','w','s'), 1},
385 };
386
387 static OPENTYPE_FEATURE_RECORD thai_features[] =
388 {
389     { MS_MAKE_TAG('c','c','m','p'), 1},
390 };
391
392 static const char* required_lao_features[] =
393 {
394     "ccmp",
395     NULL
396 };
397
398 static const char* required_devanagari_features[] =
399 {
400     "nukt",
401     "akhn",
402     "rphf",
403     "blwf",
404     "half",
405     "vatu",
406     "pres",
407     "abvs",
408     "blws",
409     "psts",
410     "haln",
411     NULL
412 };
413
414 static OPENTYPE_FEATURE_RECORD devanagari_features[] =
415 {
416     /* Localized forms */
417     { MS_MAKE_TAG('l','o','c','l'), 1},
418     /* Base forms */
419     { MS_MAKE_TAG('n','u','k','t'), 1},
420     { MS_MAKE_TAG('a','k','h','n'), 1},
421     { MS_MAKE_TAG('r','p','h','f'), 1},
422     { MS_MAKE_TAG('r','k','r','f'), 1},
423     { MS_MAKE_TAG('b','l','w','f'), 1},
424     { MS_MAKE_TAG('h','a','l','f'), 1},
425     { MS_MAKE_TAG('v','a','t','u'), 1},
426     { MS_MAKE_TAG('c','j','c','t'), 1},
427     /* Presentation forms */
428     { MS_MAKE_TAG('p','r','e','s'), 1},
429     { MS_MAKE_TAG('a','b','v','s'), 1},
430     { MS_MAKE_TAG('b','l','w','s'), 1},
431     { MS_MAKE_TAG('p','s','t','s'), 1},
432     { MS_MAKE_TAG('h','a','l','n'), 1},
433     { MS_MAKE_TAG('c','a','l','t'), 1},
434 };
435
436 static const char* required_bengali_features[] =
437 {
438     "nukt",
439     "akhn",
440     "rphf",
441     "blwf",
442     "half",
443     "vatu",
444     "pstf",
445     "init",
446     "abvs",
447     "blws",
448     "psts",
449     "haln",
450     NULL
451 };
452
453 static OPENTYPE_FEATURE_RECORD bengali_features[] =
454 {
455     /* Localized forms */
456     { MS_MAKE_TAG('l','o','c','l'), 1},
457     /* Base forms */
458     { MS_MAKE_TAG('n','u','k','t'), 1},
459     { MS_MAKE_TAG('a','k','h','n'), 1},
460     { MS_MAKE_TAG('r','p','h','f'), 1},
461     { MS_MAKE_TAG('b','l','w','f'), 1},
462     { MS_MAKE_TAG('h','a','l','f'), 1},
463     { MS_MAKE_TAG('p','s','t','f'), 1},
464     { MS_MAKE_TAG('v','a','t','u'), 1},
465     { MS_MAKE_TAG('c','j','c','t'), 1},
466     /* Presentation forms */
467     { MS_MAKE_TAG('i','n','i','t'), 1},
468     { MS_MAKE_TAG('p','r','e','s'), 1},
469     { MS_MAKE_TAG('a','b','v','s'), 1},
470     { MS_MAKE_TAG('b','l','w','s'), 1},
471     { MS_MAKE_TAG('p','s','t','s'), 1},
472     { MS_MAKE_TAG('h','a','l','n'), 1},
473     { MS_MAKE_TAG('c','a','l','t'), 1},
474 };
475
476 static const char* required_gurmukhi_features[] =
477 {
478     "nukt",
479     "akhn",
480     "rphf",
481     "blwf",
482     "half",
483     "pstf",
484     "vatu",
485     "cjct",
486     "pres",
487     "abvs",
488     "blws",
489     "psts",
490     "haln",
491     "calt",
492     NULL
493 };
494
495 static OPENTYPE_FEATURE_RECORD gurmukhi_features[] =
496 {
497     /* Localized forms */
498     { MS_MAKE_TAG('l','o','c','l'), 1},
499     /* Base forms */
500     { MS_MAKE_TAG('n','u','k','t'), 1},
501     { MS_MAKE_TAG('a','k','h','n'), 1},
502     { MS_MAKE_TAG('r','p','h','f'), 1},
503     { MS_MAKE_TAG('b','l','w','f'), 1},
504     { MS_MAKE_TAG('h','a','l','f'), 1},
505     { MS_MAKE_TAG('p','s','t','f'), 1},
506     { MS_MAKE_TAG('v','a','t','u'), 1},
507     { MS_MAKE_TAG('c','j','c','t'), 1},
508     /* Presentation forms */
509     { MS_MAKE_TAG('p','r','e','s'), 1},
510     { MS_MAKE_TAG('a','b','v','s'), 1},
511     { MS_MAKE_TAG('b','l','w','s'), 1},
512     { MS_MAKE_TAG('p','s','t','s'), 1},
513     { MS_MAKE_TAG('h','a','l','n'), 1},
514     { MS_MAKE_TAG('c','a','l','t'), 1},
515 };
516
517 static const char* required_oriya_features[] =
518 {
519     "nukt",
520     "akhn",
521     "rphf",
522     "blwf",
523     "pstf",
524     "cjct",
525     "pres",
526     "abvs",
527     "blws",
528     "psts",
529     "haln",
530     "calt",
531     NULL
532 };
533
534 static OPENTYPE_FEATURE_RECORD oriya_features[] =
535 {
536     /* Localized forms */
537     { MS_MAKE_TAG('l','o','c','l'), 1},
538     /* Base forms */
539     { MS_MAKE_TAG('n','u','k','t'), 1},
540     { MS_MAKE_TAG('a','k','h','n'), 1},
541     { MS_MAKE_TAG('r','p','h','f'), 1},
542     { MS_MAKE_TAG('b','l','w','f'), 1},
543     { MS_MAKE_TAG('p','s','t','f'), 1},
544     { MS_MAKE_TAG('c','j','c','t'), 1},
545     /* Presentation forms */
546     { MS_MAKE_TAG('p','r','e','s'), 1},
547     { MS_MAKE_TAG('a','b','v','s'), 1},
548     { MS_MAKE_TAG('b','l','w','s'), 1},
549     { MS_MAKE_TAG('p','s','t','s'), 1},
550     { MS_MAKE_TAG('h','a','l','n'), 1},
551     { MS_MAKE_TAG('c','a','l','t'), 1},
552 };
553
554 typedef struct ScriptShapeDataTag {
555     TEXTRANGE_PROPERTIES   defaultTextRange;
556     const char**           requiredFeatures;
557     CHAR                   otTag[5];
558     CHAR                   newOtTag[5];
559     ContextualShapingProc  contextProc;
560     ShapeCharGlyphPropProc charGlyphPropProc;
561 } ScriptShapeData;
562
563 /* in order of scripts */
564 static const ScriptShapeData ShapingData[] =
565 {
566     {{ standard_features, 2}, NULL, "", "", NULL, NULL},
567     {{ standard_features, 2}, NULL, "latn", "", NULL, NULL},
568     {{ standard_features, 2}, NULL, "latn", "", NULL, NULL},
569     {{ standard_features, 2}, NULL, "latn", "", NULL, NULL},
570     {{ standard_features, 2}, NULL, "" , "", NULL, NULL},
571     {{ standard_features, 2}, NULL, "latn", "", NULL, NULL},
572     {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic},
573     {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic},
574     {{ hebrew_features, 1}, NULL, "hebr", "", NULL, NULL},
575     {{ syriac_features, 4}, required_syriac_features, "syrc", "", ContextualShape_Syriac, ShapeCharGlyphProp_None},
576     {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic},
577     {{ NULL, 0}, NULL, "thaa", "", NULL, ShapeCharGlyphProp_None},
578     {{ standard_features, 2}, NULL, "grek", "", NULL, NULL},
579     {{ standard_features, 2}, NULL, "cyrl", "", NULL, NULL},
580     {{ standard_features, 2}, NULL, "armn", "", NULL, NULL},
581     {{ standard_features, 2}, NULL, "geor", "", NULL, NULL},
582     {{ sinhala_features, 7}, NULL, "sinh", "", ContextualShape_Sinhala, NULL},
583     {{ tibetan_features, 2}, NULL, "tibt", "", NULL, ShapeCharGlyphProp_Tibet},
584     {{ tibetan_features, 2}, NULL, "tibt", "", NULL, ShapeCharGlyphProp_Tibet},
585     {{ tibetan_features, 2}, NULL, "phag", "", ContextualShape_Phags_pa, ShapeCharGlyphProp_Thai},
586     {{ thai_features, 1}, NULL, "thai", "", NULL, ShapeCharGlyphProp_Thai},
587     {{ thai_features, 1}, NULL, "thai", "", NULL, ShapeCharGlyphProp_Thai},
588     {{ thai_features, 1}, required_lao_features, "lao", "", NULL, ShapeCharGlyphProp_Thai},
589     {{ thai_features, 1}, required_lao_features, "lao", "", NULL, ShapeCharGlyphProp_Thai},
590     {{ devanagari_features, 15}, required_devanagari_features, "deva", "dev2", ContextualShape_Devanagari, ShapeCharGlyphProp_Devanagari},
591     {{ devanagari_features, 15}, required_devanagari_features, "deva", "dev2", ContextualShape_Devanagari, ShapeCharGlyphProp_Devanagari},
592     {{ bengali_features, 16}, required_bengali_features, "beng", "bng2", ContextualShape_Bengali, ShapeCharGlyphProp_Bengali},
593     {{ bengali_features, 16}, required_bengali_features, "beng", "bng2", ContextualShape_Bengali, ShapeCharGlyphProp_Bengali},
594     {{ gurmukhi_features, 15}, required_gurmukhi_features, "guru", "gur2", ContextualShape_Gurmukhi, ShapeCharGlyphProp_Gurmukhi},
595     {{ gurmukhi_features, 15}, required_gurmukhi_features, "guru", "gur2", ContextualShape_Gurmukhi, ShapeCharGlyphProp_Gurmukhi},
596     {{ devanagari_features, 15}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati},
597     {{ devanagari_features, 15}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati},
598     {{ devanagari_features, 15}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati},
599     {{ oriya_features, 13}, required_oriya_features, "orya", "ory2", ContextualShape_Oriya, ShapeCharGlyphProp_Oriya},
600     {{ oriya_features, 13}, required_oriya_features, "orya", "ory2", ContextualShape_Oriya, ShapeCharGlyphProp_Oriya},
601 };
602
603 static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph)
604 {
605     const GSUB_CoverageFormat1* cf1;
606
607     cf1 = table;
608
609     if (GET_BE_WORD(cf1->CoverageFormat) == 1)
610     {
611         int count = GET_BE_WORD(cf1->GlyphCount);
612         int i;
613         TRACE("Coverage Format 1, %i glyphs\n",count);
614         for (i = 0; i < count; i++)
615             if (glyph == GET_BE_WORD(cf1->GlyphArray[i]))
616                 return i;
617         return -1;
618     }
619     else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
620     {
621         const GSUB_CoverageFormat2* cf2;
622         int i;
623         int count;
624         cf2 = (const GSUB_CoverageFormat2*)cf1;
625
626         count = GET_BE_WORD(cf2->RangeCount);
627         TRACE("Coverage Format 2, %i ranges\n",count);
628         for (i = 0; i < count; i++)
629         {
630             if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start))
631                 return -1;
632             if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
633                 (glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
634             {
635                 return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
636                     glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
637             }
638         }
639         return -1;
640     }
641     else
642         ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
643
644     return -1;
645 }
646
647 static const GSUB_Script* GSUB_get_script_table( const GSUB_Header* header, const char* tag)
648 {
649     const GSUB_ScriptList *script;
650     const GSUB_Script *deflt = NULL;
651     int i;
652     script = (const GSUB_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList));
653
654     TRACE("%i scripts in this font\n",GET_BE_WORD(script->ScriptCount));
655     for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
656     {
657         const GSUB_Script *scr;
658         int offset;
659
660         offset = GET_BE_WORD(script->ScriptRecord[i].Script);
661         scr = (const GSUB_Script*)((const BYTE*)script + offset);
662
663         if (strncmp(script->ScriptRecord[i].ScriptTag, tag,4)==0)
664             return scr;
665         if (strncmp(script->ScriptRecord[i].ScriptTag, "dflt",4)==0)
666             deflt = scr;
667     }
668     return deflt;
669 }
670
671 static const GSUB_LangSys* GSUB_get_lang_table( const GSUB_Script* script, const char* tag)
672 {
673     int i;
674     int offset;
675     const GSUB_LangSys *Lang;
676
677     TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
678
679     for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
680     {
681         offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
682         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
683
684         if ( strncmp(script->LangSysRecord[i].LangSysTag,tag,4)==0)
685             return Lang;
686     }
687     offset = GET_BE_WORD(script->DefaultLangSys);
688     if (offset)
689     {
690         Lang = (const GSUB_LangSys*)((const BYTE*)script + offset);
691         return Lang;
692     }
693     return NULL;
694 }
695
696 static const GSUB_Feature * GSUB_get_feature(const GSUB_Header *header, const GSUB_LangSys *lang, const char* tag)
697 {
698     int i;
699     const GSUB_FeatureList *feature;
700     feature = (const GSUB_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
701
702     TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
703     for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
704     {
705         int index = GET_BE_WORD(lang->FeatureIndex[i]);
706         if (strncmp(feature->FeatureRecord[index].FeatureTag,tag,4)==0)
707         {
708             const GSUB_Feature *feat;
709             feat = (const GSUB_Feature*)((const BYTE*)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
710             return feat;
711         }
712     }
713     return NULL;
714 }
715
716 static INT GSUB_apply_SingleSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
717 {
718     int j;
719     TRACE("Single Substitution Subtable\n");
720
721     for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
722     {
723         int offset;
724         const GSUB_SingleSubstFormat1 *ssf1;
725         offset = GET_BE_WORD(look->SubTable[j]);
726         ssf1 = (const GSUB_SingleSubstFormat1*)((const BYTE*)look+offset);
727         if (GET_BE_WORD(ssf1->SubstFormat) == 1)
728         {
729             int offset = GET_BE_WORD(ssf1->Coverage);
730             TRACE("  subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
731             if (GSUB_is_glyph_covered((const BYTE*)ssf1+offset, glyphs[glyph_index]) != -1)
732             {
733                 TRACE("  Glyph 0x%x ->",glyphs[glyph_index]);
734                 glyphs[glyph_index] = glyphs[glyph_index] + GET_BE_WORD(ssf1->DeltaGlyphID);
735                 TRACE(" 0x%x\n",glyphs[glyph_index]);
736                 return glyph_index + 1;
737             }
738         }
739         else
740         {
741             const GSUB_SingleSubstFormat2 *ssf2;
742             INT index;
743             INT offset;
744
745             ssf2 = (const GSUB_SingleSubstFormat2 *)ssf1;
746             offset = GET_BE_WORD(ssf1->Coverage);
747             TRACE("  subtype 2,  glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
748             index = GSUB_is_glyph_covered((const BYTE*)ssf2+offset, glyphs[glyph_index]);
749             TRACE("  Coverage index %i\n",index);
750             if (index != -1)
751             {
752                 if (glyphs[glyph_index] == GET_BE_WORD(ssf2->Substitute[index]))
753                     return GSUB_E_NOGLYPH;
754
755                 TRACE("    Glyph is 0x%x ->",glyphs[glyph_index]);
756                 glyphs[glyph_index] = GET_BE_WORD(ssf2->Substitute[index]);
757                 TRACE("0x%x\n",glyphs[glyph_index]);
758                 return glyph_index + 1;
759             }
760         }
761     }
762     return GSUB_E_NOGLYPH;
763 }
764
765 static INT GSUB_apply_AlternateSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
766 {
767     int j;
768     TRACE("Alternate Substitution Subtable\n");
769
770     for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
771     {
772         int offset;
773         const GSUB_AlternateSubstFormat1 *asf1;
774         INT index;
775
776         offset = GET_BE_WORD(look->SubTable[j]);
777         asf1 = (const GSUB_AlternateSubstFormat1*)((const BYTE*)look+offset);
778         offset = GET_BE_WORD(asf1->Coverage);
779
780         index = GSUB_is_glyph_covered((const BYTE*)asf1+offset, glyphs[glyph_index]);
781         if (index != -1)
782         {
783             const GSUB_AlternateSet *as;
784             offset =  GET_BE_WORD(asf1->AlternateSet[index]);
785             as = (const GSUB_AlternateSet*)((const BYTE*)asf1+offset);
786             FIXME("%i alternates, picking index 0\n",GET_BE_WORD(as->GlyphCount));
787             if (glyphs[glyph_index] == GET_BE_WORD(as->Alternate[0]))
788                 return GSUB_E_NOGLYPH;
789
790             TRACE("  Glyph 0x%x ->",glyphs[glyph_index]);
791             glyphs[glyph_index] = GET_BE_WORD(as->Alternate[0]);
792             TRACE(" 0x%x\n",glyphs[glyph_index]);
793             return glyph_index + 1;
794         }
795     }
796     return GSUB_E_NOGLYPH;
797 }
798
799 static INT GSUB_apply_LigatureSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
800 {
801     int j;
802
803     TRACE("Ligature Substitution Subtable\n");
804     for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
805     {
806         const GSUB_LigatureSubstFormat1 *lsf1;
807         int offset,index;
808
809         offset = GET_BE_WORD(look->SubTable[j]);
810         lsf1 = (const GSUB_LigatureSubstFormat1*)((const BYTE*)look+offset);
811         offset = GET_BE_WORD(lsf1->Coverage);
812         index = GSUB_is_glyph_covered((const BYTE*)lsf1+offset, glyphs[glyph_index]);
813         TRACE("  Coverage index %i\n",index);
814         if (index != -1)
815         {
816             const GSUB_LigatureSet *ls;
817             int k, count;
818
819             offset = GET_BE_WORD(lsf1->LigatureSet[index]);
820             ls = (const GSUB_LigatureSet*)((const BYTE*)lsf1+offset);
821             count = GET_BE_WORD(ls->LigatureCount);
822             TRACE("  LigatureSet has %i members\n",count);
823             for (k = 0; k < count; k++)
824             {
825                 const GSUB_Ligature *lig;
826                 int CompCount,l,CompIndex;
827
828                 offset = GET_BE_WORD(ls->Ligature[k]);
829                 lig = (const GSUB_Ligature*)((const BYTE*)ls+offset);
830                 CompCount = GET_BE_WORD(lig->CompCount) - 1;
831                 CompIndex = glyph_index+write_dir;
832                 for (l = 0; l < CompCount && CompIndex >= 0 && CompIndex < *glyph_count; l++)
833                 {
834                     int CompGlyph;
835                     CompGlyph = GET_BE_WORD(lig->Component[l]);
836                     if (CompGlyph != glyphs[CompIndex])
837                         break;
838                     CompIndex += write_dir;
839                 }
840                 if (l == CompCount)
841                 {
842                     int replaceIdx = glyph_index;
843                     if (write_dir < 0)
844                         replaceIdx = glyph_index - CompCount;
845
846                     TRACE("    Glyph is 0x%x (+%i) ->",glyphs[glyph_index],CompCount);
847                     glyphs[replaceIdx] = GET_BE_WORD(lig->LigGlyph);
848                     TRACE("0x%x\n",glyphs[replaceIdx]);
849                     if (CompCount > 0)
850                     {
851                         int j;
852                         for (j = replaceIdx + 1; j < *glyph_count; j++)
853                             glyphs[j] =glyphs[j+CompCount];
854                         *glyph_count = *glyph_count - CompCount;
855                     }
856                     return replaceIdx + 1;
857                 }
858             }
859         }
860     }
861     return GSUB_E_NOGLYPH;
862 }
863
864 static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
865 {
866     int j;
867     BOOL done = FALSE;
868
869     TRACE("Chaining Contextual Substitution Subtable\n");
870     for (j = 0; j < GET_BE_WORD(look->SubTableCount) && !done; j++)
871     {
872         const GSUB_ChainContextSubstFormat1 *ccsf1;
873         int offset;
874         int dirLookahead = write_dir;
875         int dirBacktrack = -1 * write_dir;
876
877         offset = GET_BE_WORD(look->SubTable[j]);
878         ccsf1 = (const GSUB_ChainContextSubstFormat1*)((const BYTE*)look+offset);
879         if (GET_BE_WORD(ccsf1->SubstFormat) == 1)
880         {
881             FIXME("  TODO: subtype 1 (Simple context glyph substitution)\n");
882             return -1;
883         }
884         else if (GET_BE_WORD(ccsf1->SubstFormat) == 2)
885         {
886             FIXME("  TODO: subtype 2 (Class-based Chaining Context Glyph Substitution)\n");
887             return -1;
888         }
889         else if (GET_BE_WORD(ccsf1->SubstFormat) == 3)
890         {
891             int k;
892             int indexGlyphs;
893             const GSUB_ChainContextSubstFormat3_1 *ccsf3_1;
894             const GSUB_ChainContextSubstFormat3_2 *ccsf3_2;
895             const GSUB_ChainContextSubstFormat3_3 *ccsf3_3;
896             const GSUB_ChainContextSubstFormat3_4 *ccsf3_4;
897             int newIndex = glyph_index;
898
899             ccsf3_1 = (const GSUB_ChainContextSubstFormat3_1 *)ccsf1;
900
901             TRACE("  subtype 3 (Coverage-based Chaining Context Glyph Substitution)\n");
902
903             for (k = 0; k < GET_BE_WORD(ccsf3_1->BacktrackGlyphCount); k++)
904             {
905                 offset = GET_BE_WORD(ccsf3_1->Coverage[k]);
906                 if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirBacktrack * (k+1))]) == -1)
907                     break;
908             }
909             if (k != GET_BE_WORD(ccsf3_1->BacktrackGlyphCount))
910                 return -1;
911             TRACE("Matched Backtrack\n");
912
913             ccsf3_2 = (const GSUB_ChainContextSubstFormat3_2 *)(((LPBYTE)ccsf1)+sizeof(GSUB_ChainContextSubstFormat3_1) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)-1)));
914
915             indexGlyphs = GET_BE_WORD(ccsf3_2->InputGlyphCount);
916             for (k = 0; k < indexGlyphs; k++)
917             {
918                 offset = GET_BE_WORD(ccsf3_2->Coverage[k]);
919                 if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (write_dir * k)]) == -1)
920                     break;
921             }
922             if (k != indexGlyphs)
923                 return -1;
924             TRACE("Matched IndexGlyphs\n");
925
926             ccsf3_3 = (const GSUB_ChainContextSubstFormat3_3 *)(((LPBYTE)ccsf3_2)+sizeof(GSUB_ChainContextSubstFormat3_2) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_2->InputGlyphCount)-1)));
927
928             for (k = 0; k < GET_BE_WORD(ccsf3_3->LookaheadGlyphCount); k++)
929             {
930                 offset = GET_BE_WORD(ccsf3_3->Coverage[k]);
931                 if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k))]) == -1)
932                     break;
933             }
934             if (k != GET_BE_WORD(ccsf3_3->LookaheadGlyphCount))
935                 return -1;
936             TRACE("Matched LookAhead\n");
937
938             ccsf3_4 = (const GSUB_ChainContextSubstFormat3_4 *)(((LPBYTE)ccsf3_3)+sizeof(GSUB_ChainContextSubstFormat3_3) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)-1)));
939
940             for (k = 0; k < GET_BE_WORD(ccsf3_4->SubstCount); k++)
941             {
942                 int lookupIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].LookupListIndex);
943                 int SequenceIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].SequenceIndex) * write_dir;
944
945                 TRACE("SUBST: %i -> %i %i\n",k, SequenceIndex, lookupIndex);
946                 newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count);
947                 if (newIndex == -1)
948                 {
949                     ERR("Chain failed to generate a glyph\n");
950                     return -1;
951                 }
952             }
953             return newIndex + 1;
954         }
955     }
956     return -1;
957 }
958
959 static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
960 {
961     int offset;
962     const GSUB_LookupTable *look;
963
964     offset = GET_BE_WORD(lookup->Lookup[lookup_index]);
965     look = (const GSUB_LookupTable*)((const BYTE*)lookup + offset);
966     TRACE("type %i, flag %x, subtables %i\n",GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
967     switch(GET_BE_WORD(look->LookupType))
968     {
969         case 1:
970             return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count);
971         case 3:
972             return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir, glyph_count);
973         case 4:
974             return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir, glyph_count);
975         case 6:
976             return GSUB_apply_ChainContextSubst(lookup, look, glyphs, glyph_index, write_dir, glyph_count);
977         default:
978             FIXME("We do not handle SubType %i\n",GET_BE_WORD(look->LookupType));
979     }
980     return GSUB_E_NOGLYPH;
981 }
982
983 static INT GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count)
984 {
985     int i;
986     int out_index = GSUB_E_NOGLYPH;
987     const GSUB_LookupList *lookup;
988
989     lookup = (const GSUB_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList));
990
991     TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
992     for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
993     {
994         out_index = GSUB_apply_lookup(lookup, GET_BE_WORD(feature->LookupListIndex[i]), glyphs, glyph_index, write_dir, glyph_count);
995         if (out_index != GSUB_E_NOGLYPH)
996             break;
997     }
998     if (out_index == GSUB_E_NOGLYPH)
999         TRACE("lookups found no glyphs\n");
1000     else
1001     {
1002         int out2;
1003         out2 = GSUB_apply_feature(header, feature, glyphs, glyph_index, write_dir, glyph_count);
1004         if (out2!=GSUB_E_NOGLYPH)
1005             out_index = out2;
1006     }
1007     return out_index;
1008 }
1009
1010 static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, BOOL tryNew)
1011 {
1012     UINT charset;
1013
1014     if (psc->userScript != 0)
1015     {
1016         if (tryNew && ShapingData[psa->eScript].newOtTag[0] != 0 && strncmp((char*)&psc->userScript,ShapingData[psa->eScript].otTag,4)==0)
1017             return ShapingData[psa->eScript].newOtTag;
1018         else
1019             return (char*)&psc->userScript;
1020     }
1021
1022     if (tryNew && ShapingData[psa->eScript].newOtTag[0] != 0)
1023         return ShapingData[psa->eScript].newOtTag;
1024
1025     if (ShapingData[psa->eScript].otTag[0] != 0)
1026         return ShapingData[psa->eScript].otTag;
1027
1028     /*
1029      * fall back to the font charset
1030      */
1031     charset = GetTextCharsetInfo(hdc, NULL, 0x0);
1032     switch (charset)
1033     {
1034         case ANSI_CHARSET: return "latn";
1035         case BALTIC_CHARSET: return "latn"; /* ?? */
1036         case CHINESEBIG5_CHARSET: return "hani";
1037         case EASTEUROPE_CHARSET: return "latn"; /* ?? */
1038         case GB2312_CHARSET: return "hani";
1039         case GREEK_CHARSET: return "grek";
1040         case HANGUL_CHARSET: return "hang";
1041         case RUSSIAN_CHARSET: return "cyrl";
1042         case SHIFTJIS_CHARSET: return "kana";
1043         case TURKISH_CHARSET: return "latn"; /* ?? */
1044         case VIETNAMESE_CHARSET: return "latn";
1045         case JOHAB_CHARSET: return "latn"; /* ?? */
1046         case ARABIC_CHARSET: return "arab";
1047         case HEBREW_CHARSET: return "hebr";
1048         case THAI_CHARSET: return "thai";
1049         default: return "latn";
1050     }
1051 }
1052
1053 static LPCVOID load_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const char* feat)
1054 {
1055     const GSUB_Feature *feature;
1056     int i;
1057
1058     for (i = 0; i <  psc->feature_count; i++)
1059         if (strncmp(psc->features[i].tag,feat,4)==0)
1060             return psc->features[i].feature;
1061
1062     feature = NULL;
1063
1064     if (psc->GSUB_Table)
1065     {
1066         const GSUB_Script *script;
1067         const GSUB_LangSys *language;
1068         int attempt = 2;
1069
1070         do
1071         {
1072             script = GSUB_get_script_table(psc->GSUB_Table, get_opentype_script(hdc,psa,psc,(attempt==2)));
1073             attempt--;
1074             if (script)
1075             {
1076                 if (psc->userLang != 0)
1077                     language = GSUB_get_lang_table(script,(char*)&psc->userLang);
1078                 else
1079                     language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
1080                 if (language)
1081                     feature = GSUB_get_feature(psc->GSUB_Table, language, feat);
1082             }
1083         } while(attempt && !feature);
1084
1085         /* try in the default (latin) table */
1086         if (!feature)
1087         {
1088             script = GSUB_get_script_table(psc->GSUB_Table, "latn");
1089             if (script)
1090             {
1091                 language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
1092                 if (language)
1093                     feature = GSUB_get_feature(psc->GSUB_Table, language, feat);
1094             }
1095         }
1096     }
1097
1098     TRACE("Feature %s located at %p\n",debugstr_an(feat,4),feature);
1099
1100     psc->feature_count++;
1101
1102     if (psc->features)
1103         psc->features = HeapReAlloc(GetProcessHeap(), 0, psc->features, psc->feature_count * sizeof(LoadedFeature));
1104     else
1105         psc->features = HeapAlloc(GetProcessHeap(), 0, psc->feature_count * sizeof(LoadedFeature));
1106
1107     lstrcpynA(psc->features[psc->feature_count - 1].tag, feat, 5);
1108     psc->features[psc->feature_count - 1].feature = feature;
1109     return feature;
1110 }
1111
1112 static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat)
1113 {
1114     const GSUB_Feature *feature;
1115
1116     feature = load_GSUB_feature(hdc, psa, psc, feat);
1117     if (!feature)
1118         return GSUB_E_NOFEATURE;
1119
1120     TRACE("applying feature %s\n",feat);
1121     return GSUB_apply_feature(psc->GSUB_Table, feature, glyphs, index, write_dir, glyph_count);
1122 }
1123
1124 static VOID *load_gsub_table(HDC hdc)
1125 {
1126     VOID* GSUB_Table = NULL;
1127     int length = GetFontData(hdc, GSUB_TAG , 0, NULL, 0);
1128     if (length != GDI_ERROR)
1129     {
1130         GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
1131         GetFontData(hdc, GSUB_TAG , 0, GSUB_Table, length);
1132         TRACE("Loaded GSUB table of %i bytes\n",length);
1133     }
1134     return GSUB_Table;
1135 }
1136
1137 static WORD GDEF_get_glyph_class(const GDEF_Header *header, WORD glyph)
1138 {
1139     int offset;
1140     WORD class = 0;
1141     const GDEF_ClassDefFormat1 *cf1;
1142
1143     if (!header)
1144         return 0;
1145
1146     offset = GET_BE_WORD(header->GlyphClassDef);
1147     if (!offset)
1148         return 0;
1149
1150     cf1 = (GDEF_ClassDefFormat1*)(((BYTE*)header)+offset);
1151     if (GET_BE_WORD(cf1->ClassFormat) == 1)
1152     {
1153         if (glyph >= GET_BE_WORD(cf1->StartGlyph))
1154         {
1155             int index = glyph - GET_BE_WORD(cf1->StartGlyph);
1156             if (index < GET_BE_WORD(cf1->GlyphCount))
1157                 class = GET_BE_WORD(cf1->ClassValueArray[index]);
1158         }
1159     }
1160     else if (GET_BE_WORD(cf1->ClassFormat) == 2)
1161     {
1162         const GDEF_ClassDefFormat2 *cf2 = (GDEF_ClassDefFormat2*)cf1;
1163         int i, top;
1164         top = GET_BE_WORD(cf2->ClassRangeCount);
1165         for (i = 0; i < top; i++)
1166         {
1167             if (glyph >= GET_BE_WORD(cf2->ClassRangeRecord[i].Start) &&
1168                 glyph <= GET_BE_WORD(cf2->ClassRangeRecord[i].End))
1169             {
1170                 class = GET_BE_WORD(cf2->ClassRangeRecord[i].Class);
1171                 break;
1172             }
1173         }
1174     }
1175     else
1176         ERR("Unknown Class Format %i\n",GET_BE_WORD(cf1->ClassFormat));
1177
1178     return class;
1179 }
1180
1181 static VOID *load_gdef_table(HDC hdc)
1182 {
1183     VOID* GDEF_Table = NULL;
1184     int length = GetFontData(hdc, GDEF_TAG , 0, NULL, 0);
1185     if (length != GDI_ERROR)
1186     {
1187         GDEF_Table = HeapAlloc(GetProcessHeap(),0,length);
1188         GetFontData(hdc, GDEF_TAG , 0, GDEF_Table, length);
1189         TRACE("Loaded GDEF table of %i bytes\n",length);
1190     }
1191     return GDEF_Table;
1192 }
1193
1194 static void GDEF_UpdateGlyphProps(HDC hdc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, SCRIPT_GLYPHPROP *pGlyphProp)
1195 {
1196     VOID* header = load_gdef_table(hdc);
1197     int i;
1198
1199     for (i = 0; i < cGlyphs; i++)
1200     {
1201         WORD class;
1202
1203         class = GDEF_get_glyph_class(header, pwGlyphs[i]);
1204
1205         switch (class)
1206         {
1207             case 0:
1208             case BaseGlyph:
1209                 pGlyphProp[i].sva.fClusterStart = 1;
1210                 pGlyphProp[i].sva.fDiacritic = 0;
1211                 pGlyphProp[i].sva.fZeroWidth = 0;
1212                 break;
1213             case LigatureGlyph:
1214                 pGlyphProp[i].sva.fClusterStart = 1;
1215                 pGlyphProp[i].sva.fDiacritic = 0;
1216                 pGlyphProp[i].sva.fZeroWidth = 0;
1217                 break;
1218             case MarkGlyph:
1219                 pGlyphProp[i].sva.fClusterStart = 0;
1220                 pGlyphProp[i].sva.fDiacritic = 1;
1221                 pGlyphProp[i].sva.fZeroWidth = 1;
1222                 break;
1223             case ComponentGlyph:
1224                 pGlyphProp[i].sva.fClusterStart = 0;
1225                 pGlyphProp[i].sva.fDiacritic = 0;
1226                 pGlyphProp[i].sva.fZeroWidth = 0;
1227                 break;
1228             default:
1229                 ERR("Unknown glyph class %i\n",class);
1230                 pGlyphProp[i].sva.fClusterStart = 1;
1231                 pGlyphProp[i].sva.fDiacritic = 0;
1232                 pGlyphProp[i].sva.fZeroWidth = 0;
1233         }
1234     }
1235 }
1236
1237 static void UpdateClustersFromGlyphProp(const int cGlyphs, const int cChars, WORD* pwLogClust, SCRIPT_GLYPHPROP *pGlyphProp)
1238 {
1239     int i;
1240
1241     for (i = 0; i < cGlyphs; i++)
1242     {
1243         if (!pGlyphProp[i].sva.fClusterStart)
1244         {
1245             int j;
1246             for (j = 0; j < cChars; j++)
1247             {
1248                 if (pwLogClust[j] == i)
1249                 {
1250                     int k = j;
1251                     while (!pGlyphProp[pwLogClust[k]].sva.fClusterStart && k >= 0 && k <cChars)
1252                         k-=1;
1253                     if (pGlyphProp[pwLogClust[k]].sva.fClusterStart)
1254                         pwLogClust[j] = pwLogClust[k];
1255                 }
1256             }
1257         }
1258     }
1259 }
1260
1261 static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int chars, WORD* pwLogClust )
1262 {
1263     if (changeCount == 0)
1264         return;
1265     else
1266     {
1267         int i;
1268         int target_glyph = nextIndex - 1;
1269         int target_index = -1;
1270         int replacing_glyph = -1;
1271         int changed = 0;
1272
1273         if (write_dir > 0)
1274             for (i = 0; i < chars; i++)
1275             {
1276                 if (pwLogClust[i] == target_glyph)
1277                 {
1278                     target_index = i;
1279                     break;
1280                 }
1281             }
1282         else
1283             for (i = chars - 1; i >= 0; i--)
1284             {
1285                 if (pwLogClust[i] == target_glyph)
1286                 {
1287                     target_index = i;
1288                     break;
1289                 }
1290             }
1291         if (target_index == -1)
1292         {
1293             ERR("Unable to find target glyph\n");
1294             return;
1295         }
1296
1297         if (changeCount < 0)
1298         {
1299             /* merge glyphs */
1300             for(i = target_index; i < chars && i >= 0; i+=write_dir)
1301             {
1302                 if (pwLogClust[i] == target_glyph)
1303                     continue;
1304                 if(pwLogClust[i] == replacing_glyph)
1305                     pwLogClust[i] = target_glyph;
1306                 else
1307                 {
1308                     changed--;
1309                     if (changed >= changeCount)
1310                     {
1311                         replacing_glyph = pwLogClust[i];
1312                         pwLogClust[i] = target_glyph;
1313                     }
1314                     else
1315                         break;
1316                 }
1317             }
1318         }
1319
1320         /* renumber trailing indexes*/
1321         for(i = target_index; i < chars && i >= 0; i+=write_dir)
1322         {
1323             if (pwLogClust[i] != target_glyph)
1324                 pwLogClust[i] += changeCount;
1325         }
1326     }
1327 }
1328
1329 static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, const char* feat, WORD *pwLogClust )
1330 {
1331     int i;
1332
1333     if (psc->GSUB_Table)
1334     {
1335         const GSUB_Feature *feature;
1336
1337         feature = load_GSUB_feature(hdc, psa, psc, feat);
1338         if (!feature)
1339             return GSUB_E_NOFEATURE;
1340
1341         i = 0;
1342         TRACE("applying feature %s\n",debugstr_an(feat,4));
1343         while(i < *pcGlyphs)
1344         {
1345                 INT nextIndex;
1346                 INT prevCount = *pcGlyphs;
1347                 nextIndex = GSUB_apply_feature(psc->GSUB_Table, feature, pwOutGlyphs, i, write_dir, pcGlyphs);
1348                 if (nextIndex > GSUB_E_NOGLYPH)
1349                 {
1350                     UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust);
1351                     i = nextIndex;
1352                 }
1353                 else
1354                     i++;
1355         }
1356         return *pcGlyphs;
1357     }
1358     return GSUB_E_NOFEATURE;
1359 }
1360
1361 static WCHAR neighbour_char(int i, int delta, const WCHAR* chars, INT cchLen)
1362 {
1363     if (i + delta < 0)
1364         return 0;
1365     if ( i+ delta >= cchLen)
1366         return 0;
1367
1368     i += delta;
1369
1370     return chars[i];
1371 }
1372
1373 static CHAR neighbour_joining_type(int i, int delta, const CHAR* context_type, INT cchLen, SCRIPT_ANALYSIS *psa)
1374 {
1375     if (i + delta < 0)
1376     {
1377         if (psa->fLinkBefore)
1378             return jtR;
1379         else
1380             return jtU;
1381     }
1382     if ( i+ delta >= cchLen)
1383     {
1384         if (psa->fLinkAfter)
1385             return jtL;
1386         else
1387             return jtU;
1388     }
1389
1390     i += delta;
1391
1392     if (context_type[i] == jtT)
1393         return neighbour_joining_type(i,delta,context_type,cchLen,psa);
1394     else
1395         return context_type[i];
1396 }
1397
1398 static inline BOOL right_join_causing(CHAR joining_type)
1399 {
1400     return (joining_type == jtL || joining_type == jtD || joining_type == jtC);
1401 }
1402
1403 static inline BOOL left_join_causing(CHAR joining_type)
1404 {
1405     return (joining_type == jtR || joining_type == jtD || joining_type == jtC);
1406 }
1407
1408 static inline BOOL word_break_causing(WCHAR chr)
1409 {
1410     /* we are working within a string of characters already guareented to
1411        be within one script, Syriac, so we do not worry about any characers
1412        other than the space character outside of that range */
1413     return (chr == 0 || chr == 0x20 );
1414 }
1415
1416 /*
1417  * ContextualShape_Arabic
1418  */
1419 static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
1420 {
1421     CHAR *context_type;
1422     INT *context_shape;
1423     INT dirR, dirL;
1424     int i;
1425
1426     if (*pcGlyphs != cChars)
1427     {
1428         ERR("Number of Glyphs and Chars need to match at the beginning\n");
1429         return;
1430     }
1431
1432     if (!psa->fLogicalOrder && psa->fRTL)
1433     {
1434         dirR = 1;
1435         dirL = -1;
1436     }
1437     else
1438     {
1439         dirR = -1;
1440         dirL = 1;
1441     }
1442
1443     if (!psc->GSUB_Table)
1444         psc->GSUB_Table = load_gsub_table(hdc);
1445
1446     context_type = HeapAlloc(GetProcessHeap(),0,cChars);
1447     context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars);
1448
1449     for (i = 0; i < cChars; i++)
1450         context_type[i] = wine_shaping_table[wine_shaping_table[pwcChars[i] >> 8] + (pwcChars[i] & 0xff)];
1451
1452     for (i = 0; i < cChars; i++)
1453     {
1454         if (context_type[i] == jtR && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1455             context_shape[i] = Xr;
1456         else if (context_type[i] == jtL && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
1457             context_shape[i] = Xl;
1458         else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)) && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1459             context_shape[i] = Xm;
1460         else if (context_type[i] == jtD && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1461             context_shape[i] = Xr;
1462         else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
1463             context_shape[i] = Xl;
1464         else
1465             context_shape[i] = Xn;
1466     }
1467
1468     /* Contextual Shaping */
1469     i = 0;
1470     while(i < *pcGlyphs)
1471     {
1472         BOOL shaped = FALSE;
1473
1474         if (psc->GSUB_Table)
1475         {
1476             INT nextIndex;
1477             INT prevCount = *pcGlyphs;
1478             nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
1479             if (nextIndex > GSUB_E_NOGLYPH)
1480             {
1481                 i = nextIndex;
1482                 UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
1483             }
1484             shaped = (nextIndex > GSUB_E_NOGLYPH);
1485         }
1486
1487         if (!shaped)
1488         {
1489             WORD newGlyph = pwOutGlyphs[i];
1490             if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <= LAST_ARABIC_CHAR)
1491             {
1492                 /* fall back to presentation form B */
1493                 WCHAR context_char = wine_shaping_forms[pwcChars[i] - FIRST_ARABIC_CHAR][context_shape[i]];
1494                 if (context_char != pwcChars[i] && GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000)
1495                     pwOutGlyphs[i] = newGlyph;
1496             }
1497             i++;
1498         }
1499     }
1500
1501     HeapFree(GetProcessHeap(),0,context_shape);
1502     HeapFree(GetProcessHeap(),0,context_type);
1503 }
1504
1505 /*
1506  * ContextualShape_Syriac
1507  */
1508
1509 #define ALAPH 0x710
1510 #define DALATH 0x715
1511 #define RISH 0x72A
1512
1513 static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
1514 {
1515     CHAR *context_type;
1516     INT *context_shape;
1517     INT dirR, dirL;
1518     int i;
1519
1520     if (*pcGlyphs != cChars)
1521     {
1522         ERR("Number of Glyphs and Chars need to match at the beginning\n");
1523         return;
1524     }
1525
1526     if (!psa->fLogicalOrder && psa->fRTL)
1527     {
1528         dirR = 1;
1529         dirL = -1;
1530     }
1531     else
1532     {
1533         dirR = -1;
1534         dirL = 1;
1535     }
1536
1537     if (!psc->GSUB_Table)
1538         psc->GSUB_Table = load_gsub_table(hdc);
1539
1540     if (!psc->GSUB_Table)
1541         return;
1542
1543     context_type = HeapAlloc(GetProcessHeap(),0,cChars);
1544     context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars);
1545
1546     for (i = 0; i < cChars; i++)
1547         context_type[i] = wine_shaping_table[wine_shaping_table[pwcChars[i] >> 8] + (pwcChars[i] & 0xff)];
1548
1549     for (i = 0; i < cChars; i++)
1550     {
1551         if (pwcChars[i] == ALAPH)
1552         {
1553             WCHAR rchar = neighbour_char(i,dirR,pwcChars,cChars);
1554
1555             if (left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
1556             context_shape[i] = Afj;
1557             else if ( rchar != DALATH && rchar != RISH &&
1558 !left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) &&
1559 word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
1560             context_shape[i] = Afn;
1561             else if ( (rchar == DALATH || rchar == RISH) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
1562             context_shape[i] = Afx;
1563             else
1564             context_shape[i] = Xn;
1565         }
1566         else if (context_type[i] == jtR &&
1567 right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1568             context_shape[i] = Xr;
1569         else if (context_type[i] == jtL && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
1570             context_shape[i] = Xl;
1571         else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)) && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1572             context_shape[i] = Xm;
1573         else if (context_type[i] == jtD && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
1574             context_shape[i] = Xr;
1575         else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
1576             context_shape[i] = Xl;
1577         else
1578             context_shape[i] = Xn;
1579     }
1580
1581     /* Contextual Shaping */
1582     i = 0;
1583     while(i < *pcGlyphs)
1584     {
1585         INT nextIndex;
1586         INT prevCount = *pcGlyphs;
1587         nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
1588         if (nextIndex > GSUB_E_NOGLYPH)
1589         {
1590             UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
1591             i = nextIndex;
1592         }
1593         else
1594             i++;
1595     }
1596
1597     HeapFree(GetProcessHeap(),0,context_shape);
1598     HeapFree(GetProcessHeap(),0,context_type);
1599 }
1600
1601 /*
1602  * ContextualShape_Phags_pa
1603  */
1604
1605 #define phags_pa_CANDRABINDU  0xA873
1606 #define phags_pa_START 0xA840
1607 #define phags_pa_END  0xA87F
1608
1609 static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
1610 {
1611     INT *context_shape;
1612     INT dirR, dirL;
1613     int i;
1614
1615     if (*pcGlyphs != cChars)
1616     {
1617         ERR("Number of Glyphs and Chars need to match at the beginning\n");
1618         return;
1619     }
1620
1621     if (!psa->fLogicalOrder && psa->fRTL)
1622     {
1623         dirR = 1;
1624         dirL = -1;
1625     }
1626     else
1627     {
1628         dirR = -1;
1629         dirL = 1;
1630     }
1631
1632     if (!psc->GSUB_Table)
1633         psc->GSUB_Table = load_gsub_table(hdc);
1634
1635     if (!psc->GSUB_Table)
1636         return;
1637
1638     context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars);
1639
1640     for (i = 0; i < cChars; i++)
1641     {
1642         if (pwcChars[i] >= phags_pa_START && pwcChars[i] <=  phags_pa_END)
1643         {
1644             WCHAR rchar = neighbour_char(i,dirR,pwcChars,cChars);
1645             WCHAR lchar = neighbour_char(i,dirL,pwcChars,cChars);
1646             BOOL jrchar = (rchar != phags_pa_CANDRABINDU && rchar >= phags_pa_START && rchar <=  phags_pa_END);
1647             BOOL jlchar = (lchar != phags_pa_CANDRABINDU && lchar >= phags_pa_START && lchar <=  phags_pa_END);
1648
1649             if (jrchar && jlchar)
1650                 context_shape[i] = Xm;
1651             else if (jrchar)
1652                 context_shape[i] = Xr;
1653             else if (jlchar)
1654                 context_shape[i] = Xl;
1655             else
1656                 context_shape[i] = Xn;
1657         }
1658         else
1659             context_shape[i] = -1;
1660     }
1661
1662     /* Contextual Shaping */
1663     i = 0;
1664     while(i < *pcGlyphs)
1665     {
1666         if (context_shape[i] >= 0)
1667         {
1668             INT nextIndex;
1669             INT prevCount = *pcGlyphs;
1670             nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
1671             if (nextIndex > GSUB_E_NOGLYPH)
1672             {
1673                 UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
1674                 i = nextIndex;
1675             }
1676             else
1677                 i++;
1678         }
1679         else
1680             i++;
1681     }
1682
1683     HeapFree(GetProcessHeap(),0,context_shape);
1684 }
1685
1686 static void ReplaceInsertChars(HDC hdc, INT cWalk, INT* pcChars, WCHAR *pwOutChars, const WCHAR *replacements)
1687 {
1688     int i;
1689
1690     /* Replace */
1691     pwOutChars[cWalk] = replacements[0];
1692     cWalk=cWalk+1;
1693
1694     /* Insert */
1695     for (i = 1; replacements[i] != 0x0000 && i < 3; i++)
1696     {
1697         int j;
1698         for (j = *pcChars; j > cWalk; j--)
1699             pwOutChars[j] = pwOutChars[j-1];
1700         *pcChars= *pcChars+1;
1701         pwOutChars[cWalk] = replacements[i];
1702         cWalk = cWalk+1;
1703     }
1704 }
1705
1706 static void DecomposeVowels(HDC hdc, WCHAR *pwOutChars, INT *pcChars, const VowelComponents vowels[])
1707 {
1708     int i;
1709     int cWalk;
1710
1711     for (cWalk = 0; cWalk < *pcChars; cWalk++)
1712     {
1713         for (i = 0; vowels[i].base != 0x0; i++)
1714         {
1715             if (pwOutChars[cWalk] == vowels[i].base)
1716             {
1717                 ReplaceInsertChars(hdc, cWalk, pcChars, pwOutChars, vowels[i].parts);
1718                 break;
1719             }
1720         }
1721     }
1722 }
1723
1724 static void ComposeConsonants(HDC hdc, WCHAR *pwOutChars, INT *pcChars, const ConsonantComponents consonants[])
1725 {
1726     int i;
1727     int cWalk;
1728
1729     for (cWalk = 0; cWalk < *pcChars; cWalk++)
1730     {
1731         for (i = 0; consonants[i].output!= 0x0; i++)
1732         {
1733             int j;
1734             for (j = 0; j + cWalk < *pcChars && consonants[i].parts[j]!=0x0; j++)
1735                 if (pwOutChars[cWalk+j] != consonants[i].parts[j])
1736                     break;
1737
1738             if (consonants[i].parts[j]==0x0) /* matched all */
1739             {
1740                 int k;
1741                 j--;
1742                 pwOutChars[cWalk] = consonants[i].output;
1743                 for(k = cWalk+1; k < *pcChars - j; k++)
1744                     pwOutChars[k] = pwOutChars[k+j];
1745                 *pcChars = *pcChars - j;
1746                 break;
1747             }
1748         }
1749         cWalk++;
1750     }
1751 }
1752
1753 static void Reorder_Ra_follows_base(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1754 {
1755     if (start != main && end > start+1 && lexical(pwChar[start]) == lex_Ra && lexical(pwChar[start+1]) == lex_Halant)
1756     {
1757         int j;
1758         WORD Ra = pwChar[start];
1759         WORD H = pwChar[start+1];
1760
1761         TRACE("Doing reorder of Ra to %i\n",main);
1762         for (j = start; j < main-1; j++)
1763             pwChar[j] = pwChar[j+2];
1764         pwChar[main-1] = Ra;
1765         pwChar[main] = H;
1766     }
1767 }
1768
1769 static void Reorder_Ra_follows_mantra_post(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1770 {
1771     if (start != main && end > start+1 && lexical(pwChar[start]) == lex_Ra && lexical(pwChar[start+1]) == lex_Halant)
1772     {
1773         int j,loc;
1774         WORD Ra = pwChar[start];
1775         WORD H = pwChar[start+1];
1776         for (loc = main; loc > end; loc++)
1777             if (lexical(pwChar[loc]) == lex_Mantra_post)
1778                 break;
1779         if (loc == end) loc = main;
1780
1781         TRACE("Doing reorder of Ra to %i\n",loc);
1782         for (j = start; j < loc-1; j++)
1783             pwChar[j] = pwChar[j+2];
1784         pwChar[loc-1] = Ra;
1785         pwChar[loc] = H;
1786     }
1787 }
1788
1789 static void Reorder_Mantra_precede_base(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1790 {
1791     int i;
1792
1793     /* reorder Mantras */
1794     if (end > main)
1795     {
1796         for (i = 1; i <= end-main; i++)
1797         {
1798             if (lexical(pwChar[main+i]) == lex_Mantra_pre)
1799             {
1800                 int j;
1801                 WCHAR c = pwChar[main+i];
1802                 TRACE("Doing reorder of %x %x\n",c,pwChar[main]);
1803                 for (j = main+i; j > main; j--)
1804                     pwChar[j] = pwChar[j-1];
1805                 pwChar[main] = c;
1806             }
1807         }
1808     }
1809 }
1810
1811 static void Reorder_Mantra_precede_syllable(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1812 {
1813     int i;
1814
1815     /* reorder Mantras */
1816     if (end > main)
1817     {
1818         for (i = 1; i <= end-main; i++)
1819         {
1820             if (lexical(pwChar[main+i]) == lex_Mantra_pre)
1821             {
1822                 int j;
1823                 WCHAR c = pwChar[main+i];
1824                 TRACE("Doing reorder of %x to %i\n",c,start);
1825                 for (j = main+i; j > start; j--)
1826                     pwChar[j] = pwChar[j-1];
1827                 pwChar[start] = c;
1828             }
1829         }
1830     }
1831 }
1832
1833 static void Reorder_Like_Sinhala(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1834 {
1835     TRACE("Syllable (%i..%i..%i)\n",start,main,end);
1836     if (start == main && main == end)  return;
1837
1838     main = Indic_FindBaseConsonant(pwChar, start, main, end, lexical);
1839     if (lexical(pwChar[main]) == lex_Vowel) return;
1840
1841     Reorder_Ra_follows_base(pwChar, start, main, end, lexical);
1842     Reorder_Mantra_precede_base(pwChar, start, main, end, lexical);
1843 }
1844
1845 static void Reorder_Like_Devanagari(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1846 {
1847     TRACE("Syllable (%i..%i..%i)\n",start,main,end);
1848     if (start == main && main == end)  return;
1849
1850     main = Indic_FindBaseConsonant(pwChar, start, main, end, lexical);
1851     if (lexical(pwChar[main]) == lex_Vowel) return;
1852
1853     Reorder_Ra_follows_mantra_post(pwChar, start, main, end, lexical);
1854     Reorder_Mantra_precede_syllable(pwChar, start, main, end, lexical);
1855 }
1856
1857 static void Reorder_Like_Bengali(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical)
1858 {
1859     TRACE("Syllable (%i..%i..%i)\n",start,main,end);
1860     if (start == main && main == end)  return;
1861
1862     main = Indic_FindBaseConsonant(pwChar, start, main, end, lexical);
1863     if (lexical(pwChar[main]) == lex_Vowel) return;
1864
1865     Reorder_Ra_follows_base(pwChar, start, main, end, lexical);
1866     Reorder_Mantra_precede_syllable(pwChar, start, main, end, lexical);
1867 }
1868
1869 static int sinhala_lex(WCHAR c)
1870 {
1871     switch (c)
1872     {
1873         case 0x0DCA: return lex_Halant;
1874         case 0x0DCF:
1875         case 0x0DDF:
1876         case 0x0DD8: return lex_Mantra_post;
1877         case 0x0DD9:
1878         case 0x0DDB: return lex_Mantra_pre;
1879         case 0x0DDA:
1880         case 0x0DDC: return lex_Composed_Vowel;
1881         case 0x200D: return lex_ZWJ;
1882         case 0x200C: return lex_ZWNJ;
1883         case 0x00A0: return lex_NBSP;
1884         default:
1885             if (c>=0x0D82 && c <=0x0D83) return lex_Modifier;
1886             else if (c>=0x0D85 && c <=0x0D96) return lex_Vowel;
1887             else if (c>=0x0D96 && c <=0x0DC6) return lex_Consonant;
1888             else if (c>=0x0DD0 && c <=0x0DD1) return lex_Mantra_post;
1889             else if (c>=0x0DD2 && c <=0x0DD3) return lex_Mantra_above;
1890             else if (c>=0x0DD4 && c <=0x0DD6) return lex_Mantra_below;
1891             else if (c>=0x0DDD && c <=0x0DDE) return lex_Composed_Vowel;
1892             else if (c>=0x0DF2 && c <=0x0DF3) return lex_Mantra_post;
1893             else return lex_Generic;
1894     }
1895 }
1896
1897 static const VowelComponents Sinhala_vowels[] = {
1898             {0x0DDA, {0x0DD9,0x0DCA,0x0}},
1899             {0x0DDC, {0x0DD9,0x0DCF,0x0}},
1900             {0x0DDD, {0x0DD9,0x0DCF,0x0DCA}},
1901             {0x0DDE, {0x0DD9,0x0DDF,0x0}},
1902             {0x0000, {0x0000,0x0000,0x0}}};
1903
1904 static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
1905 {
1906     int cCount = cChars;
1907     WCHAR *input;
1908
1909     if (*pcGlyphs != cChars)
1910     {
1911         ERR("Number of Glyphs and Chars need to match at the beginning\n");
1912         return;
1913     }
1914
1915     input = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * (cChars * 3));
1916
1917     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
1918
1919     /* Step 1:  Decompose multi part vowels */
1920     DecomposeVowels(hdc, input,  &cCount, Sinhala_vowels);
1921
1922     TRACE("New double vowel expanded string %s (%i)\n",debugstr_wn(input,cCount),cCount);
1923
1924     /* Step 2:  Reorder within Syllables */
1925     Indic_ReorderCharacters( input, cCount, sinhala_lex, Reorder_Like_Sinhala);
1926     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
1927
1928     /* Step 3:  Get glyphs */
1929     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
1930     *pcGlyphs = cCount;
1931
1932     HeapFree(GetProcessHeap(),0,input);
1933 }
1934
1935 static int devanagari_lex(WCHAR c)
1936 {
1937     switch (c)
1938     {
1939         case 0x0951:
1940         case 0x0952:
1941         case 0x0903: return lex_Modifier;
1942         case 0x0930: return lex_Ra;
1943         case 0x093C: return lex_Nukta;
1944         case 0x0940:
1945         case 0x093E: return lex_Mantra_post;
1946         case 0x093F: return lex_Mantra_pre;
1947         case 0x094D: return lex_Halant;
1948         case 0x0972: return lex_Vowel;
1949         case 0x200C: return lex_ZWNJ;
1950         case 0x200D: return lex_ZWJ;
1951         default:
1952             if (c>=0x0901 && c<=0x0902) return lex_Mantra_above;
1953             else if (c>=0x0904 && c<=0x0914) return lex_Vowel;
1954             else if (c>=0x0915 && c<=0x0939) return lex_Consonant;
1955             else if (c>=0x0941 && c<=0x0944) return lex_Mantra_below;
1956             else if (c>=0x0945 && c<=0x0948) return lex_Mantra_above;
1957             else if (c>=0x0949 && c<=0x094C) return lex_Mantra_post;
1958             else if (c>=0x0953 && c<=0x0954) return lex_Modifier;
1959             else if (c>=0x0958 && c<=0x095F) return lex_Consonant;
1960             else if (c>=0x0960 && c<=0x0961) return lex_Vowel;
1961             else if (c>=0x0962 && c<=0x0963) return lex_Mantra_below;
1962             else if (c>=0x097B && c<=0x097C) return lex_Consonant;
1963             else if (c>=0x097E && c<=0x097F) return lex_Consonant;
1964             else return lex_Generic;
1965     }
1966 }
1967
1968 static const ConsonantComponents Devanagari_consonants[] ={
1969     {{0x0928, 0x093C, 0x00000}, 0x0929},
1970     {{0x0930, 0x093C, 0x00000}, 0x0931},
1971     {{0x0933, 0x093C, 0x00000}, 0x0934},
1972     {{0x0915, 0x093C, 0x00000}, 0x0958},
1973     {{0x0916, 0x093C, 0x00000}, 0x0959},
1974     {{0x0917, 0x093C, 0x00000}, 0x095A},
1975     {{0x091C, 0x093C, 0x00000}, 0x095B},
1976     {{0x0921, 0x093C, 0x00000}, 0x095C},
1977     {{0x0922, 0x093C, 0x00000}, 0x095D},
1978     {{0x092B, 0x093C, 0x00000}, 0x095E},
1979     {{0x092F, 0x093C, 0x00000}, 0x095F}};
1980
1981 static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
1982 {
1983     int cCount = cChars;
1984     WCHAR *input;
1985
1986     if (*pcGlyphs != cChars)
1987     {
1988         ERR("Number of Glyphs and Chars need to match at the beginning\n");
1989         return;
1990     }
1991
1992     input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR));
1993     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
1994
1995     /* Step 1: Compose Consonant and Nukta */
1996     ComposeConsonants(hdc, input, &cCount, Devanagari_consonants);
1997     TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount);
1998
1999     /* Step 2: Reorder within Syllables */
2000     Indic_ReorderCharacters( input, cCount, devanagari_lex, Reorder_Like_Devanagari);
2001     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
2002     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
2003     *pcGlyphs = cCount;
2004
2005     HeapFree(GetProcessHeap(),0,input);
2006 }
2007
2008 static int bengali_lex(WCHAR c)
2009 {
2010     switch (c)
2011     {
2012         case 0x0981: return lex_Modifier;
2013         case 0x09AC:
2014         case 0x09AF:
2015         case 0x09CE: return lex_Consonant;
2016         case 0x09B0: return lex_Ra;
2017         case 0x09BC: return lex_Nukta;
2018         case 0x09BF: return lex_Mantra_pre;
2019         case 0x09D7:
2020         case 0x09BE:
2021         case 0x09C0: return lex_Mantra_post;
2022         case 0x09CD: return lex_Halant;
2023         case 0x200C: return lex_ZWNJ;
2024         case 0x200D: return lex_ZWJ;
2025         default:
2026             if (c>=0x0982 && c<=0x0983) return lex_Mantra_post;
2027             else if (c>=0x0985 && c<=0x0994) return lex_Vowel;
2028             else if (c>=0x0995 && c<=0x09B9) return lex_Consonant;
2029             else if (c>=0x09C1 && c<=0x09C4) return lex_Mantra_below;
2030             else if (c>=0x09C7 && c<=0x09C8) return lex_Mantra_pre;
2031             else if (c>=0x09DC && c<=0x09DF) return lex_Consonant;
2032             else if (c>=0x09E0 && c<=0x09E1) return lex_Vowel;
2033             else if (c>=0x09E2 && c<=0x09E3) return lex_Mantra_below;
2034             else if (c>=0x09F0 && c<=0x09F1) return lex_Consonant;
2035             else return lex_Generic;
2036     }
2037 }
2038
2039 static const VowelComponents Bengali_vowels[] = {
2040             {0x09CB, {0x09C7,0x09BE,0x0000}},
2041             {0x09CC, {0x09C7,0x09D7,0x0000}},
2042             {0x0000, {0x0000,0x0000,0x0000}}};
2043
2044 static const ConsonantComponents Bengali_consonants[] = {
2045             {{0x09A4,0x09CD,0x200D}, 0x09CE},
2046             {{0x09A1,0x09BC,0x0000}, 0x09DC},
2047             {{0x09A2,0x09BC,0x0000}, 0x09DD},
2048             {{0x09AF,0x09BC,0x0000}, 0x09DF},
2049             {{0x0000,0x0000,0x0000}, 0x0000}};
2050
2051 static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
2052 {
2053     int cCount = cChars;
2054     WCHAR *input;
2055
2056     if (*pcGlyphs != cChars)
2057     {
2058         ERR("Number of Glyphs and Chars need to match at the beginning\n");
2059         return;
2060     }
2061
2062     input = HeapAlloc(GetProcessHeap(), 0, (cChars * 2) * sizeof(WCHAR));
2063     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
2064
2065     /* Step 1: Decompose Vowels and Compose Consonents */
2066     DecomposeVowels(hdc, input,  &cCount, Bengali_vowels);
2067     ComposeConsonants(hdc, input, &cCount, Bengali_consonants);
2068     TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount);
2069
2070     /* Step 2: Reorder within Syllables */
2071     Indic_ReorderCharacters( input, cCount, bengali_lex, Reorder_Like_Bengali);
2072     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
2073     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
2074     *pcGlyphs = cCount;
2075
2076     HeapFree(GetProcessHeap(),0,input);
2077 }
2078
2079 static int gurmukhi_lex(WCHAR c)
2080 {
2081     switch (c)
2082     {
2083         case 0x0A2f: return lex_Consonant;
2084         case 0x0A30:
2085         case 0x0A35:
2086         case 0x0A39: return lex_Ra;
2087         case 0x0A3C: return lex_Nukta;
2088         case 0x0A3F: return lex_Mantra_pre;
2089         case 0x0A03:
2090         case 0x0A3E:
2091         case 0x0A40: return lex_Mantra_post;
2092         case 0x0A4D: return lex_Halant;
2093         case 0x0A70:
2094         case 0x0A71: return lex_Modifier;
2095         case 0x200C: return lex_ZWNJ;
2096         case 0x200D: return lex_ZWJ;
2097         default:
2098             if (c>=0x0A01 && c<=0x0A02) return lex_Modifier;
2099             else if (c>=0x0A05 && c<=0x0A14) return lex_Vowel;
2100             else if (c>=0x0A15 && c<=0x0A38) return lex_Consonant;
2101             else if (c>=0x0A41 && c<=0x0A42) return lex_Mantra_below;
2102             else if (c>=0x0A47 && c<=0x0A4C) return lex_Mantra_above;
2103             else if (c>=0x0A59 && c<=0x0A5E) return lex_Consonant;
2104             else return lex_Generic;
2105     }
2106 }
2107
2108 static const ConsonantComponents Gurmukhi_consonants[] = {
2109             {{0x0A32,0x0A3C,0x0000}, 0x0A33},
2110             {{0x0A38,0x0A3C,0x0000}, 0x0A36},
2111             {{0x0A16,0x0A3C,0x0000}, 0x0A59},
2112             {{0x0A17,0x0A3C,0x0000}, 0x0A5A},
2113             {{0x0A1C,0x0A3C,0x0000}, 0x0A5B},
2114             {{0x0A2B,0x0A3C,0x0000}, 0x0A5E},
2115             {{0x0000,0x0000,0x0000}, 0x0000}};
2116
2117 static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
2118 {
2119     int cCount = cChars;
2120     WCHAR *input;
2121
2122     if (*pcGlyphs != cChars)
2123     {
2124         ERR("Number of Glyphs and Chars need to match at the beginning\n");
2125         return;
2126     }
2127
2128     input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR));
2129     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
2130
2131     /* Step 1: Compose Consonents */
2132     ComposeConsonants(hdc, input, &cCount, Gurmukhi_consonants);
2133     TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount);
2134
2135     /* Step 2: Reorder within Syllables */
2136     Indic_ReorderCharacters( input, cCount, gurmukhi_lex, Reorder_Like_Bengali);
2137     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
2138     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
2139     *pcGlyphs = cCount;
2140
2141     HeapFree(GetProcessHeap(),0,input);
2142 }
2143
2144 static int gujarati_lex(WCHAR c)
2145 {
2146     switch (c)
2147     {
2148         case 0x0A83: return lex_Modifier;
2149         case 0x0AB0: return lex_Ra;
2150         case 0x0ABC: return lex_Nukta;
2151         case 0x0ABF: return lex_Mantra_pre;
2152         case 0x0ABE:
2153         case 0x0AC0: return lex_Mantra_post;
2154         case 0x0ACD: return lex_Halant;
2155         case 0x200C: return lex_ZWNJ;
2156         case 0x200D: return lex_ZWJ;
2157         default:
2158             if (c>=0x0A81 && c<=0x0A82) return lex_Modifier;
2159             else if (c>=0x0A85 && c<=0x0A94) return lex_Vowel;
2160             else if (c>=0x0A95 && c<=0x0AB9) return lex_Consonant;
2161             else if (c>=0x0AC1 && c<=0x0AC4) return lex_Mantra_below;
2162             else if (c>=0x0AC5 && c<=0x0AC8) return lex_Mantra_above;
2163             else if (c>=0x0AC9 && c<=0x0ACC) return lex_Mantra_post;
2164             else if (c>=0x0AE0 && c<=0x0AE1) return lex_Vowel;
2165             else if (c>=0x0AE2 && c<=0x0AE3) return lex_Mantra_below;
2166             else return lex_Generic;
2167     }
2168 }
2169
2170 static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
2171 {
2172     int cCount = cChars;
2173     WCHAR *input;
2174
2175     if (*pcGlyphs != cChars)
2176     {
2177         ERR("Number of Glyphs and Chars need to match at the beginning\n");
2178         return;
2179     }
2180
2181     input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR));
2182     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
2183
2184     /* Step 1: Reorder within Syllables */
2185     Indic_ReorderCharacters( input, cCount, gujarati_lex, Reorder_Like_Devanagari);
2186     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
2187     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
2188     *pcGlyphs = cCount;
2189
2190     HeapFree(GetProcessHeap(),0,input);
2191 }
2192
2193 static int oriya_lex(WCHAR c)
2194 {
2195     switch (c)
2196     {
2197         case 0x0B24:
2198         case 0x0B28:
2199         case 0x0B2F:
2200         case 0x0B5F:
2201         case 0x0B71:
2202         case 0x0B33: return lex_Consonant;
2203         case 0x0B30: return lex_Ra;
2204         case 0x0B3C: return lex_Nukta;
2205         case 0x0B3F:
2206         case 0x0B56: return lex_Mantra_above;
2207         case 0x0B3E:
2208         case 0x0B40: return lex_Mantra_post;
2209         case 0x0B47:
2210         case 0x0B57: return lex_Mantra_pre;
2211         case 0x0B4D: return lex_Halant;
2212         case 0x200C: return lex_ZWNJ;
2213         case 0x200D: return lex_ZWJ;
2214         default:
2215             if (c>=0x0B01 && c<=0x0B03) return lex_Modifier;
2216             else if (c>=0x0B05 && c<=0x0B14) return lex_Vowel;
2217             else if (c>=0x0B15 && c<=0x0B39) return lex_Consonant;
2218             else if (c>=0x0B2C && c<=0x0B2E) return lex_Consonant;
2219             else if (c>=0x0B32 && c<=0x0B33) return lex_Consonant;
2220             else if (c>=0x0B41 && c<=0x0B44) return lex_Mantra_below;
2221             else if (c>=0x0B48 && c<=0x0B4C) return lex_Composed_Vowel;
2222             else if (c>=0x0B5C && c<=0x0B5D) return lex_Consonant;
2223             else if (c>=0x0B60 && c<=0x0B61) return lex_Vowel;
2224             else if (c>=0x0B62 && c<=0x0B63) return lex_Mantra_below;
2225             else return lex_Generic;
2226     }
2227 }
2228
2229 static const VowelComponents Oriya_vowels[] = {
2230             {0x0B48, {0x0B47,0x0B56,0x0000}},
2231             {0x0B4B, {0x0B47,0x0B3E,0x0000}},
2232             {0x0B4C, {0x0B47,0x0B57,0x0000}},
2233             {0x0000, {0x0000,0x0000,0x0000}}};
2234
2235 static const ConsonantComponents Oriya_consonants[] = {
2236             {{0x0B21,0x0B3C,0x0000}, 0x0B5C},
2237             {{0x0B22,0x0B3C,0x0000}, 0x0B5D},
2238             {{0x0000,0x0000,0x0000}, 0x0000}};
2239
2240 static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
2241 {
2242     int cCount = cChars;
2243     WCHAR *input;
2244
2245     if (*pcGlyphs != cChars)
2246     {
2247         ERR("Number of Glyphs and Chars need to match at the beginning\n");
2248         return;
2249     }
2250
2251     input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR));
2252     memcpy(input, pwcChars, cChars * sizeof(WCHAR));
2253
2254     /* Step 1: Decompose Vowels and Compose Consonents */
2255     DecomposeVowels(hdc, input,  &cCount, Oriya_vowels);
2256     ComposeConsonants(hdc, input, &cCount, Oriya_consonants);
2257     TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount);
2258
2259     /* Step 2: Reorder within Syllables */
2260     Indic_ReorderCharacters( input, cCount, oriya_lex, Reorder_Like_Bengali);
2261     TRACE("reordered string %s\n",debugstr_wn(input,cCount));
2262     GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0);
2263     *pcGlyphs = cCount;
2264
2265     HeapFree(GetProcessHeap(),0,input);
2266 }
2267
2268 static void ShapeCharGlyphProp_Default( 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)
2269 {
2270     int i,k;
2271
2272     for (i = 0; i < cGlyphs; i++)
2273     {
2274         int char_index[20];
2275         int char_count = 0;
2276
2277         for (k = 0; k < cChars; k++)
2278         {
2279             if (pwLogClust[k] == i)
2280             {
2281                 char_index[char_count] = k;
2282                 char_count++;
2283             }
2284         }
2285
2286         if (char_count == 0)
2287         {
2288             FIXME("No chars in this glyph?  Must be an error\n");
2289             continue;
2290         }
2291
2292         if (char_count ==1 && pwcChars[char_index[0]] == 0x0020)  /* space */
2293         {
2294             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK;
2295             pCharProp[char_index[0]].fCanGlyphAlone = 1;
2296         }
2297         else
2298             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER;
2299     }
2300
2301     GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
2302     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2303 }
2304
2305 static void ShapeCharGlyphProp_Arabic( 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 )
2306 {
2307     int i,k;
2308     int initGlyph, finaGlyph;
2309     INT dirR, dirL;
2310     BYTE *spaces;
2311
2312     spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs);
2313     memset(spaces,0,cGlyphs);
2314
2315     if (!psa->fLogicalOrder && psa->fRTL)
2316     {
2317         initGlyph = cGlyphs-1;
2318         finaGlyph = 0;
2319         dirR = 1;
2320         dirL = -1;
2321     }
2322     else
2323     {
2324         initGlyph = 0;
2325         finaGlyph = cGlyphs-1;
2326         dirR = -1;
2327         dirL = 1;
2328     }
2329
2330     for (i = 0; i < cGlyphs; i++)
2331     {
2332         for (k = 0; k < cChars; k++)
2333             if (pwLogClust[k] == i)
2334             {
2335                 if (pwcChars[k] == 0x0020)
2336                     spaces[i] = 1;
2337             }
2338     }
2339
2340     for (i = 0; i < cGlyphs; i++)
2341     {
2342         int char_index[20];
2343         int char_count = 0;
2344         BOOL isInit, isFinal;
2345
2346         for (k = 0; k < cChars; k++)
2347         {
2348             if (pwLogClust[k] == i)
2349             {
2350                 char_index[char_count] = k;
2351                 char_count++;
2352             }
2353         }
2354
2355         isInit = (i == initGlyph || (i+dirR > 0 && i+dirR < cGlyphs && spaces[i+dirR]));
2356         isFinal = (i == finaGlyph || (i+dirL > 0 && i+dirL < cGlyphs && spaces[i+dirL]));
2357
2358         if (char_count == 0)
2359         {
2360             FIXME("No chars in this glyph?  Must be an error\n");
2361             continue;
2362         }
2363
2364         if (char_count == 1)
2365         {
2366             if (pwcChars[char_index[0]] == 0x0020)  /* space */
2367             {
2368                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BLANK;
2369                 pCharProp[char_index[0]].fCanGlyphAlone = 1;
2370             }
2371             else if (pwcChars[char_index[0]] == 0x0640)  /* kashida */
2372                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_KASHIDA;
2373             else if (pwcChars[char_index[0]] == 0x0633)  /* SEEN */
2374             {
2375                 if (!isInit && !isFinal)
2376                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_SEEN_M;
2377                 else if (isInit)
2378                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_SEEN;
2379                 else
2380                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2381             }
2382             else if (!isInit)
2383             {
2384                 if (pwcChars[char_index[0]] == 0x0628 ) /* BA */
2385                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BA;
2386                 else if (pwcChars[char_index[0]] == 0x0631 ) /* RA */
2387                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_RA;
2388                 else if (pwcChars[char_index[0]] == 0x0647 ) /* HA */
2389                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_HA;
2390                 else if ((pwcChars[char_index[0]] == 0x0627 || pwcChars[char_index[0]] == 0x0625 || pwcChars[char_index[0]] == 0x0623 || pwcChars[char_index[0]] == 0x0622) ) /* alef-like */
2391                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_ALEF;
2392                 else
2393                     pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2394             }
2395             else if (!isInit && !isFinal)
2396                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL;
2397             else
2398                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2399         }
2400         else if (char_count == 2)
2401         {
2402             if ((pwcChars[char_index[0]] == 0x0628 && pwcChars[char_index[1]]== 0x0631) ||  (pwcChars[char_index[0]] == 0x0631 && pwcChars[char_index[1]]== 0x0628)) /* BA+RA */
2403                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BARA;
2404             else if (!isInit)
2405                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL;
2406             else
2407                 pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2408         }
2409         else if (!isInit && !isFinal)
2410             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL;
2411         else
2412             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2413     }
2414
2415     GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
2416     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2417     HeapFree(GetProcessHeap(),0,spaces);
2418 }
2419
2420 static void ShapeCharGlyphProp_Thai( 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 )
2421 {
2422     int i,k;
2423     int finaGlyph;
2424     INT dirL;
2425     BYTE *spaces;
2426
2427     spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs);
2428     memset(spaces,0,cGlyphs);
2429
2430     if (!psa->fLogicalOrder && psa->fRTL)
2431     {
2432         finaGlyph = 0;
2433         dirL = -1;
2434     }
2435     else
2436     {
2437         finaGlyph = cGlyphs-1;
2438         dirL = 1;
2439     }
2440
2441     for (i = 0; i < cGlyphs; i++)
2442     {
2443         for (k = 0; k < cChars; k++)
2444             if (pwLogClust[k] == i)
2445             {
2446                 if (pwcChars[k] == 0x0020)
2447                     spaces[i] = 1;
2448             }
2449     }
2450
2451     for (i = 0; i < cGlyphs; i++)
2452     {
2453         int char_index[20];
2454         int char_count = 0;
2455
2456         for (k = 0; k < cChars; k++)
2457         {
2458             if (pwLogClust[k] == i)
2459             {
2460                 char_index[char_count] = k;
2461                 char_count++;
2462             }
2463         }
2464
2465         if (char_count == 0)
2466         {
2467             FIXME("No chars in this glyph?  Must be an error\n");
2468             continue;
2469         }
2470
2471         if (char_count ==1 && pwcChars[char_index[0]] == 0x0020)  /* space */
2472         {
2473             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER;
2474             pCharProp[char_index[0]].fCanGlyphAlone = 1;
2475         }
2476         else if (i == finaGlyph)
2477             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2478         else
2479             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER;
2480     }
2481
2482     HeapFree(GetProcessHeap(),0,spaces);
2483     GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
2484     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2485
2486     /* Do not allow justification between marks and their base */
2487     for (i = 0; i < cGlyphs; i++)
2488     {
2489         if (!pGlyphProp[i].sva.fClusterStart)
2490             pGlyphProp[i-dirL].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2491     }
2492 }
2493
2494 static void ShapeCharGlyphProp_None( 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)
2495 {
2496     int i,k;
2497
2498     for (i = 0; i < cGlyphs; i++)
2499     {
2500         int char_index[20];
2501         int char_count = 0;
2502
2503         for (k = 0; k < cChars; k++)
2504         {
2505             if (pwLogClust[k] == i)
2506             {
2507                 char_index[char_count] = k;
2508                 char_count++;
2509             }
2510         }
2511
2512         if (char_count == 0)
2513         {
2514             FIXME("No chars in this glyph?  Must be an error\n");
2515             continue;
2516         }
2517
2518         if (char_count ==1 && pwcChars[char_index[0]] == 0x0020)  /* space */
2519         {
2520             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER;
2521             pCharProp[char_index[0]].fCanGlyphAlone = 1;
2522         }
2523         else
2524             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2525     }
2526     GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
2527     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2528 }
2529
2530 static void ShapeCharGlyphProp_Tibet( 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)
2531 {
2532     int i,k;
2533
2534     for (i = 0; i < cGlyphs; i++)
2535     {
2536         int char_index[20];
2537         int char_count = 0;
2538
2539         for (k = 0; k < cChars; k++)
2540         {
2541             if (pwLogClust[k] == i)
2542             {
2543                 char_index[char_count] = k;
2544                 char_count++;
2545             }
2546         }
2547
2548         if (char_count == 0)
2549         {
2550             FIXME("No chars in this glyph?  Must be an error\n");
2551             continue;
2552         }
2553
2554         if (char_count ==1 && pwcChars[char_index[0]] == 0x0020)  /* space */
2555         {
2556             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK;
2557             pCharProp[char_index[0]].fCanGlyphAlone = 1;
2558         }
2559         else
2560             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2561     }
2562     GDEF_UpdateGlyphProps(hdc, pwGlyphs, cGlyphs, pwLogClust, pGlyphProp);
2563     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2564
2565     /* Tibeten script does not set sva.fDiacritic or sva.fZeroWidth */
2566     for (i = 0; i < cGlyphs; i++)
2567     {
2568         if (!pGlyphProp[i].sva.fClusterStart)
2569         {
2570             pGlyphProp[i].sva.fDiacritic = 0;
2571             pGlyphProp[i].sva.fZeroWidth = 0;
2572         }
2573     }
2574 }
2575
2576 static void ShapeCharGlyphProp_BaseIndic( 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, lexical_function lexical)
2577 {
2578     int i,k;
2579
2580     for (i = 0; i < cGlyphs; i++)
2581     {
2582         int char_index[20];
2583         int char_count = 0;
2584
2585         for (k = 0; k < cChars; k++)
2586         {
2587             if (pwLogClust[k] == i)
2588             {
2589                 char_index[char_count] = k;
2590                 char_count++;
2591             }
2592         }
2593
2594         if (char_count == 0)
2595         {
2596             FIXME("No chars in this glyph?  Must be an error\n");
2597             continue;
2598         }
2599
2600         if (char_count ==1 && pwcChars[char_index[0]] == 0x0020)  /* space */
2601         {
2602             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK;
2603             pCharProp[char_index[0]].fCanGlyphAlone = 1;
2604         }
2605         else
2606             pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE;
2607
2608         pGlyphProp[i].sva.fClusterStart = 0;
2609         for (k = 0; k < char_count && !pGlyphProp[i].sva.fClusterStart; k++)
2610             switch (lexical(pwcChars[char_index[k]]))
2611             {
2612                 case lex_Mantra_pre:
2613                 case lex_Mantra_post:
2614                 case lex_Mantra_above:
2615                 case lex_Mantra_below:
2616                 case lex_Modifier:
2617                     break;
2618                 default:
2619                     pGlyphProp[i].sva.fClusterStart = 1;
2620                     break;
2621             }
2622     }
2623     UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
2624 }
2625
2626 static void ShapeCharGlyphProp_Devanagari( 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 )
2627 {
2628     ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, devanagari_lex);
2629 }
2630
2631 static void ShapeCharGlyphProp_Bengali( 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 )
2632 {
2633     ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, bengali_lex);
2634 }
2635
2636 static void ShapeCharGlyphProp_Gurmukhi( 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 )
2637 {
2638     ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, gurmukhi_lex);
2639 }
2640
2641 static void ShapeCharGlyphProp_Gujarati( 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 )
2642 {
2643     ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, gujarati_lex);
2644 }
2645
2646 static void ShapeCharGlyphProp_Oriya( 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 )
2647 {
2648     ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, oriya_lex);
2649 }
2650
2651 void SHAPE_CharGlyphProp(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)
2652 {
2653     if (ShapingData[psa->eScript].charGlyphPropProc)
2654         ShapingData[psa->eScript].charGlyphPropProc(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp);
2655     else
2656         ShapeCharGlyphProp_Default(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp);
2657 }
2658
2659 void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
2660 {
2661     if (ShapingData[psa->eScript].contextProc)
2662         ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust);
2663 }
2664
2665 static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust)
2666 {
2667     int i;
2668     INT dirL;
2669
2670     if (!rpRangeProperties)
2671         return;
2672
2673     if (!psc->GSUB_Table)
2674         psc->GSUB_Table = load_gsub_table(hdc);
2675
2676     if (!psc->GSUB_Table)
2677         return;
2678
2679     if (!psa->fLogicalOrder && psa->fRTL)
2680         dirL = -1;
2681     else
2682         dirL = 1;
2683
2684     for (i = 0; i < rpRangeProperties->cotfRecords; i++)
2685     {
2686         if (rpRangeProperties->potfRecords[i].lParameter > 0)
2687         apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust);
2688     }
2689 }
2690
2691 void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust)
2692 {
2693 const TEXTRANGE_PROPERTIES *rpRangeProperties;
2694 rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange;
2695
2696     SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust);
2697 }
2698
2699 HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa)
2700 {
2701     const GSUB_Feature *feature;
2702     int i;
2703
2704     if (!ShapingData[psa->eScript].requiredFeatures)
2705         return S_OK;
2706
2707     if (!psc->GSUB_Table)
2708         psc->GSUB_Table = load_gsub_table(hdc);
2709
2710     /* we need to have at least one of the required features */
2711     i = 0;
2712     while (ShapingData[psa->eScript].requiredFeatures[i])
2713     {
2714         feature = load_GSUB_feature(hdc, psa, psc, ShapingData[psa->eScript].requiredFeatures[i]);
2715         if (feature)
2716             return S_OK;
2717         i++;
2718     }
2719
2720     return USP_E_SCRIPT_NOT_IN_FONT;
2721 }