ReactOS 0.4.15-dev-7788-g1ad9096
usp10.c
Go to the documentation of this file.
1/*
2 * Implementation of Uniscribe Script Processor (usp10.dll)
3 *
4 * Copyright 2005 Steven Edwards for CodeWeavers
5 * Copyright 2006 Hans Leidekker
6 * Copyright 2010 CodeWeavers, Aric Stewart
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 *
22 * Notes:
23 * Uniscribe allows for processing of complex scripts such as joining
24 * and filtering characters and bi-directional text with custom line breaks.
25 */
26
27#include <stdarg.h>
28#include <stdlib.h>
29#include <math.h>
30#ifdef __REACTOS__
31#include <wchar.h>
32#endif
33
34#include "windef.h"
35#include "winbase.h"
36#include "wingdi.h"
37#include "winuser.h"
38#include "winnls.h"
39#include "winreg.h"
40#include "usp10.h"
41
42#include "usp10_internal.h"
43
44#include "wine/debug.h"
45#include "wine/heap.h"
46
48
49static const struct usp10_script_range
50{
56}
58{
59 /* Basic Latin: U+0000–U+007A */
61 /* Latin-1 Supplement: U+0080–U+00FF */
62 /* Latin Extended-A: U+0100–U+017F */
63 /* Latin Extended-B: U+0180–U+024F */
64 /* IPA Extensions: U+0250–U+02AF */
65 /* Spacing Modifier Letters:U+02B0–U+02FF */
67 /* Combining Diacritical Marks : U+0300–U+036F */
68 { Script_Diacritical,0x300, 0x36f, 0, 0},
69 /* Greek: U+0370–U+03FF */
70 { Script_Greek, 0x370, 0x3ff, 0, 0},
71 /* Cyrillic: U+0400–U+04FF */
72 /* Cyrillic Supplement: U+0500–U+052F */
73 { Script_Cyrillic, 0x400, 0x52f, 0, 0},
74 /* Armenian: U+0530–U+058F */
75 { Script_Armenian, 0x530, 0x58f, 0, 0},
76 /* Hebrew: U+0590–U+05FF */
77 { Script_Hebrew, 0x590, 0x5ff, 0, 0},
78 /* Arabic: U+0600–U+06FF */
79 { Script_Arabic, 0x600, 0x6ef, Script_Arabic_Numeric, 0},
80 /* Defined by Windows */
81 { Script_Persian, 0x6f0, 0x6f9, 0, 0},
82 /* Continue Arabic: U+0600–U+06FF */
83 { Script_Arabic, 0x6fa, 0x6ff, 0, 0},
84 /* Syriac: U+0700–U+074F*/
85 { Script_Syriac, 0x700, 0x74f, 0, 0},
86 /* Arabic Supplement: U+0750–U+077F */
87 { Script_Arabic, 0x750, 0x77f, 0, 0},
88 /* Thaana: U+0780–U+07BF */
89 { Script_Thaana, 0x780, 0x7bf, 0, 0},
90 /* N’Ko: U+07C0–U+07FF */
91 { Script_NKo, 0x7c0, 0x7ff, 0, 0},
92 /* Devanagari: U+0900–U+097F */
94 /* Bengali: U+0980–U+09FF */
95 { Script_Bengali, 0x980, 0x9ff, Script_Bengali_Numeric, 0},
96 /* Gurmukhi: U+0A00–U+0A7F*/
97 { Script_Gurmukhi, 0xa00, 0xa7f, Script_Gurmukhi_Numeric, 0},
98 /* Gujarati: U+0A80–U+0AFF*/
99 { Script_Gujarati, 0xa80, 0xaff, Script_Gujarati_Numeric, 0},
100 /* Oriya: U+0B00–U+0B7F */
101 { Script_Oriya, 0xb00, 0xb7f, Script_Oriya_Numeric, 0},
102 /* Tamil: U+0B80–U+0BFF */
103 { Script_Tamil, 0xb80, 0xbff, Script_Tamil_Numeric, 0},
104 /* Telugu: U+0C00–U+0C7F */
105 { Script_Telugu, 0xc00, 0xc7f, Script_Telugu_Numeric, 0},
106 /* Kannada: U+0C80–U+0CFF */
107 { Script_Kannada, 0xc80, 0xcff, Script_Kannada_Numeric, 0},
108 /* Malayalam: U+0D00–U+0D7F */
109 { Script_Malayalam, 0xd00, 0xd7f, Script_Malayalam_Numeric, 0},
110 /* Sinhala: U+0D80–U+0DFF */
111 { Script_Sinhala, 0xd80, 0xdff, 0, 0},
112 /* Thai: U+0E00–U+0E7F */
113 { Script_Thai, 0xe00, 0xe7f, Script_Thai_Numeric, 0},
114 /* Lao: U+0E80–U+0EFF */
115 { Script_Lao, 0xe80, 0xeff, Script_Lao_Numeric, 0},
116 /* Tibetan: U+0F00–U+0FFF */
117 { Script_Tibetan, 0xf00, 0xfff, 0, 0},
118 /* Myanmar: U+1000–U+109F */
119 { Script_Myanmar, 0x1000, 0x109f, Script_Myanmar_Numeric, 0},
120 /* Georgian: U+10A0–U+10FF */
121 { Script_Georgian, 0x10a0, 0x10ff, 0, 0},
122 /* Hangul Jamo: U+1100–U+11FF */
123 { Script_Hangul, 0x1100, 0x11ff, 0, 0},
124 /* Ethiopic: U+1200–U+137F */
125 /* Ethiopic Extensions: U+1380–U+139F */
126 { Script_Ethiopic, 0x1200, 0x139f, 0, 0},
127 /* Cherokee: U+13A0–U+13FF */
128 { Script_Cherokee, 0x13a0, 0x13ff, 0, 0},
129 /* Canadian Aboriginal Syllabics: U+1400–U+167F */
130 { Script_Canadian, 0x1400, 0x167f, 0, 0},
131 /* Ogham: U+1680–U+169F */
132 { Script_Ogham, 0x1680, 0x169f, 0, 0},
133 /* Runic: U+16A0–U+16F0 */
134 { Script_Runic, 0x16a0, 0x16f0, 0, 0},
135 /* Khmer: U+1780–U+17FF */
136 { Script_Khmer, 0x1780, 0x17ff, Script_Khmer_Numeric, 0},
137 /* Mongolian: U+1800–U+18AF */
138 { Script_Mongolian, 0x1800, 0x18af, Script_Mongolian_Numeric, 0},
139 /* Canadian Aboriginal Syllabics Extended: U+18B0–U+18FF */
140 { Script_Canadian, 0x18b0, 0x18ff, 0, 0},
141 /* Tai Le: U+1950–U+197F */
142 { Script_Tai_Le, 0x1950, 0x197f, 0, 0},
143 /* New Tai Lue: U+1980–U+19DF */
145 /* Khmer Symbols: U+19E0–U+19FF */
146 { Script_Khmer, 0x19e0, 0x19ff, Script_Khmer_Numeric, 0},
147 /* Vedic Extensions: U+1CD0-U+1CFF */
148 { Script_Devanagari, 0x1cd0, 0x1cff, Script_Devanagari_Numeric, 0},
149 /* Phonetic Extensions: U+1D00–U+1DBF */
150 { Script_Latin, 0x1d00, 0x1dbf, 0, 0},
151 /* Combining Diacritical Marks Supplement: U+1DC0–U+1DFF */
152 { Script_Diacritical,0x1dc0, 0x1dff, 0, 0},
153 /* Latin Extended Additional: U+1E00–U+1EFF */
154 { Script_Latin, 0x1e00, 0x1eff, 0, 0},
155 /* Greek Extended: U+1F00–U+1FFF */
156 { Script_Greek, 0x1f00, 0x1fff, 0, 0},
157 /* General Punctuation: U+2000 –U+206f */
158 { Script_Latin, 0x2000, 0x206f, 0, 0},
159 /* Superscripts and Subscripts : U+2070 –U+209f */
160 /* Currency Symbols : U+20a0 –U+20cf */
161 { Script_Numeric2, 0x2070, 0x2070, 0, 0},
162 { Script_Latin, 0x2071, 0x2073, 0, 0},
163 { Script_Numeric2, 0x2074, 0x2079, 0, 0},
164 { Script_Latin, 0x207a, 0x207f, 0, 0},
165 { Script_Numeric2, 0x2080, 0x2089, 0, 0},
166 { Script_Latin, 0x208a, 0x20cf, 0, 0},
167 /* Letterlike Symbols : U+2100 –U+214f */
168 /* Number Forms : U+2150 –U+218f */
169 /* Arrows : U+2190 –U+21ff */
170 /* Mathematical Operators : U+2200 –U+22ff */
171 /* Miscellaneous Technical : U+2300 –U+23ff */
172 /* Control Pictures : U+2400 –U+243f */
173 /* Optical Character Recognition : U+2440 –U+245f */
174 /* Enclosed Alphanumerics : U+2460 –U+24ff */
175 /* Box Drawing : U+2500 –U+25ff */
176 /* Block Elements : U+2580 –U+259f */
177 /* Geometric Shapes : U+25a0 –U+25ff */
178 /* Miscellaneous Symbols : U+2600 –U+26ff */
179 /* Dingbats : U+2700 –U+27bf */
180 /* Miscellaneous Mathematical Symbols-A : U+27c0 –U+27ef */
181 /* Supplemental Arrows-A : U+27f0 –U+27ff */
182 { Script_Latin, 0x2100, 0x27ff, 0, 0},
183 /* Braille Patterns: U+2800–U+28FF */
184 { Script_Braille, 0x2800, 0x28ff, 0, 0},
185 /* Supplemental Arrows-B : U+2900 –U+297f */
186 /* Miscellaneous Mathematical Symbols-B : U+2980 –U+29ff */
187 /* Supplemental Mathematical Operators : U+2a00 –U+2aff */
188 /* Miscellaneous Symbols and Arrows : U+2b00 –U+2bff */
189 { Script_Latin, 0x2900, 0x2bff, 0, 0},
190 /* Latin Extended-C: U+2C60–U+2C7F */
191 { Script_Latin, 0x2c60, 0x2c7f, 0, 0},
192 /* Georgian: U+2D00–U+2D2F */
193 { Script_Georgian, 0x2d00, 0x2d2f, 0, 0},
194 /* Tifinagh: U+2D30–U+2D7F */
195 { Script_Tifinagh, 0x2d30, 0x2d7f, 0, 0},
196 /* Ethiopic Extensions: U+2D80–U+2DDF */
197 { Script_Ethiopic, 0x2d80, 0x2ddf, 0, 0},
198 /* Cyrillic Extended-A: U+2DE0–U+2DFF */
199 { Script_Cyrillic, 0x2de0, 0x2dff, 0, 0},
200 /* CJK Radicals Supplement: U+2E80–U+2EFF */
201 /* Kangxi Radicals: U+2F00–U+2FDF */
202 { Script_CJK_Han, 0x2e80, 0x2fdf, 0, 0},
203 /* Ideographic Description Characters: U+2FF0–U+2FFF */
204 { Script_Ideograph ,0x2ff0, 0x2fff, 0, 0},
205 /* CJK Symbols and Punctuation: U+3000–U+303F */
206 { Script_Ideograph ,0x3000, 0x3004, 0, 0},
207 { Script_CJK_Han ,0x3005, 0x3005, 0, 0},
208 { Script_Ideograph ,0x3006, 0x3006, 0, 0},
209 { Script_CJK_Han ,0x3007, 0x3007, 0, 0},
210 { Script_Ideograph ,0x3008, 0x3020, 0, 0},
211 { Script_CJK_Han ,0x3021, 0x3029, 0, 0},
212 { Script_Ideograph ,0x302a, 0x3030, 0, 0},
213 /* Kana Marks: */
214 { Script_Kana ,0x3031, 0x3035, 0, 0},
215 { Script_Ideograph ,0x3036, 0x3037, 0, 0},
216 { Script_CJK_Han ,0x3038, 0x303b, 0, 0},
217 { Script_Ideograph ,0x303c, 0x303f, 0, 0},
218 /* Hiragana: U+3040–U+309F */
219 /* Katakana: U+30A0–U+30FF */
220 { Script_Kana ,0x3040, 0x30ff, 0, 0},
221 /* Bopomofo: U+3100–U+312F */
222 { Script_Bopomofo ,0x3100, 0x312f, 0, 0},
223 /* Hangul Compatibility Jamo: U+3130–U+318F */
224 { Script_Hangul ,0x3130, 0x318f, 0, 0},
225 /* Kanbun: U+3190–U+319F */
226 { Script_Ideograph ,0x3190, 0x319f, 0, 0},
227 /* Bopomofo Extended: U+31A0–U+31BF */
228 { Script_Bopomofo ,0x31a0, 0x31bf, 0, 0},
229 /* CJK Strokes: U+31C0–U+31EF */
230 { Script_Ideograph ,0x31c0, 0x31ef, 0, 0},
231 /* Katakana Phonetic Extensions: U+31F0–U+31FF */
232 { Script_Kana ,0x31f0, 0x31ff, 0, 0},
233 /* Enclosed CJK Letters and Months: U+3200–U+32FF */
234 { Script_Hangul ,0x3200, 0x321f, 0, 0},
235 { Script_Ideograph ,0x3220, 0x325f, 0, 0},
236 { Script_Hangul ,0x3260, 0x327f, 0, 0},
237 { Script_Ideograph ,0x3280, 0x32ef, 0, 0},
238 { Script_Kana ,0x32d0, 0x31ff, 0, 0},
239 /* CJK Compatibility: U+3300–U+33FF*/
240 { Script_Kana ,0x3300, 0x3357, 0, 0},
241 { Script_Ideograph ,0x3358, 0x33ff, 0, 0},
242 /* CJK Unified Ideographs Extension A: U+3400–U+4DBF */
243 { Script_CJK_Han ,0x3400, 0x4dbf, 0, 0},
244 /* CJK Unified Ideographs: U+4E00–U+9FFF */
245 { Script_CJK_Han ,0x4e00, 0x9fff, 0, 0},
246 /* Yi: U+A000–U+A4CF */
247 { Script_Yi ,0xa000, 0xa4cf, 0, 0},
248 /* Vai: U+A500–U+A63F */
249 { Script_Vai ,0xa500, 0xa63f, Script_Vai_Numeric, 0},
250 /* Cyrillic Extended-B: U+A640–U+A69F */
251 { Script_Cyrillic, 0xa640, 0xa69f, 0, 0},
252 /* Modifier Tone Letters: U+A700–U+A71F */
253 /* Latin Extended-D: U+A720–U+A7FF */
254 { Script_Latin, 0xa700, 0xa7ff, 0, 0},
255 /* Phags-pa: U+A840–U+A87F */
256 { Script_Phags_pa, 0xa840, 0xa87f, 0, 0},
257 /* Devanagari Extended: U+A8E0-U+A8FF */
258 { Script_Devanagari, 0xa8e0, 0xa8ff, Script_Devanagari_Numeric, 0},
259 /* Myanmar Extended-A: U+AA60–U+AA7F */
260 { Script_Myanmar, 0xaa60, 0xaa7f, Script_Myanmar_Numeric, 0},
261 /* Hangul Jamo Extended-A: U+A960–U+A97F */
262 { Script_Hangul, 0xa960, 0xa97f, 0, 0},
263 /* Hangul Syllables: U+AC00–U+D7A3 */
264 { Script_Hangul, 0xac00, 0xd7a3, 0, 0},
265 /* Hangul Jamo Extended-B: U+D7B0–U+D7FF */
266 { Script_Hangul, 0xd7b0, 0xd7ff, 0, 0},
267 /* Surrogates Area: U+D800–U+DFFF */
268 { Script_Surrogates, 0xd800, 0xdbfe, 0, 0},
269 { Script_Private, 0xdbff, 0xdc00, 0, 0},
270 { Script_Surrogates, 0xdc01, 0xdfff, 0, 0},
271 /* Private Use Area: U+E000–U+F8FF */
272 { Script_Private, 0xe000, 0xf8ff, 0, 0},
273 /* CJK Compatibility Ideographs: U+F900–U+FAFF */
274 { Script_CJK_Han ,0xf900, 0xfaff, 0, 0},
275 /* Latin Ligatures: U+FB00–U+FB06 */
276 { Script_Latin, 0xfb00, 0xfb06, 0, 0},
277 /* Armenian ligatures U+FB13..U+FB17 */
278 { Script_Armenian, 0xfb13, 0xfb17, 0, 0},
279 /* Alphabetic Presentation Forms: U+FB1D–U+FB4F */
280 { Script_Hebrew, 0xfb1d, 0xfb4f, 0, 0},
281 /* Arabic Presentation Forms-A: U+FB50–U+FDFF*/
282 { Script_Arabic, 0xfb50, 0xfdff, 0, 0},
283 /* Vertical Forms: U+FE10–U+FE1F */
284 /* Combining Half Marks: U+FE20–U+FE2F */
285 /* CJK Compatibility Forms: U+FE30–U+FE4F */
286 /* Small Form Variants: U+FE50–U+FE6F */
287 { Script_Ideograph ,0xfe10, 0xfe6f, 0, 0},
288 /* Arabic Presentation Forms-B: U+FE70–U+FEFF*/
289 { Script_Arabic, 0xfe70, 0xfeff, 0, 0},
290 /* Halfwidth and Fullwidth Forms: U+FF00–FFEF */
291 { Script_Ideograph ,0xff00, 0xff64, Script_Numeric2, 0},
292 { Script_Kana ,0xff65, 0xff9f, 0, 0},
293 { Script_Hangul ,0xffa0, 0xffdf, 0, 0},
294 { Script_Ideograph ,0xffe0, 0xffef, 0, 0},
295 /* Plane - 1 */
296 /* Deseret: U+10400–U+1044F */
297 { Script_Deseret, 0x10400, 0x1044F, 0, 0},
298 /* Osmanya: U+10480–U+104AF */
299 { Script_Osmanya, 0x10480, 0x104AF, Script_Osmanya_Numeric, 0},
300 /* Mathematical Alphanumeric Symbols: U+1D400–U+1D7FF */
301 { Script_MathAlpha, 0x1D400, 0x1D7FF, 0, 0},
303
304/* this must be in order so that the index matches the Script value */
306 {{SCRIPT_UNDEFINED, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
307 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
308 0x00000000,
309 {0}},
310 {{Script_Latin, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
311 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
312 MS_MAKE_TAG('l','a','t','n'),
313 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
314 {{Script_CR, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
315 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
316 0x00000000,
317 {0}},
318 {{Script_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
319 {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
320 0x00000000,
321 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
322 {{Script_Control, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
323 {LANG_ENGLISH, 0, 1, 0, 0, ANSI_CHARSET, 1, 0, 0, 0, 0, 0, 1, 0, 0},
324 0x00000000,
325 {0}},
326 {{Script_Punctuation, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
327 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
328 0x00000000,
329 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
330 {{Script_Arabic, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}},
331 {LANG_ARABIC, 0, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 1, 0},
332 MS_MAKE_TAG('a','r','a','b'),
333 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
334 {{Script_Arabic_Numeric, 0, 1, 0, 0, 0, 0, { 2,0,0,0,0,0,0,0,0,0,0}},
335 {LANG_ARABIC, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
336 MS_MAKE_TAG('a','r','a','b'),
337 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
338 {{Script_Hebrew, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}},
339 {LANG_HEBREW, 0, 1, 0, 1, HEBREW_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
340 MS_MAKE_TAG('h','e','b','r'),
341 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
342 {{Script_Syriac, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}},
343 {LANG_SYRIAC, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 1, 0},
344 MS_MAKE_TAG('s','y','r','c'),
345 {'E','s','t','r','a','n','g','e','l','o',' ','E','d','e','s','s','a',0}},
346 {{Script_Persian, 0, 1, 0, 0, 0, 0, { 2,0,0,0,0,0,0,0,0,0,0}},
347 {LANG_PERSIAN, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
348 MS_MAKE_TAG('a','r','a','b'),
349 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
350 {{Script_Thaana, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}},
351 {LANG_DIVEHI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
352 MS_MAKE_TAG('t','h','a','a'),
353 {'M','V',' ','B','o','l','i',0}},
354 {{Script_Greek, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
355 {LANG_GREEK, 0, 0, 0, 0, GREEK_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
356 MS_MAKE_TAG('g','r','e','k'),
357 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
358 {{Script_Cyrillic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
359 {LANG_RUSSIAN, 0, 0, 0, 0, RUSSIAN_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
360 MS_MAKE_TAG('c','y','r','l'),
361 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
362 {{Script_Armenian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
363 {LANG_ARMENIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
364 MS_MAKE_TAG('a','r','m','n'),
365 {'S','y','l','f','a','e','n',0}},
366 {{Script_Georgian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
367 {LANG_GEORGIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
368 MS_MAKE_TAG('g','e','o','r'),
369 {'S','y','l','f','a','e','n',0}},
370 {{Script_Sinhala, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
371 {LANG_SINHALESE, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
372 MS_MAKE_TAG('s','i','n','h'),
373 {'I','s','k','o','o','l','a',' ','P','o','t','a',0}},
374 {{Script_Tibetan, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
375 {LANG_TIBETAN, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0},
376 MS_MAKE_TAG('t','i','b','t'),
377 {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}},
378 {{Script_Tibetan_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
379 {LANG_TIBETAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
380 MS_MAKE_TAG('t','i','b','t'),
381 {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}},
382 {{Script_Phags_pa, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
383 {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
384 MS_MAKE_TAG('p','h','a','g'),
385 {'M','i','c','r','o','s','o','f','t',' ','P','h','a','g','s','P','a',0}},
386 {{Script_Thai, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
387 {LANG_THAI, 0, 1, 1, 1, THAI_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 1},
388 MS_MAKE_TAG('t','h','a','i'),
389 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
390 {{Script_Thai_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
391 {LANG_THAI, 1, 1, 0, 0, THAI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
392 MS_MAKE_TAG('t','h','a','i'),
393 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
394 {{Script_Lao, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
395 {LANG_LAO, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0},
396 MS_MAKE_TAG('l','a','o',' '),
397 {'D','o','k','C','h','a','m','p','a',0}},
398 {{Script_Lao_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
399 {LANG_LAO, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
400 MS_MAKE_TAG('l','a','o',' '),
401 {'D','o','k','C','h','a','m','p','a',0}},
402 {{Script_Devanagari, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
403 {LANG_HINDI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
404 MS_MAKE_TAG('d','e','v','a'),
405 {'M','a','n','g','a','l',0}},
406 {{Script_Devanagari_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
407 {LANG_HINDI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
408 MS_MAKE_TAG('d','e','v','a'),
409 {'M','a','n','g','a','l',0}},
410 {{Script_Bengali, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
411 {LANG_BENGALI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
412 MS_MAKE_TAG('b','e','n','g'),
413 {'V','r','i','n','d','a',0}},
414 {{Script_Bengali_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
415 {LANG_BENGALI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
416 MS_MAKE_TAG('b','e','n','g'),
417 {'V','r','i','n','d','a',0}},
418 {{Script_Bengali_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
419 {LANG_BENGALI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
420 MS_MAKE_TAG('b','e','n','g'),
421 {'V','r','i','n','d','a',0}},
422 {{Script_Gurmukhi, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
423 {LANG_PUNJABI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
424 MS_MAKE_TAG('g','u','r','u'),
425 {'R','a','a','v','i',0}},
426 {{Script_Gurmukhi_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
427 {LANG_PUNJABI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
428 MS_MAKE_TAG('g','u','r','u'),
429 {'R','a','a','v','i',0}},
430 {{Script_Gujarati, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
431 {LANG_GUJARATI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
432 MS_MAKE_TAG('g','u','j','r'),
433 {'S','h','r','u','t','i',0}},
434 {{Script_Gujarati_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
435 {LANG_GUJARATI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
436 MS_MAKE_TAG('g','u','j','r'),
437 {'S','h','r','u','t','i',0}},
438 {{Script_Gujarati_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
439 {LANG_GUJARATI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
440 MS_MAKE_TAG('g','u','j','r'),
441 {'S','h','r','u','t','i',0}},
442 {{Script_Oriya, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
443 {LANG_ORIYA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
444 MS_MAKE_TAG('o','r','y','a'),
445 {'K','a','l','i','n','g','a',0}},
446 {{Script_Oriya_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
447 {LANG_ORIYA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
448 MS_MAKE_TAG('o','r','y','a'),
449 {'K','a','l','i','n','g','a',0}},
450 {{Script_Tamil, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
451 {LANG_TAMIL, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
452 MS_MAKE_TAG('t','a','m','l'),
453 {'L','a','t','h','a',0}},
454 {{Script_Tamil_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
455 {LANG_TAMIL, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
456 MS_MAKE_TAG('t','a','m','l'),
457 {'L','a','t','h','a',0}},
458 {{Script_Telugu, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
459 {LANG_TELUGU, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
460 MS_MAKE_TAG('t','e','l','u'),
461 {'G','a','u','t','a','m','i',0}},
462 {{Script_Telugu_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
463 {LANG_TELUGU, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
464 MS_MAKE_TAG('t','e','l','u'),
465 {'G','a','u','t','a','m','i',0}},
466 {{Script_Kannada, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
467 {LANG_KANNADA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
468 MS_MAKE_TAG('k','n','d','a'),
469 {'T','u','n','g','a',0}},
470 {{Script_Kannada_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
471 {LANG_KANNADA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
472 MS_MAKE_TAG('k','n','d','a'),
473 {'T','u','n','g','a',0}},
474 {{Script_Malayalam, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
475 {LANG_MALAYALAM, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
476 MS_MAKE_TAG('m','l','y','m'),
477 {'K','a','r','t','i','k','a',0}},
478 {{Script_Malayalam_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
479 {LANG_MALAYALAM, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
480 MS_MAKE_TAG('m','l','y','m'),
481 {'K','a','r','t','i','k','a',0}},
482 {{Script_Diacritical, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
483 {LANG_ENGLISH, 0, 1, 0, 1, ANSI_CHARSET, 0, 0, 0, 0, 0, 1, 1, 0, 0},
484 0x00000000,
485 {0}},
486 {{Script_Punctuation2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
487 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
488 MS_MAKE_TAG('l','a','t','n'),
489 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
490 {{Script_Numeric2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
491 {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
492 0x00000000,
493 {0}},
494 {{Script_Myanmar, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
495 {0x55, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
496 MS_MAKE_TAG('m','y','m','r'),
497 {'M','y','a','n','m','a','r',' ','T','e','x','t',0}},
498 {{Script_Myanmar_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
499 {0x55, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
500 MS_MAKE_TAG('m','y','m','r'),
501 {0}},
502 {{Script_Tai_Le, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
503 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
504 MS_MAKE_TAG('t','a','l','e'),
505 {'M','i','c','r','o','s','o','f','t',' ','T','a','i',' ','L','e',0}},
506 {{Script_New_Tai_Lue, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
507 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
508 MS_MAKE_TAG('t','a','l','u'),
509 {'M','i','c','r','o','s','o','f','t',' ','N','e','w',' ','T','a','i',' ','L','u','e',0}},
510 {{Script_New_Tai_Lue_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
511 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
512 MS_MAKE_TAG('t','a','l','u'),
513 {'M','i','c','r','o','s','o','f','t',' ','N','e','w',' ','T','a','i',' ','L','u','e',0}},
514 {{Script_Khmer, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
515 {0x53, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0},
516 MS_MAKE_TAG('k','h','m','r'),
517 {'D','a','u','n','P','e','n','h',0}},
518 {{Script_Khmer_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
519 {0x53, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
520 MS_MAKE_TAG('k','h','m','r'),
521 {'D','a','u','n','P','e','n','h',0}},
522 {{Script_CJK_Han, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
523 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
524 MS_MAKE_TAG('h','a','n','i'),
525 {0}},
526 {{Script_Ideograph, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
527 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
528 MS_MAKE_TAG('h','a','n','i'),
529 {0}},
530 {{Script_Bopomofo, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
531 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
532 MS_MAKE_TAG('b','o','p','o'),
533 {0}},
534 {{Script_Kana, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
535 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
536 MS_MAKE_TAG('k','a','n','a'),
537 {0}},
538 {{Script_Hangul, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
539 {LANG_KOREAN, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
540 MS_MAKE_TAG('h','a','n','g'),
541 {0}},
542 {{Script_Yi, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
543 {LANG_ENGLISH, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
544 MS_MAKE_TAG('y','i',' ',' '),
545 {'M','i','c','r','o','s','o','f','t',' ','Y','i',' ','B','a','i','t','i',0}},
546 {{Script_Ethiopic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
547 {0x5e, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
548 MS_MAKE_TAG('e','t','h','i'),
549 {'N','y','a','l','a',0}},
550 {{Script_Ethiopic_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
551 {0x5e, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
552 MS_MAKE_TAG('e','t','h','i'),
553 {'N','y','a','l','a',0}},
554 {{Script_Mongolian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
555 {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
556 MS_MAKE_TAG('m','o','n','g'),
557 {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i',0}},
558 {{Script_Mongolian_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
559 {LANG_MONGOLIAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
560 MS_MAKE_TAG('m','o','n','g'),
561 {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i',0}},
562 {{Script_Tifinagh, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
563 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
564 MS_MAKE_TAG('t','f','n','g'),
565 {'E','b','r','i','m','a',0}},
566 {{Script_NKo, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}},
567 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
568 MS_MAKE_TAG('n','k','o',' '),
569 {'E','b','r','i','m','a',0}},
570 {{Script_Vai, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
571 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
572 MS_MAKE_TAG('v','a','i',' '),
573 {'E','b','r','i','m','a',0}},
574 {{Script_Vai_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
575 {0, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
576 MS_MAKE_TAG('v','a','i',' '),
577 {'E','b','r','i','m','a',0}},
578 {{Script_Cherokee, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
579 {0x5c, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
580 MS_MAKE_TAG('c','h','e','r'),
581 {'P','l','a','n','t','a','g','e','n','e','t',' ','C','h','e','r','o','k','e','e',0}},
582 {{Script_Canadian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
583 {0x5d, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
584 MS_MAKE_TAG('c','a','n','s'),
585 {'E','u','p','h','e','m','i','a',0}},
586 {{Script_Ogham, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
587 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
588 MS_MAKE_TAG('o','g','a','m'),
589 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l',0}},
590 {{Script_Runic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
591 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
592 MS_MAKE_TAG('r','u','n','r'),
593 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l',0}},
594 {{Script_Braille, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
595 {LANG_ENGLISH, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
596 MS_MAKE_TAG('b','r','a','i'),
597 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l',0}},
598 {{Script_Surrogates, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
599 {LANG_ENGLISH, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0},
600 0x00000000,
601 {0}},
602 {{Script_Private, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
603 {0, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 1, 0, 0, 0, 0, 1, 0, 0},
604 0x00000000,
605 {0}},
606 {{Script_Deseret, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
607 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
608 MS_MAKE_TAG('d','s','r','t'),
609 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l',0}},
610 {{Script_Osmanya, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
611 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
612 MS_MAKE_TAG('o','s','m','a'),
613 {'E','b','r','i','m','a',0}},
614 {{Script_Osmanya_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
615 {0, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
616 MS_MAKE_TAG('o','s','m','a'),
617 {'E','b','r','i','m','a',0}},
618 {{Script_MathAlpha, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
619 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
620 MS_MAKE_TAG('m','a','t','h'),
621 {'C','a','m','b','r','i','a',' ','M','a','t','h',0}},
622 {{Script_Hebrew_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
623 {LANG_HEBREW, 0, 1, 0, 0, HEBREW_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
624 MS_MAKE_TAG('h','e','b','r'),
625 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
626 {{Script_Vietnamese_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
627 {LANG_VIETNAMESE, 0, 0, 0, 0, VIETNAMESE_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
628 MS_MAKE_TAG('l','a','t','n'),
629 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
630 {{Script_Thai_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}},
631 {LANG_THAI, 0, 1, 0, 0, THAI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0},
632 MS_MAKE_TAG('t','h','a','i'),
633 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}},
634};
635
637{
679};
680
683{
684 0, 0, &cs_script_cache,
686 0, 0, { (DWORD_PTR)(__FILE__ ": script_cache") }
687};
688static CRITICAL_SECTION cs_script_cache = { &cs_script_cache_dbg, -1, 0, 0, 0, 0 };
690
691typedef struct {
703
705{
708};
709
710typedef struct {
724
725typedef struct {
729
730BOOL usp10_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
731{
732 SIZE_T max_capacity, new_capacity;
733 void *new_elements;
734
735 if (count <= *capacity)
736 return TRUE;
737
738 max_capacity = ~(SIZE_T)0 / size;
739 if (count > max_capacity)
740 return FALSE;
741
742 new_capacity = max(1, *capacity);
743 while (new_capacity < count && new_capacity <= max_capacity / 2)
744 new_capacity *= 2;
745 if (new_capacity < count)
746 new_capacity = count;
747
748 if (!*elements)
749 new_elements = heap_alloc_zero(new_capacity * size);
750 else
751 new_elements = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *elements, new_capacity * size);
752 if (!new_elements)
753 return FALSE;
754
755 *elements = new_elements;
756 *capacity = new_capacity;
757 return TRUE;
758}
759
760/* TODO Fix font properties on Arabic locale */
762{
763 sc->sfp.cBytes = sizeof(sc->sfp);
764
765 if (!sc->sfnt)
766 {
767 sc->sfp.wgBlank = sc->tm.tmBreakChar;
768 sc->sfp.wgDefault = sc->tm.tmDefaultChar;
769 sc->sfp.wgInvalid = sc->sfp.wgBlank;
770 sc->sfp.wgKashida = 0xFFFF;
771 sc->sfp.iKashidaWidth = 0;
772 }
773 else
774 {
775 static const WCHAR chars[4] = {0x0020, 0x200B, 0xF71B, 0x0640};
776 /* U+0020: numeric space
777 U+200B: zero width space
778 U+F71B: unknown char found by black box testing
779 U+0640: kashida */
780 WORD gi[4];
781
783 {
784 if(gi[0] != 0xFFFF) /* 0xFFFF: index of default non exist char */
785 sc->sfp.wgBlank = gi[0];
786 else
787 sc->sfp.wgBlank = 0;
788
789 sc->sfp.wgDefault = 0;
790
791 if (gi[2] != 0xFFFF)
792 sc->sfp.wgInvalid = gi[2];
793 else if (gi[1] != 0xFFFF)
794 sc->sfp.wgInvalid = gi[1];
795 else if (gi[0] != 0xFFFF)
796 sc->sfp.wgInvalid = gi[0];
797 else
798 sc->sfp.wgInvalid = 0;
799
800 sc->sfp.wgKashida = gi[3];
801
802 sc->sfp.iKashidaWidth = 0; /* TODO */
803 }
804 else
805 return FALSE;
806 }
807 return TRUE;
808}
809
811{
812 *sfp = sc->sfp;
813}
814
816{
817 return ((ScriptCache *)*psc)->tm.tmHeight;
818}
819
821{
822 return ((ScriptCache *)*psc)->tm.tmPitchAndFamily;
823}
824
826{
827 CacheGlyphPage *page = ((ScriptCache *)*psc)->page[c / 0x10000];
828 WORD *block;
829
830 if (!page) return 0;
831 block = page->glyphs[(c % 0x10000) >> GLYPH_BLOCK_SHIFT];
832 if (!block) return 0;
833 return block[(c % 0x10000) & GLYPH_BLOCK_MASK];
834}
835
837{
838 CacheGlyphPage **page = &((ScriptCache *)*psc)->page[c / 0x10000];
839 WORD **block;
840 if (!*page && !(*page = heap_alloc_zero(sizeof(CacheGlyphPage)))) return 0;
841
842 block = &(*page)->glyphs[(c % 0x10000) >> GLYPH_BLOCK_SHIFT];
843 if (!*block && !(*block = heap_alloc_zero(sizeof(WORD) * GLYPH_BLOCK_SIZE))) return 0;
844 return ((*block)[(c % 0x10000) & GLYPH_BLOCK_MASK] = glyph);
845}
846
848{
849 static const ABC nil;
850 ABC *block = ((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
851
852 if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(ABC))) return FALSE;
853 memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC));
854 return TRUE;
855}
856
858{
859 ABC **block = &((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
860
861 if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE))) return FALSE;
862 memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC));
863 return TRUE;
864}
865
867{
868 ScriptCache *sc;
869 unsigned size;
870 LOGFONTW lf;
871
872 if (!psc) return E_INVALIDARG;
873 if (*psc) return S_OK;
874 if (!hdc) return E_PENDING;
875
876 if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf))
877 {
878 return E_INVALIDARG;
879 }
880 /* Ensure canonical result by zeroing extra space in lfFaceName */
882 memset(lf.lfFaceName + size, 0, sizeof(lf.lfFaceName) - size * sizeof(WCHAR));
883
886 {
887 if (!memcmp(&sc->lf, &lf, sizeof(lf)))
888 {
889 sc->refcount++;
891 *psc = sc;
892 return S_OK;
893 }
894 }
896
897 if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY;
898 if (!GetTextMetricsW(hdc, &sc->tm))
899 {
900 heap_free(sc);
901 return E_INVALIDARG;
902 }
904 if (size)
905 {
906 sc->otm = heap_alloc(size);
907 sc->otm->otmSize = size;
909 }
910 sc->sfnt = (GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0)!=GDI_ERROR);
912 {
913 heap_free(sc);
914 return E_INVALIDARG;
915 }
916 sc->lf = lf;
917 sc->refcount = 1;
918 *psc = sc;
919
923 {
924 if (sc != *psc && !memcmp(&sc->lf, &lf, sizeof(lf)))
925 {
926 /* Another thread won the race. Use their cache instead of ours */
927 list_remove(&sc->entry);
928 sc->refcount++;
930 heap_free(*psc);
931 *psc = sc;
932 return S_OK;
933 }
934 }
936 TRACE("<- %p\n", sc);
937 return S_OK;
938}
939
941{
943 return ch + wine_mirror_map[wine_mirror_map[ch >> 8] + (ch & 0xff)];
944}
945
946static DWORD decode_surrogate_pair(const WCHAR *str, unsigned int index, unsigned int end)
947{
948 if (index < end-1 && IS_SURROGATE_PAIR(str[index],str[index+1]))
949 {
950 DWORD ch = 0x10000 + ((str[index] - 0xd800) << 10) + (str[index+1] - 0xdc00);
951 TRACE("Surrogate Pair %x %x => %x\n",str[index], str[index+1], ch);
952 return ch;
953 }
954 return 0;
955}
956
957static int __cdecl usp10_compare_script_range(const void *key, const void *value)
958{
959 const struct usp10_script_range *range = value;
960 const DWORD *ch = key;
961
962 if (*ch < range->rangeFirst)
963 return -1;
964 if (*ch > range->rangeLast)
965 return 1;
966 return 0;
967}
968
969static enum usp10_script get_char_script(const WCHAR *str, unsigned int index,
970 unsigned int end, unsigned int *consumed)
971{
972 static const WCHAR latin_punc[] = {'#','$','&','\'',',',';','<','>','?','@','\\','^','_','`','{','|','}','~', 0x00a0, 0};
974 WORD type = 0, type2 = 0;
975 DWORD ch;
976
977 *consumed = 1;
978
979 if (str[index] == 0xc || str[index] == 0x20 || str[index] == 0x202f)
980 return Script_CR;
981
982 /* These punctuation characters are separated out as Latin punctuation */
983 if (wcschr(latin_punc,str[index]))
984 return Script_Punctuation2;
985
986 /* These chars are itemized as Punctuation by Windows */
987 if (str[index] == 0x2212 || str[index] == 0x2044)
988 return Script_Punctuation;
989
990 /* Currency Symbols by Unicode point */
991 switch (str[index])
992 {
993 case 0x09f2:
994 case 0x09f3: return Script_Bengali_Currency;
995 case 0x0af1: return Script_Gujarati_Currency;
996 case 0x0e3f: return Script_Thai_Currency;
997 case 0x20aa: return Script_Hebrew_Currency;
998 case 0x20ab: return Script_Vietnamese_Currency;
999 case 0xfb29: return Script_Hebrew_Currency;
1000 }
1001
1003 GetStringTypeW(CT_CTYPE2, &str[index], 1, &type2);
1004
1005 if (type == 0)
1006 return SCRIPT_UNDEFINED;
1007
1008 if (type & C1_CNTRL)
1009 return Script_Control;
1010
1012 if (ch)
1013 *consumed = 2;
1014 else
1015 ch = str[index];
1016
1019 return (*consumed == 2) ? Script_Surrogates : Script_Undefined;
1020
1021 if (range->numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER))
1022 return range->numericScript;
1023 if (range->punctScript && type & C1_PUNCT)
1024 return range->punctScript;
1025 return range->script;
1026}
1027
1028static int __cdecl compare_FindGlyph(const void *a, const void* b)
1029{
1031 const WORD *idx= (WORD*)b;
1032 int rc = 0;
1033
1034 if ( find->target > *idx)
1035 rc = 1;
1036 else if (find->target < *idx)
1037 rc = -1;
1038
1039 if (!find->ascending)
1040 rc *= -1;
1041 return rc;
1042}
1043
1045{
1046 FindGlyph_struct fgs;
1047 WORD *ptr;
1048 INT k;
1049
1050 if (pwLogClust[0] < pwLogClust[cChars-1])
1051 fgs.ascending = TRUE;
1052 else
1053 fgs.ascending = FALSE;
1054
1055 fgs.target = target;
1056 ptr = bsearch(&fgs, pwLogClust, cChars, sizeof(WORD), compare_FindGlyph);
1057
1058 if (!ptr)
1059 return -1;
1060
1061 for (k = (ptr - pwLogClust)-1; k >= 0 && pwLogClust[k] == target; k--)
1062 ;
1063 k++;
1064
1065 return k;
1066}
1067
1068/***********************************************************************
1069 * ScriptFreeCache (USP10.@)
1070 *
1071 * Free a script cache.
1072 *
1073 * PARAMS
1074 * psc [I/O] Script cache.
1075 *
1076 * RETURNS
1077 * Success: S_OK
1078 * Failure: Non-zero HRESULT value.
1079 */
1081{
1082 TRACE("%p\n", psc);
1083
1084 if (psc && *psc)
1085 {
1086 unsigned int i;
1087 INT n;
1088
1090 if (--((ScriptCache *)*psc)->refcount > 0)
1091 {
1093 *psc = NULL;
1094 return S_OK;
1095 }
1098
1099 for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++)
1100 {
1101 heap_free(((ScriptCache *)*psc)->widths[i]);
1102 }
1103 for (i = 0; i < NUM_PAGES; i++)
1104 {
1105 unsigned int j;
1106 if (((ScriptCache *)*psc)->page[i])
1107 for (j = 0; j < GLYPH_MAX / GLYPH_BLOCK_SIZE; j++)
1108 heap_free(((ScriptCache *)*psc)->page[i]->glyphs[j]);
1109 heap_free(((ScriptCache *)*psc)->page[i]);
1110 }
1111 heap_free(((ScriptCache *)*psc)->GSUB_Table);
1112 heap_free(((ScriptCache *)*psc)->GDEF_Table);
1113 heap_free(((ScriptCache *)*psc)->CMAP_Table);
1114 heap_free(((ScriptCache *)*psc)->GPOS_Table);
1115 for (n = 0; n < ((ScriptCache *)*psc)->script_count; n++)
1116 {
1117 int j;
1118 for (j = 0; j < ((ScriptCache *)*psc)->scripts[n].language_count; j++)
1119 {
1120 int k;
1121 for (k = 0; k < ((ScriptCache *)*psc)->scripts[n].languages[j].feature_count; k++)
1122 heap_free(((ScriptCache *)*psc)->scripts[n].languages[j].features[k].lookups);
1123 heap_free(((ScriptCache *)*psc)->scripts[n].languages[j].features);
1124 }
1125 for (j = 0; j < ((ScriptCache *)*psc)->scripts[n].default_language.feature_count; j++)
1126 heap_free(((ScriptCache *)*psc)->scripts[n].default_language.features[j].lookups);
1127 heap_free(((ScriptCache *)*psc)->scripts[n].default_language.features);
1128 heap_free(((ScriptCache *)*psc)->scripts[n].languages);
1129 }
1130 heap_free(((ScriptCache *)*psc)->scripts);
1131 heap_free(((ScriptCache *)*psc)->otm);
1132 heap_free(*psc);
1133 *psc = NULL;
1134 }
1135 return S_OK;
1136}
1137
1138/***********************************************************************
1139 * ScriptGetProperties (USP10.@)
1140 *
1141 * Retrieve a list of script properties.
1142 *
1143 * PARAMS
1144 * props [I] Pointer to an array of SCRIPT_PROPERTIES pointers.
1145 * num [I] Pointer to the number of scripts.
1146 *
1147 * RETURNS
1148 * Success: S_OK
1149 * Failure: Non-zero HRESULT value.
1150 *
1151 * NOTES
1152 * Behaviour matches WinXP.
1153 */
1155{
1156 TRACE("(%p,%p)\n", props, num);
1157
1158 if (!props && !num) return E_INVALIDARG;
1159
1160 if (num) *num = ARRAY_SIZE(script_props);
1161 if (props) *props = script_props;
1162
1163 return S_OK;
1164}
1165
1166/***********************************************************************
1167 * ScriptGetFontProperties (USP10.@)
1168 *
1169 * Get information on special glyphs.
1170 *
1171 * PARAMS
1172 * hdc [I] Device context.
1173 * psc [I/O] Opaque pointer to a script cache.
1174 * sfp [O] Font properties structure.
1175 */
1177{
1178 HRESULT hr;
1179
1180 TRACE("%p,%p,%p\n", hdc, psc, sfp);
1181
1182 if (!sfp) return E_INVALIDARG;
1183 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
1184
1185 if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES))
1186 return E_INVALIDARG;
1187
1189
1190 return S_OK;
1191}
1192
1193/***********************************************************************
1194 * ScriptRecordDigitSubstitution (USP10.@)
1195 *
1196 * Record digit substitution settings for a given locale.
1197 *
1198 * PARAMS
1199 * locale [I] Locale identifier.
1200 * sds [I] Structure to record substitution settings.
1201 *
1202 * RETURNS
1203 * Success: S_OK
1204 * Failure: E_POINTER if sds is NULL, E_INVALIDARG otherwise.
1205 *
1206 * SEE ALSO
1207 * http://blogs.msdn.com/michkap/archive/2006/02/22/536877.aspx
1208 */
1210{
1211 DWORD plgid, sub;
1212
1213 TRACE("0x%x, %p\n", locale, sds);
1214
1215 /* This implementation appears to be correct for all languages, but it's
1216 * not clear if sds->DigitSubstitute is ever set to anything except
1217 * CONTEXT or NONE in reality */
1218
1219 if (!sds) return E_POINTER;
1220
1222
1224 return E_INVALIDARG;
1225
1227 sds->TraditionalDigitLanguage = plgid;
1228
1229 if (plgid == LANG_ARABIC || plgid == LANG_FARSI)
1230 sds->NationalDigitLanguage = plgid;
1231 else
1233
1234 if (!GetLocaleInfoW(locale, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER,
1235 (WCHAR *)&sub, sizeof(sub) / sizeof(WCHAR)))
1236 return E_INVALIDARG;
1237
1238 switch (sub)
1239 {
1240 case 0:
1241 if (plgid == LANG_ARABIC || plgid == LANG_FARSI)
1243 else
1245 break;
1246 case 1:
1248 break;
1249 case 2:
1251 break;
1252 default:
1254 break;
1255 }
1256
1257 sds->dwReserved = 0;
1258 return S_OK;
1259}
1260
1261/***********************************************************************
1262 * ScriptApplyDigitSubstitution (USP10.@)
1263 *
1264 * Apply digit substitution settings.
1265 *
1266 * PARAMS
1267 * sds [I] Structure with recorded substitution settings.
1268 * sc [I] Script control structure.
1269 * ss [I] Script state structure.
1270 *
1271 * RETURNS
1272 * Success: S_OK
1273 * Failure: E_INVALIDARG if sds is invalid. Otherwise an HRESULT.
1274 */
1277{
1279
1280 TRACE("%p, %p, %p\n", sds, sc, ss);
1281
1282 if (!sc || !ss) return E_POINTER;
1283 if (!sds)
1284 {
1285 sds = &psds;
1287 return E_INVALIDARG;
1288 }
1289
1291 sc->fContextDigits = 0;
1292 ss->fDigitSubstitute = 0;
1293
1294 switch (sds->DigitSubstitute) {
1299 return S_OK;
1300 default:
1301 return E_INVALIDARG;
1302 }
1303}
1304
1306{
1308}
1309
1311{
1312 switch (script)
1313 {
1314 case Script_Devanagari:
1316 case Script_Bengali:
1319 case Script_Gurmukhi:
1321 case Script_Gujarati:
1324 case Script_Oriya:
1326 case Script_Tamil:
1328 case Script_Telugu:
1330 case Script_Kannada:
1332 case Script_Malayalam:
1334 default:
1335 return Script_Undefined;
1336 };
1337}
1338
1340{
1342}
1343
1344static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars,
1348{
1349
1350#define Numeric_space 0x0020
1351#define ZWSP 0x200B
1352#define ZWNJ 0x200C
1353#define ZWJ 0x200D
1354
1355 enum usp10_script last_indic = Script_Undefined;
1356 int cnt = 0, index = 0, str = 0;
1357 enum usp10_script New_Script = -1;
1358 int i;
1359 WORD *levels = NULL;
1360 WORD *layout_levels = NULL;
1361 WORD *overrides = NULL;
1362 WORD *strength = NULL;
1363 enum usp10_script *scripts;
1364 WORD baselevel = 0;
1365 WORD baselayout = 0;
1366 BOOL new_run;
1367 WORD layoutRTL = 0;
1368 BOOL forceLevels = FALSE;
1369 unsigned int consumed = 0;
1371
1372 TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems,
1374
1375 if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2)
1376 return E_INVALIDARG;
1377
1378 if (!(scripts = heap_calloc(cInChars, sizeof(*scripts))))
1379 return E_OUTOFMEMORY;
1380
1381 for (i = 0; i < cInChars; i++)
1382 {
1383 if (!consumed)
1384 {
1385 scripts[i] = get_char_script(pwcInChars,i,cInChars,&consumed);
1386 consumed --;
1387 }
1388 else
1389 {
1390 scripts[i] = scripts[i-1];
1391 consumed --;
1392 }
1393 /* Devanagari danda (U+0964) and double danda (U+0965) are used for
1394 all Indic scripts */
1395 if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic != Script_Undefined)
1396 scripts[i] = last_indic;
1397 else if (is_indic(scripts[i]))
1398 last_indic = base_indic(scripts[i]);
1399
1400 /* Some unicode points :
1401 (Zero Width Space U+200B - Right-to-Left Mark U+200F)
1402 (Left Right Embed U+202A - Left Right Override U+202D)
1403 (Left Right Isolate U+2066 - Pop Directional Isolate U+2069)
1404 will force us into bidi mode */
1405 if (!forceLevels && ((pwcInChars[i] >= 0x200B && pwcInChars[i] <= 0x200F) ||
1406 (pwcInChars[i] >= 0x202A && pwcInChars[i] <= 0x202E) ||
1407 (pwcInChars[i] >= 0x2066 && pwcInChars[i] <= 0x2069)))
1408
1409 forceLevels = TRUE;
1410
1411 /* Diacritical marks merge with other scripts */
1412 if (scripts[i] == Script_Diacritical)
1413 {
1414 if (i > 0)
1415 {
1416 if (pScriptTags)
1417 scripts[i] = scripts[i-1];
1418 else
1419 {
1420 int j;
1421 BOOL asian = FALSE;
1422 enum usp10_script first_script = scripts[i-1];
1423 for (j = i-1; j >= 0 && scripts[j] == first_script && pwcInChars[j] != Numeric_space; j--)
1424 {
1425 enum usp10_script original = scripts[j];
1426 if (original == Script_Ideograph || original == Script_Kana || original == Script_Yi || original == Script_CJK_Han || original == Script_Bopomofo)
1427 {
1428 asian = TRUE;
1429 break;
1430 }
1431 if (original != Script_MathAlpha && scriptInformation[scripts[j]].props.fComplex)
1432 break;
1433 scripts[j] = scripts[i];
1434 if (original == Script_Punctuation2)
1435 break;
1436 }
1437 if (j >= 0 && (scriptInformation[scripts[j]].props.fComplex || asian))
1438 scripts[i] = scripts[j];
1439 }
1440 }
1441 }
1442 }
1443
1444 for (i = 0; i < cInChars; i++)
1445 {
1446 /* Joiners get merged preferencially right */
1447 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ || pwcInChars[i] == ZWSP))
1448 {
1449 int j;
1450 if (i+1 == cInChars)
1451 scripts[i] = scripts[i-1];
1452 else
1453 {
1454 for (j = i+1; j < cInChars; j++)
1455 {
1456 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
1457 && pwcInChars[j] != ZWSP && pwcInChars[j] != Numeric_space)
1458 {
1459 scripts[i] = scripts[j];
1460 break;
1461 }
1462 }
1463 }
1464 }
1465 }
1466
1467 if (psState && psControl)
1468 {
1469 if (!(levels = heap_calloc(cInChars, sizeof(*levels))))
1470 goto nomemory;
1471
1472 if (!(overrides = heap_calloc(cInChars, sizeof(*overrides))))
1473 goto nomemory;
1474
1475 if (!(layout_levels = heap_calloc(cInChars, sizeof(*layout_levels))))
1476 goto nomemory;
1477
1478 if (psState->fOverrideDirection)
1479 {
1480 if (!forceLevels)
1481 {
1483 s.fOverrideDirection = FALSE;
1484 BIDI_DetermineLevels(pwcInChars, cInChars, &s, psControl, layout_levels, overrides);
1485 if (odd(layout_levels[0]))
1486 forceLevels = TRUE;
1487 else for (i = 0; i < cInChars; i++)
1488 if (layout_levels[i]!=layout_levels[0])
1489 {
1490 forceLevels = TRUE;
1491 break;
1492 }
1493 }
1494
1495 BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels, overrides);
1496 }
1497 else
1498 {
1499 BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels, overrides);
1500 memcpy(layout_levels, levels, cInChars * sizeof(WORD));
1501 }
1502 baselevel = levels[0];
1503 baselayout = layout_levels[0];
1504 for (i = 0; i < cInChars; i++)
1505 if (levels[i]!=levels[0])
1506 break;
1507 if (i >= cInChars && !odd(baselevel) && !odd(psState->uBidiLevel) && !forceLevels)
1508 {
1510 heap_free(overrides);
1511 heap_free(layout_levels);
1512 overrides = NULL;
1513 levels = NULL;
1514 layout_levels = NULL;
1515 }
1516 else
1517 {
1518 static const WCHAR math_punc[] = {'#','$','%','+',',','-','.','/',':',0x2212, 0x2044, 0x00a0,0};
1519 static const WCHAR repeatable_math_punc[] = {'#','$','%','+','-','/',0x2212, 0x2044,0};
1520
1521 if (!(strength = heap_calloc(cInChars, sizeof(*strength))))
1522 goto nomemory;
1523 BIDI_GetStrengths(pwcInChars, cInChars, psControl, strength);
1524
1525 /* We currently mis-level leading Diacriticals */
1526 if (scripts[0] == Script_Diacritical)
1527 for (i = 0; i < cInChars && scripts[0] == Script_Diacritical; i++)
1528 {
1529 levels[i] = odd(levels[i])?levels[i]+1:levels[i];
1530 strength[i] = BIDI_STRONG;
1531 }
1532
1533 /* Math punctuation bordered on both sides by numbers can be
1534 merged into the number */
1535 for (i = 0; i < cInChars; i++)
1536 {
1537 if (i > 0 && i < cInChars-1 &&
1538 script_is_numeric(scripts[i-1]) &&
1539 wcschr(math_punc, pwcInChars[i]))
1540 {
1541 if (script_is_numeric(scripts[i+1]))
1542 {
1543 scripts[i] = scripts[i+1];
1544 levels[i] = levels[i-1];
1545 strength[i] = strength[i-1];
1546 i++;
1547 }
1548 else if (wcschr(repeatable_math_punc, pwcInChars[i]))
1549 {
1550 int j;
1551 for (j = i+1; j < cInChars; j++)
1552 {
1553 if (script_is_numeric(scripts[j]))
1554 {
1555 for(;i<j; i++)
1556 {
1557 scripts[i] = scripts[j];
1558 levels[i] = levels[i-1];
1559 strength[i] = strength[i-1];
1560 }
1561 }
1562 else if (pwcInChars[i] != pwcInChars[j]) break;
1563 }
1564 }
1565 }
1566 }
1567
1568 for (i = 0; i < cInChars; i++)
1569 {
1570 /* Numerics at level 0 get bumped to level 2 */
1571 if (!overrides[i] && (levels[i] == 0 || (odd(psState->uBidiLevel)
1572 && levels[i] == psState->uBidiLevel + 1)) && script_is_numeric(scripts[i]))
1573 {
1574 levels[i] = 2;
1575 }
1576
1577 /* Joiners get merged preferencially right */
1578 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ || pwcInChars[i] == ZWSP))
1579 {
1580 int j;
1581 if (i+1 == cInChars && levels[i-1] == levels[i])
1582 strength[i] = strength[i-1];
1583 else
1584 for (j = i+1; j < cInChars && levels[i] == levels[j]; j++)
1585 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
1586 && pwcInChars[j] != ZWSP && pwcInChars[j] != Numeric_space)
1587 {
1588 strength[i] = strength[j];
1589 break;
1590 }
1591 }
1592 }
1594 {
1595 /* Merge the neutrals */
1596 for (i = 0; i < cInChars; i++)
1597 {
1598 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK)
1599 {
1600 int j;
1601 for (j = i; j > 0; j--)
1602 {
1603 if (levels[i] != levels[j])
1604 break;
1605 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK))
1606 {
1607 scripts[i] = scripts[j];
1608 strength[i] = strength[j];
1609 break;
1610 }
1611 }
1612 }
1613 /* Try going the other way */
1614 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK)
1615 {
1616 int j;
1617 for (j = i; j < cInChars; j++)
1618 {
1619 if (levels[i] != levels[j])
1620 break;
1621 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK))
1622 {
1623 scripts[i] = scripts[j];
1624 strength[i] = strength[j];
1625 break;
1626 }
1627 }
1628 }
1629 }
1630 }
1631 }
1632 }
1633
1634 while ((!levels || (levels && cnt+1 < cInChars && levels[cnt+1] == levels[0]))
1635 && (cnt < cInChars && pwcInChars[cnt] == Numeric_space))
1636 cnt++;
1637
1638 if (cnt == cInChars) /* All Spaces */
1639 {
1640 cnt = 0;
1641 New_Script = scripts[cnt];
1642 }
1643
1644 pItems[index].iCharPos = 0;
1645 pItems[index].a = scriptInformation[scripts[cnt]].a;
1646 if (pScriptTags)
1648
1649 if (strength && strength[cnt] == BIDI_STRONG)
1650 str = strength[cnt];
1651 else if (strength)
1652 str = strength[0];
1653
1654 cnt = 0;
1655
1656 if (levels)
1657 {
1658 if (strength[cnt] == BIDI_STRONG)
1659 layoutRTL = odd(layout_levels[cnt]);
1660 else
1661 layoutRTL = (psState->uBidiLevel || odd(layout_levels[cnt]));
1662 if (overrides)
1663 pItems[index].a.s.fOverrideDirection = (overrides[cnt] != 0);
1664 pItems[index].a.fRTL = odd(levels[cnt]);
1665 if (script_is_numeric(pItems[index].a.eScript))
1666 pItems[index].a.fLayoutRTL = layoutRTL;
1667 else
1668 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1669 pItems[index].a.s.uBidiLevel = levels[cnt];
1670 }
1671 else if (!pItems[index].a.s.uBidiLevel || (overrides && overrides[cnt]))
1672 {
1673 if (pItems[index].a.s.uBidiLevel != baselevel)
1674 pItems[index].a.s.fOverrideDirection = TRUE;
1675 layoutRTL = odd(baselayout);
1676 pItems[index].a.s.uBidiLevel = baselevel;
1677 pItems[index].a.fRTL = odd(baselevel);
1678 if (script_is_numeric(pItems[index].a.eScript))
1679 pItems[index].a.fLayoutRTL = odd(baselayout);
1680 else
1681 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1682 }
1683
1684 TRACE("New_Level=%i New_Strength=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n",
1685 levels?levels[cnt]:-1, str, New_Script, pItems[index].a.eScript, index, cnt,
1686 pItems[index].iCharPos);
1687
1688 for (cnt=1; cnt < cInChars; cnt++)
1689 {
1690 if(pwcInChars[cnt] != Numeric_space)
1691 New_Script = scripts[cnt];
1692 else if (levels)
1693 {
1694 int j = 1;
1695 while (cnt + j < cInChars - 1 && pwcInChars[cnt+j] == Numeric_space && levels[cnt] == levels[cnt+j])
1696 j++;
1697 if (cnt + j < cInChars && levels[cnt] == levels[cnt+j])
1698 New_Script = scripts[cnt+j];
1699 else
1700 New_Script = scripts[cnt];
1701 }
1702
1703 new_run = FALSE;
1704 /* merge space strengths*/
1705 if (strength && strength[cnt] == BIDI_STRONG && str != BIDI_STRONG && New_Script == pItems[index].a.eScript)
1706 str = BIDI_STRONG;
1707
1708 if (strength && strength[cnt] == BIDI_NEUTRAL && str == BIDI_STRONG && pwcInChars[cnt] != Numeric_space && New_Script == pItems[index].a.eScript)
1709 str = BIDI_NEUTRAL;
1710
1711 /* changes in level */
1712 if (levels && (levels[cnt] != pItems[index].a.s.uBidiLevel))
1713 {
1714 TRACE("Level break(%i/%i)\n",pItems[index].a.s.uBidiLevel,levels[cnt]);
1715 new_run = TRUE;
1716 }
1717 /* changes in strength */
1718 else if (strength && pwcInChars[cnt] != Numeric_space && str != strength[cnt])
1719 {
1720 TRACE("Strength break (%i/%i)\n",str,strength[cnt]);
1721 new_run = TRUE;
1722 }
1723 /* changes in script */
1724 else if (((pwcInChars[cnt] != Numeric_space) && (New_Script != -1) && (New_Script != pItems[index].a.eScript)) || (New_Script == Script_Control))
1725 {
1726 TRACE("Script break(%i/%i)\n",pItems[index].a.eScript,New_Script);
1727 new_run = TRUE;
1728 }
1729
1730 if (!new_run && strength && str == BIDI_STRONG)
1731 {
1732 layoutRTL = odd(layout_levels[cnt]);
1733 if (script_is_numeric(pItems[index].a.eScript))
1734 pItems[index].a.fLayoutRTL = layoutRTL;
1735 }
1736
1737 if (new_run)
1738 {
1739 TRACE("New_Level = %i, New_Strength = %i, New_Script=%d, eScript=%d\n", levels?levels[cnt]:-1, strength?strength[cnt]:str, New_Script, pItems[index].a.eScript);
1740
1741 index++;
1742 if (index+1 > cMaxItems)
1743 goto nomemory;
1744
1745 if (strength)
1746 str = strength[cnt];
1747
1748 pItems[index].iCharPos = cnt;
1749 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
1750
1751 pItems[index].a = scriptInformation[New_Script].a;
1752 if (pScriptTags)
1754 if (levels)
1755 {
1756 if (overrides)
1757 pItems[index].a.s.fOverrideDirection = (overrides[cnt] != 0);
1758 if (layout_levels[cnt] == 0)
1759 layoutRTL = 0;
1760 else
1761 layoutRTL = (layoutRTL || odd(layout_levels[cnt]));
1762 pItems[index].a.fRTL = odd(levels[cnt]);
1763 if (script_is_numeric(pItems[index].a.eScript))
1764 pItems[index].a.fLayoutRTL = layoutRTL;
1765 else
1766 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1767 pItems[index].a.s.uBidiLevel = levels[cnt];
1768 }
1769 else if (!pItems[index].a.s.uBidiLevel || (overrides && overrides[cnt]))
1770 {
1771 if (pItems[index].a.s.uBidiLevel != baselevel)
1772 pItems[index].a.s.fOverrideDirection = TRUE;
1773 pItems[index].a.s.uBidiLevel = baselevel;
1774 pItems[index].a.fRTL = odd(baselevel);
1775 if (script_is_numeric(pItems[index].a.eScript))
1776 pItems[index].a.fLayoutRTL = layoutRTL;
1777 else
1778 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1779 }
1780
1781 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos);
1782 }
1783 }
1784
1785 /* While not strictly necessary according to the spec, make sure the n+1
1786 * item is set up to prevent random behaviour if the caller erroneously
1787 * checks the n+1 structure */
1788 index++;
1789 if (index + 1 > cMaxItems) goto nomemory;
1790 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
1791
1792 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos);
1793
1794 /* Set one SCRIPT_STATE item being returned */
1795 if (pcItems) *pcItems = index;
1796
1797 /* Set SCRIPT_ITEM */
1798 pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */
1799 res = S_OK;
1800nomemory:
1802 heap_free(overrides);
1803 heap_free(layout_levels);
1804 heap_free(strength);
1805 heap_free(scripts);
1806 return res;
1807}
1808
1809/***********************************************************************
1810 * ScriptItemizeOpenType (USP10.@)
1811 *
1812 * Split a Unicode string into shapeable parts.
1813 *
1814 * PARAMS
1815 * pwcInChars [I] String to split.
1816 * cInChars [I] Number of characters in pwcInChars.
1817 * cMaxItems [I] Maximum number of items to return.
1818 * psControl [I] Pointer to a SCRIPT_CONTROL structure.
1819 * psState [I] Pointer to a SCRIPT_STATE structure.
1820 * pItems [O] Buffer to receive SCRIPT_ITEM structures.
1821 * pScriptTags [O] Buffer to receive OPENTYPE_TAGs.
1822 * pcItems [O] Number of script items returned.
1823 *
1824 * RETURNS
1825 * Success: S_OK
1826 * Failure: Non-zero HRESULT value.
1827 */
1831{
1833}
1834
1835/***********************************************************************
1836 * ScriptItemize (USP10.@)
1837 *
1838 * Split a Unicode string into shapeable parts.
1839 *
1840 * PARAMS
1841 * pwcInChars [I] String to split.
1842 * cInChars [I] Number of characters in pwcInChars.
1843 * cMaxItems [I] Maximum number of items to return.
1844 * psControl [I] Pointer to a SCRIPT_CONTROL structure.
1845 * psState [I] Pointer to a SCRIPT_STATE structure.
1846 * pItems [O] Buffer to receive SCRIPT_ITEM structures.
1847 * pcItems [O] Number of script items returned.
1848 *
1849 * RETURNS
1850 * Success: S_OK
1851 * Failure: Non-zero HRESULT value.
1852 */
1855 SCRIPT_ITEM *pItems, int *pcItems)
1856{
1858}
1859
1860static inline int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x)
1861{
1862 int defWidth;
1863 int cTabStops=0;
1864 INT *lpTabPos = NULL;
1865 INT nTabOrg = 0;
1866 INT x = 0;
1867
1868 if (pTabdef)
1869 lpTabPos = pTabdef->pTabStops;
1870
1871 if (pTabdef && pTabdef->iTabOrigin)
1872 {
1873 if (pTabdef->iScale)
1874 nTabOrg = (pTabdef->iTabOrigin * pTabdef->iScale)/4;
1875 else
1876 nTabOrg = pTabdef->iTabOrigin * psc->tm.tmAveCharWidth;
1877 }
1878
1879 if (pTabdef)
1880 cTabStops = pTabdef->cTabStops;
1881
1882 if (cTabStops == 1)
1883 {
1884 if (pTabdef->iScale)
1885 defWidth = ((pTabdef->pTabStops[0])*pTabdef->iScale) / 4;
1886 else
1887 defWidth = (pTabdef->pTabStops[0])*psc->tm.tmAveCharWidth;
1888 cTabStops = 0;
1889 }
1890 else
1891 {
1892 if (pTabdef->iScale)
1893 defWidth = (32 * pTabdef->iScale) / 4;
1894 else
1895 defWidth = 8 * psc->tm.tmAveCharWidth;
1896 }
1897
1898 for (; cTabStops>0 ; lpTabPos++, cTabStops--)
1899 {
1900 int position = *lpTabPos;
1901 if (position < 0)
1902 position = -1 * position;
1903 if (pTabdef->iScale)
1904 position = (position * pTabdef->iScale) / 4;
1905 else
1906 position = position * psc->tm.tmAveCharWidth;
1907
1908 if( nTabOrg + position > current_x)
1909 {
1910 if( position >= 0)
1911 {
1912 /* a left aligned tab */
1913 x = (nTabOrg + position) - current_x;
1914 break;
1915 }
1916 else
1917 {
1918 FIXME("Negative tabstop\n");
1919 break;
1920 }
1921 }
1922 }
1923 if ((!cTabStops) && (defWidth > 0))
1924 x =((((current_x - nTabOrg) / defWidth)+1) * defWidth) - current_x;
1925 else if ((!cTabStops) && (defWidth < 0))
1926 FIXME("TODO: Negative defWidth\n");
1927
1928 return x;
1929}
1930
1931/***********************************************************************
1932 * Helper function for ScriptStringAnalyse
1933 */
1935 const WCHAR *pwcInChars, int cChars )
1936{
1937 /* FIXME: When to properly fallback is still a bit of a mystery */
1938 WORD *glyphs;
1939
1940 if (psa->fNoGlyphIndex)
1941 return FALSE;
1942
1943 if (init_script_cache(hdc, psc) != S_OK)
1944 return FALSE;
1945
1947 return TRUE;
1948
1949 if (!(glyphs = heap_calloc(cChars, sizeof(*glyphs))))
1950 return FALSE;
1951 if (ScriptGetCMap(hdc, psc, pwcInChars, cChars, 0, glyphs) != S_OK)
1952 {
1954 return TRUE;
1955 }
1957
1958 return FALSE;
1959}
1960
1961static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName)
1962{
1963 HKEY hkey;
1964
1965 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Uniscribe\\Fallback", &hkey))
1966 {
1967 static const WCHAR szFmt[] = {'%','x',0};
1968 WCHAR value[10];
1969 DWORD count = LF_FACESIZE * sizeof(WCHAR);
1970 DWORD type;
1971
1972 swprintf(value, szFmt, scriptInformation[scriptid].scriptTag);
1973 if (RegQueryValueExW(hkey, value, 0, &type, (BYTE *)FaceName, &count))
1974 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont);
1975 RegCloseKey(hkey);
1976 }
1977 else
1978 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont);
1979}
1980
1981/***********************************************************************
1982 * ScriptStringAnalyse (USP10.@)
1983 *
1984 */
1986 int cGlyphs, int iCharset, DWORD dwFlags,
1987 int iReqWidth, SCRIPT_CONTROL *psControl,
1988 SCRIPT_STATE *psState, const int *piDx,
1989 SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass,
1991{
1993 StringAnalysis *analysis = NULL;
1994 SCRIPT_CONTROL sControl;
1995 SCRIPT_STATE sState;
1996 int i, num_items = 255;
1997 BYTE *BidiLevel;
1998 WCHAR *iString = NULL;
1999
2000 TRACE("(%p,%p,%d,%d,%d,0x%x,%d,%p,%p,%p,%p,%p,%p)\n",
2001 hdc, pString, cString, cGlyphs, iCharset, dwFlags, iReqWidth,
2002 psControl, psState, piDx, pTabdef, pbInClass, pssa);
2003
2004 if (iCharset != -1)
2005 {
2006 FIXME("Only Unicode strings are supported\n");
2007 return E_INVALIDARG;
2008 }
2009 if (cString < 1 || !pString) return E_INVALIDARG;
2010 if ((dwFlags & SSA_GLYPHS) && !hdc) return E_PENDING;
2011
2012 if (!(analysis = heap_alloc_zero(sizeof(*analysis))))
2013 return E_OUTOFMEMORY;
2014 if (!(analysis->pItem = heap_calloc(num_items + 1, sizeof(*analysis->pItem))))
2015 goto error;
2016
2017 /* FIXME: handle clipping */
2018 analysis->clip_len = cString;
2019 analysis->hdc = hdc;
2020 analysis->ssa_flags = dwFlags;
2021
2022 if (psState)
2023 sState = *psState;
2024 else
2025 memset(&sState, 0, sizeof(SCRIPT_STATE));
2026
2027 if (psControl)
2028 sControl = *psControl;
2029 else
2030 memset(&sControl, 0, sizeof(SCRIPT_CONTROL));
2031
2032 if (dwFlags & SSA_PASSWORD)
2033 {
2034 if (!(iString = heap_calloc(cString, sizeof(*iString))))
2035 {
2036 hr = E_OUTOFMEMORY;
2037 goto error;
2038 }
2039 for (i = 0; i < cString; i++)
2040 iString[i] = *((const WCHAR *)pString);
2041 pString = iString;
2042 }
2043
2044 hr = ScriptItemize(pString, cString, num_items, &sControl, &sState, analysis->pItem,
2045 &analysis->numItems);
2046
2047 if (FAILED(hr))
2048 {
2049 if (hr == E_OUTOFMEMORY)
2050 hr = E_INVALIDARG;
2051 goto error;
2052 }
2053
2054 /* set back to out of memory for default goto error behaviour */
2055 hr = E_OUTOFMEMORY;
2056
2057 if (dwFlags & SSA_BREAK)
2058 {
2059 if (!(analysis->logattrs = heap_calloc(cString, sizeof(*analysis->logattrs))))
2060 goto error;
2061
2062 for (i = 0; i < analysis->numItems; ++i)
2063 ScriptBreak(&((const WCHAR *)pString)[analysis->pItem[i].iCharPos],
2064 analysis->pItem[i + 1].iCharPos - analysis->pItem[i].iCharPos,
2065 &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]);
2066 }
2067
2068 if (!(analysis->logical2visual = heap_calloc(analysis->numItems, sizeof(*analysis->logical2visual))))
2069 goto error;
2070 if (!(BidiLevel = heap_alloc_zero(analysis->numItems)))
2071 goto error;
2072
2073 if (dwFlags & SSA_GLYPHS)
2074 {
2075 int tab_x = 0;
2076
2077 if (!(analysis->glyphs = heap_calloc(analysis->numItems, sizeof(*analysis->glyphs))))
2078 {
2079 heap_free(BidiLevel);
2080 goto error;
2081 }
2082
2083 for (i = 0; i < analysis->numItems; i++)
2084 {
2085 SCRIPT_CACHE *sc = (SCRIPT_CACHE*)&analysis->glyphs[i].sc;
2086 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2087 int numGlyphs = 1.5 * cChar + 16;
2088 WORD *glyphs = heap_calloc(numGlyphs, sizeof(*glyphs));
2089 WORD *pwLogClust = heap_calloc(cChar, sizeof(*pwLogClust));
2090 int *piAdvance = heap_calloc(numGlyphs, sizeof(*piAdvance));
2091 SCRIPT_VISATTR *psva = heap_calloc(numGlyphs, sizeof(*psva));
2092 GOFFSET *pGoffset = heap_calloc(numGlyphs, sizeof(*pGoffset));
2093 int numGlyphsReturned;
2094 HFONT originalFont = 0x0;
2095
2096 /* FIXME: non unicode strings */
2097 const WCHAR* pStr = (const WCHAR*)pString;
2098 analysis->glyphs[i].fallbackFont = NULL;
2099
2100 if (!glyphs || !pwLogClust || !piAdvance || !psva || !pGoffset)
2101 {
2102 heap_free (BidiLevel);
2103 heap_free (glyphs);
2105 heap_free (piAdvance);
2106 heap_free (psva);
2107 heap_free (pGoffset);
2108 hr = E_OUTOFMEMORY;
2109 goto error;
2110 }
2111
2112 if ((dwFlags & SSA_FALLBACK) && requires_fallback(hdc, sc, &analysis->pItem[i].a, &pStr[analysis->pItem[i].iCharPos], cChar))
2113 {
2114 LOGFONTW lf;
2115 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), & lf);
2117 lf.lfFaceName[0] = 0;
2118 find_fallback_font(analysis->pItem[i].a.eScript, lf.lfFaceName);
2119 if (lf.lfFaceName[0])
2120 {
2121 analysis->glyphs[i].fallbackFont = CreateFontIndirectW(&lf);
2122 if (analysis->glyphs[i].fallbackFont)
2123 {
2124 ScriptFreeCache(sc);
2125 originalFont = SelectObject(hdc, analysis->glyphs[i].fallbackFont);
2126 }
2127 }
2128 }
2129
2130 /* FIXME: When we properly shape Hangul remove this check */
2131 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && analysis->pItem[i].a.eScript == Script_Hangul)
2132 analysis->pItem[i].a.fNoGlyphIndex = TRUE;
2133
2134 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex && !analysis->pItem[i].a.fRTL)
2135 analysis->pItem[i].a.fNoGlyphIndex = TRUE;
2136
2137 ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], cChar, numGlyphs,
2138 &analysis->pItem[i].a, glyphs, pwLogClust, psva, &numGlyphsReturned);
2139 hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a,
2140 piAdvance, pGoffset, &analysis->glyphs[i].abc);
2141 if (originalFont)
2142 SelectObject(hdc,originalFont);
2143
2144 if (dwFlags & SSA_TAB)
2145 {
2146 int tabi = 0;
2147 for (tabi = 0; tabi < cChar; tabi++)
2148 {
2149 if (pStr[analysis->pItem[i].iCharPos+tabi] == 0x0009)
2150 piAdvance[tabi] = getGivenTabWidth(analysis->glyphs[i].sc, pTabdef, analysis->pItem[i].iCharPos+tabi, tab_x);
2151 tab_x+=piAdvance[tabi];
2152 }
2153 }
2154
2155 analysis->glyphs[i].numGlyphs = numGlyphsReturned;
2156 analysis->glyphs[i].glyphs = glyphs;
2157 analysis->glyphs[i].pwLogClust = pwLogClust;
2158 analysis->glyphs[i].piAdvance = piAdvance;
2159 analysis->glyphs[i].psva = psva;
2160 analysis->glyphs[i].pGoffset = pGoffset;
2161 analysis->glyphs[i].iMaxPosX= -1;
2162
2163 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel;
2164 }
2165 }
2166 else
2167 {
2168 for (i = 0; i < analysis->numItems; i++)
2169 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel;
2170 }
2171
2172 ScriptLayout(analysis->numItems, BidiLevel, NULL, analysis->logical2visual);
2173 heap_free(BidiLevel);
2174
2175 *pssa = analysis;
2176 heap_free(iString);
2177 return S_OK;
2178
2179error:
2180 heap_free(iString);
2181 heap_free(analysis->glyphs);
2182 heap_free(analysis->logattrs);
2183 heap_free(analysis->pItem);
2184 heap_free(analysis->logical2visual);
2185 heap_free(analysis);
2186 return hr;
2187}
2188
2189static inline BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction)
2190{
2191 if (pva[glyph].fClusterStart)
2192 return TRUE;
2194 return TRUE;
2195
2196 return FALSE;
2197}
2198
2199
2201 int iX,
2202 int iY,
2203 int iItem,
2204 int cStart,
2205 int cEnd,
2206 UINT uOptions,
2207 const RECT *prc,
2208 BOOL fSelected,
2209 BOOL fDisabled)
2210{
2211 StringAnalysis *analysis;
2212 int off_x = 0;
2213 HRESULT hr;
2214 COLORREF BkColor = 0x0;
2215 COLORREF TextColor = 0x0;
2216 INT BkMode = 0;
2217 INT runStart, runEnd;
2218 INT iGlyph, cGlyphs;
2219 HFONT oldFont = 0x0;
2220 RECT crc;
2221 int i;
2222
2223 TRACE("(%p,%d,%d,%d,%d,%d, 0x%1x, %d, %d)\n",
2224 ssa, iX, iY, iItem, cStart, cEnd, uOptions, fSelected, fDisabled);
2225
2226 if (!(analysis = ssa)) return E_INVALIDARG;
2227
2228 if ((cStart >= 0 && analysis->pItem[iItem+1].iCharPos <= cStart) ||
2229 (cEnd >= 0 && analysis->pItem[iItem].iCharPos >= cEnd))
2230 return S_OK;
2231
2232 CopyRect(&crc,prc);
2233 if (fSelected)
2234 {
2235 BkMode = GetBkMode(analysis->hdc);
2236 SetBkMode( analysis->hdc, OPAQUE);
2237 BkColor = GetBkColor(analysis->hdc);
2239 if (!fDisabled)
2240 {
2241 TextColor = GetTextColor(analysis->hdc);
2243 }
2244 }
2245 if (analysis->glyphs[iItem].fallbackFont)
2246 oldFont = SelectObject(analysis->hdc, analysis->glyphs[iItem].fallbackFont);
2247
2248 if (cStart >= 0 && analysis->pItem[iItem+1].iCharPos > cStart && analysis->pItem[iItem].iCharPos <= cStart)
2249 runStart = cStart - analysis->pItem[iItem].iCharPos;
2250 else
2251 runStart = 0;
2252 if (cEnd >= 0 && analysis->pItem[iItem+1].iCharPos > cEnd && analysis->pItem[iItem].iCharPos <= cEnd)
2253 runEnd = (cEnd-1) - analysis->pItem[iItem].iCharPos;
2254 else
2255 runEnd = (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos) - 1;
2256
2257 if (analysis->pItem[iItem].a.fRTL)
2258 {
2259 if (cEnd >= 0 && cEnd < analysis->pItem[iItem+1].iCharPos)
2260 ScriptStringCPtoX(ssa, cEnd, FALSE, &off_x);
2261 else
2262 ScriptStringCPtoX(ssa, analysis->pItem[iItem+1].iCharPos-1, TRUE, &off_x);
2263 crc.left = iX + off_x;
2264 }
2265 else
2266 {
2267 if (cStart >=0 && runStart)
2268 ScriptStringCPtoX(ssa, cStart, FALSE, &off_x);
2269 else
2270 ScriptStringCPtoX(ssa, analysis->pItem[iItem].iCharPos, FALSE, &off_x);
2271 crc.left = iX + off_x;
2272 }
2273
2274 if (analysis->pItem[iItem].a.fRTL)
2275 iGlyph = analysis->glyphs[iItem].pwLogClust[runEnd];
2276 else
2277 iGlyph = analysis->glyphs[iItem].pwLogClust[runStart];
2278
2279 if (analysis->pItem[iItem].a.fRTL)
2280 cGlyphs = analysis->glyphs[iItem].pwLogClust[runStart] - iGlyph;
2281 else
2282 cGlyphs = analysis->glyphs[iItem].pwLogClust[runEnd] - iGlyph;
2283
2284 cGlyphs++;
2285
2286 /* adjust for cluster glyphs when starting */
2287 if (analysis->pItem[iItem].a.fRTL)
2288 i = analysis->pItem[iItem+1].iCharPos - 1;
2289 else
2290 i = analysis->pItem[iItem].iCharPos;
2291
2292 for (; i >=analysis->pItem[iItem].iCharPos && i < analysis->pItem[iItem+1].iCharPos; (analysis->pItem[iItem].a.fRTL)?i--:i++)
2293 {
2294 if (analysis->glyphs[iItem].pwLogClust[i - analysis->pItem[iItem].iCharPos] == iGlyph)
2295 {
2296 if (analysis->pItem[iItem].a.fRTL)
2297 ScriptStringCPtoX(ssa, i, TRUE, &off_x);
2298 else
2299 ScriptStringCPtoX(ssa, i, FALSE, &off_x);
2300 break;
2301 }
2302 }
2303
2304 if (cEnd < 0 || scriptInformation[analysis->pItem[iItem].a.eScript].props.fNeedsCaretInfo)
2305 {
2306 INT direction;
2307 INT clust_glyph;
2308
2309 clust_glyph = iGlyph + cGlyphs;
2310 if (analysis->pItem[iItem].a.fRTL)
2311 direction = -1;
2312 else
2313 direction = 1;
2314
2315 while(clust_glyph < analysis->glyphs[iItem].numGlyphs &&
2316 !does_glyph_start_cluster(analysis->glyphs[iItem].psva, analysis->glyphs[iItem].pwLogClust, (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos), clust_glyph, direction))
2317 {
2318 cGlyphs++;
2319 clust_glyph++;
2320 }
2321 }
2322
2323 hr = ScriptTextOut(analysis->hdc,
2324 (SCRIPT_CACHE *)&analysis->glyphs[iItem].sc, iX + off_x,
2325 iY, uOptions, &crc, &analysis->pItem[iItem].a, NULL, 0,
2326 &analysis->glyphs[iItem].glyphs[iGlyph], cGlyphs,
2327 &analysis->glyphs[iItem].piAdvance[iGlyph], NULL,
2328 &analysis->glyphs[iItem].pGoffset[iGlyph]);
2329
2330 TRACE("ScriptTextOut hr=%08x\n", hr);
2331
2332 if (fSelected)
2333 {
2334 SetBkColor(analysis->hdc, BkColor);
2335 SetBkMode( analysis->hdc, BkMode);
2336 if (!fDisabled)
2337 SetTextColor(analysis->hdc, TextColor);
2338 }
2339 if (analysis->glyphs[iItem].fallbackFont)
2340 SelectObject(analysis->hdc, oldFont);
2341
2342 return hr;
2343}
2344
2345/***********************************************************************
2346 * ScriptStringOut (USP10.@)
2347 *
2348 * This function takes the output of ScriptStringAnalyse and joins the segments
2349 * of glyphs and passes the resulting string to ScriptTextOut. ScriptStringOut
2350 * only processes glyphs.
2351 *
2352 * Parameters:
2353 * ssa [I] buffer to hold the analysed string components
2354 * iX [I] X axis displacement for output
2355 * iY [I] Y axis displacement for output
2356 * uOptions [I] flags controlling output processing
2357 * prc [I] rectangle coordinates
2358 * iMinSel [I] starting pos for substringing output string
2359 * iMaxSel [I] ending pos for substringing output string
2360 * fDisabled [I] controls text highlighting
2361 *
2362 * RETURNS
2363 * Success: S_OK
2364 * Failure: is the value returned by ScriptTextOut
2365 */
2367 int iX,
2368 int iY,
2369 UINT uOptions,
2370 const RECT *prc,
2371 int iMinSel,
2372 int iMaxSel,
2373 BOOL fDisabled)
2374{
2375 StringAnalysis *analysis;
2376 int item;
2377 HRESULT hr;
2378
2379 TRACE("(%p,%d,%d,0x%08x,%s,%d,%d,%d)\n",
2380 ssa, iX, iY, uOptions, wine_dbgstr_rect(prc), iMinSel, iMaxSel, fDisabled);
2381
2382 if (!(analysis = ssa)) return E_INVALIDARG;
2383 if (!(analysis->ssa_flags & SSA_GLYPHS)) return E_INVALIDARG;
2384
2385 for (item = 0; item < analysis->numItems; item++)
2386 {
2387 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], -1, -1, uOptions, prc, FALSE, fDisabled);
2388 if (FAILED(hr))
2389 return hr;
2390 }
2391
2392 if (iMinSel < iMaxSel && (iMinSel > 0 || iMaxSel > 0))
2393 {
2394 if (iMaxSel > 0 && iMinSel < 0)
2395 iMinSel = 0;
2396 for (item = 0; item < analysis->numItems; item++)
2397 {
2398 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], iMinSel, iMaxSel, uOptions, prc, TRUE, fDisabled);
2399 if (FAILED(hr))
2400 return hr;
2401 }
2402 }
2403
2404 return S_OK;
2405}
2406
2407/***********************************************************************
2408 * ScriptStringCPtoX (USP10.@)
2409 *
2410 */
2412{
2413 int item;
2414 int runningX = 0;
2415 StringAnalysis* analysis = ssa;
2416
2417 TRACE("(%p), %d, %d, (%p)\n", ssa, icp, fTrailing, pX);
2418
2419 if (!ssa || !pX) return S_FALSE;
2420 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
2421
2422 /* icp out of range */
2423 if(icp < 0)
2424 {
2426 return E_INVALIDARG;
2427 }
2428
2429 for(item=0; item<analysis->numItems; item++)
2430 {
2431 int CP, i;
2432 int offset;
2433
2434 i = analysis->logical2visual[item];
2435 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2436 /* initialize max extents for uninitialized runs */
2437 if (analysis->glyphs[i].iMaxPosX == -1)
2438 {
2439 if (analysis->pItem[i].a.fRTL)
2440 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2441 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2442 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2443 else
2444 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2445 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2446 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2447 }
2448
2449 if (icp >= analysis->pItem[i+1].iCharPos || icp < analysis->pItem[i].iCharPos)
2450 {
2451 runningX += analysis->glyphs[i].iMaxPosX;
2452 continue;
2453 }
2454
2455 icp -= analysis->pItem[i].iCharPos;
2456 ScriptCPtoX(icp, fTrailing, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2457 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2458 &analysis->pItem[i].a, &offset);
2459 runningX += offset;
2460
2461 *pX = runningX;
2462 return S_OK;
2463 }
2464
2465 /* icp out of range */
2467 return E_INVALIDARG;
2468}
2469
2470/***********************************************************************
2471 * ScriptStringXtoCP (USP10.@)
2472 *
2473 */
2474HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing)
2475{
2476 StringAnalysis* analysis = ssa;
2477 int item;
2478
2479 TRACE("(%p), %d, (%p), (%p)\n", ssa, iX, piCh, piTrailing);
2480
2481 if (!ssa || !piCh || !piTrailing) return S_FALSE;
2482 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
2483
2484 /* out of range */
2485 if(iX < 0)
2486 {
2487 if (analysis->pItem[0].a.fRTL)
2488 {
2489 *piCh = 1;
2490 *piTrailing = FALSE;
2491 }
2492 else
2493 {
2494 *piCh = -1;
2495 *piTrailing = TRUE;
2496 }
2497 return S_OK;
2498 }
2499
2500 for(item=0; item<analysis->numItems; item++)
2501 {
2502 int i;
2503 int CP;
2504
2505 for (i = 0; i < analysis->numItems && analysis->logical2visual[i] != item; i++)
2506 /* nothing */;
2507
2508 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2509 /* initialize max extents for uninitialized runs */
2510 if (analysis->glyphs[i].iMaxPosX == -1)
2511 {
2512 if (analysis->pItem[i].a.fRTL)
2513 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2514 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2515 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2516 else
2517 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2518 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2519 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2520 }
2521
2522 if (iX > analysis->glyphs[i].iMaxPosX)
2523 {
2524 iX -= analysis->glyphs[i].iMaxPosX;
2525 continue;
2526 }
2527
2528 ScriptXtoCP(iX, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2529 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2530 &analysis->pItem[i].a, piCh, piTrailing);
2531 *piCh += analysis->pItem[i].iCharPos;
2532
2533 return S_OK;
2534 }
2535
2536 /* out of range */
2537 *piCh = analysis->pItem[analysis->numItems].iCharPos;
2538 *piTrailing = FALSE;
2539
2540 return S_OK;
2541}
2542
2543
2544/***********************************************************************
2545 * ScriptStringFree (USP10.@)
2546 *
2547 * Free a string analysis.
2548 *
2549 * PARAMS
2550 * pssa [I] string analysis.
2551 *
2552 * RETURNS
2553 * Success: S_OK
2554 * Failure: Non-zero HRESULT value.
2555 */
2557{
2558 StringAnalysis* analysis;
2559 BOOL invalid;
2560 int i;
2561
2562 TRACE("(%p)\n", pssa);
2563
2564 if (!pssa || !(analysis = *pssa)) return E_INVALIDARG;
2565
2567
2568 if (analysis->glyphs)
2569 {
2570 for (i = 0; i < analysis->numItems; i++)
2571 {
2572 heap_free(analysis->glyphs[i].glyphs);
2573 heap_free(analysis->glyphs[i].pwLogClust);
2574 heap_free(analysis->glyphs[i].piAdvance);
2575 heap_free(analysis->glyphs[i].psva);
2576 heap_free(analysis->glyphs[i].pGoffset);
2577 if (analysis->glyphs[i].fallbackFont)
2578 DeleteObject(analysis->glyphs[i].fallbackFont);
2579 ScriptFreeCache((SCRIPT_CACHE *)&analysis->glyphs[i].sc);
2580 heap_free(analysis->glyphs[i].sc);
2581 }
2582 heap_free(analysis->glyphs);
2583 }
2584
2585 heap_free(analysis->pItem);
2586 heap_free(analysis->logattrs);
2587 heap_free(analysis->logical2visual);
2588 heap_free(analysis);
2589
2590 if (invalid) return E_INVALIDARG;
2591 return S_OK;
2592}
2593
2594static inline int get_cluster_size(const WORD *pwLogClust, int cChars, int item,
2595 int direction, int* iCluster, int *check_out)
2596{
2597 int clust_size = 1;
2598 int check;
2599 WORD clust = pwLogClust[item];
2600
2601 for (check = item+direction; check < cChars && check >= 0; check+=direction)
2602 {
2603 if (pwLogClust[check] == clust)
2604 {
2605 clust_size ++;
2606 if (iCluster && *iCluster == -1)
2607 *iCluster = item;
2608 }
2609 else break;
2610 }
2611
2612 if (check_out)
2613 *check_out = check;
2614
2615 return clust_size;
2616}
2617
2618static inline int get_glyph_cluster_advance(const int* piAdvance, const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cGlyphs, int cChars, int glyph, int direction)
2619{
2620 int advance;
2621 int log_clust_max;
2622
2623 advance = piAdvance[glyph];
2624
2625 if (pwLogClust[0] > pwLogClust[cChars-1])
2626 log_clust_max = pwLogClust[0];
2627 else
2628 log_clust_max = pwLogClust[cChars-1];
2629
2630 if (glyph > log_clust_max)
2631 return advance;
2632
2633 for (glyph+=direction; glyph < cGlyphs && glyph >= 0; glyph +=direction)
2634 {
2635
2636 if (does_glyph_start_cluster(pva, pwLogClust, cChars, glyph, direction))
2637 break;
2638 if (glyph > log_clust_max)
2639 break;
2640 advance += piAdvance[glyph];
2641 }
2642
2643 return advance;
2644}
2645
2646/***********************************************************************
2647 * ScriptCPtoX (USP10.@)
2648 *
2649 */
2651 BOOL fTrailing,
2652 int cChars,
2653 int cGlyphs,
2654 const WORD *pwLogClust,
2655 const SCRIPT_VISATTR *psva,
2656 const int *piAdvance,
2657 const SCRIPT_ANALYSIS *psa,
2658 int *piX)
2659{
2660 int item;
2661 float iPosX;
2662 int iSpecial = -1;
2663 int iCluster = -1;
2664 int clust_size = 1;
2665 float special_size = 0.0;
2666 int iMaxPos = 0;
2667 int advance = 0;
2668 BOOL rtl = FALSE;
2669
2670 TRACE("(%d,%d,%d,%d,%p,%p,%p,%p,%p)\n",
2671 iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance,
2672 psa, piX);
2673
2674 if (psa->fRTL && ! psa->fLogicalOrder)
2675 rtl = TRUE;
2676
2677 if (fTrailing)
2678 iCP++;
2679
2680 if (rtl)
2681 {
2682 int max_clust = pwLogClust[0];
2683
2684 for (item=0; item < cGlyphs; item++)
2685 if (pwLogClust[item] > max_clust)
2686 {
2687 ERR("We do not handle non reversed clusters properly\n");
2688 break;
2689 }
2690
2691 iMaxPos = 0;
2692 for (item = max_clust; item >=0; item --)
2693 iMaxPos += piAdvance[item];
2694 }
2695
2696 iPosX = 0.0;
2697 for (item=0; item < iCP && item < cChars; item++)
2698 {
2699 if (iSpecial == -1 && (iCluster == -1 || iCluster+clust_size <= item))
2700 {
2701 int check;
2702 int clust = pwLogClust[item];
2703
2704 iCluster = -1;
2705 clust_size = get_cluster_size(pwLogClust, cChars, item, 1, &iCluster,
2706 &check);
2707
2708 advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, 1);
2709
2710 if (check >= cChars && !iMaxPos)
2711 {
2712 int glyph;
2713 for (glyph = clust; glyph < cGlyphs; glyph++)
2714 special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, glyph, 1);
2715 iSpecial = item;
2716 special_size /= (cChars - item);
2717 iPosX += special_size;
2718 }
2719 else
2720 {
2722 {
2723 clust_size --;
2724 if (clust_size == 0)
2725 iPosX += advance;
2726 }
2727 else
2728 iPosX += advance / (float)clust_size;
2729 }
2730 }
2731 else if (iSpecial != -1)
2732 iPosX += special_size;
2733 else /* (iCluster != -1) */
2734 {
2735 int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], 1);
2737 {
2738 clust_size --;
2739 if (clust_size == 0)
2740 iPosX += adv;
2741 }
2742 else
2743 iPosX += adv / (float)clust_size;
2744 }
2745 }
2746
2747 if (iMaxPos > 0)
2748 {
2749 iPosX = iMaxPos - iPosX;
2750 if (iPosX < 0)
2751 iPosX = 0;
2752 }
2753
2754 *piX = iPosX;
2755 TRACE("*piX=%d\n", *piX);
2756 return S_OK;
2757}
2758
2759/* Count the number of characters in a cluster and its starting index*/
2760static inline BOOL get_cluster_data(const WORD *pwLogClust, int cChars, int cluster_index, int *cluster_size, int *start_index)
2761{
2762 int size = 0;
2763 int i;
2764
2765 for (i = 0; i < cChars; i++)
2766 {
2767 if (pwLogClust[i] == cluster_index)
2768 {
2769 if (!size && start_index)
2770 {
2771 *start_index = i;
2772 if (!cluster_size)
2773 return TRUE;
2774 }
2775 size++;
2776 }
2777 else if (size) break;
2778 }
2779 if (cluster_size)
2780 *cluster_size = size;
2781
2782 return (size > 0);
2783}
2784
2785/*
2786 To handle multi-glyph clusters we need to find all the glyphs that are
2787 represented in the cluster. This involves finding the glyph whose
2788 index is the cluster index as well as whose glyph indices are greater than
2789 our cluster index but not part of a new cluster.
2790
2791 Then we sum all those glyphs' advances.
2792*/
2793static inline int get_cluster_advance(const int* piAdvance,
2794 const SCRIPT_VISATTR *psva,
2795 const WORD *pwLogClust, int cGlyphs,
2796 int cChars, int cluster, int direction)
2797{
2798 int glyph_start;
2799 int glyph_end;
2800 int i, advance;
2801
2802 if (direction > 0)
2803 i = 0;
2804 else
2805 i = (cChars - 1);
2806
2807 for (glyph_start = -1, glyph_end = -1; i < cChars && i >= 0 && (glyph_start < 0 || glyph_end < 0); i+=direction)
2808 {
2809 if (glyph_start < 0 && pwLogClust[i] != cluster) continue;
2810 if (pwLogClust[i] == cluster && glyph_start < 0) glyph_start = pwLogClust[i];
2811 if (glyph_start >= 0 && glyph_end < 0 && pwLogClust[i] != cluster) glyph_end = pwLogClust[i];
2812 }
2813 if (glyph_end < 0)
2814 {
2815 if (direction > 0)
2816 glyph_end = cGlyphs;
2817 else
2818 {
2819 /* Don't fully understand multi-glyph reversed clusters yet,
2820 * do they occur for real or just in our test? */
2821 FIXME("multi-glyph reversed clusters found\n");
2822 glyph_end = glyph_start + 1;
2823 }
2824 }
2825
2826 /* Check for fClusterStart, finding this generally would mean a malformed set of data */
2827 for (i = glyph_start+1; i< glyph_end; i++)
2828 {
2829 if (psva[i].fClusterStart)
2830 {
2831 glyph_end = i;
2832 break;
2833 }
2834 }
2835
2836 for (advance = 0, i = glyph_start; i < glyph_end; i++)
2837 advance += piAdvance[i];
2838
2839 return advance;
2840}
2841
2842
2843/***********************************************************************
2844 * ScriptXtoCP (USP10.@)
2845 *
2846 * Basic algorithm :
2847 * Use piAdvance to find the cluster we are looking at.
2848 * Find the character that is the first character of the cluster.
2849 * That is our base piCP.
2850 * If the script snaps to cluster boundaries (Hebrew, Indic, Thai) then we
2851 * are good. Otherwise if the cluster is larger than 1 glyph we need to
2852 * determine how far through the cluster to advance the cursor.
2853 */
2855 int cChars,
2856 int cGlyphs,
2857 const WORD *pwLogClust,
2858 const SCRIPT_VISATTR *psva,
2859 const int *piAdvance,
2860 const SCRIPT_ANALYSIS *psa,
2861 int *piCP,
2862 int *piTrailing)
2863{
2864 int direction = 1;
2865 int iPosX;
2866 int i;
2867 int glyph_index, cluster_index;
2868 int cluster_size;
2869
2870 TRACE("(%d,%d,%d,%p,%p,%p,%p,%p,%p)\n",
2871 iX, cChars, cGlyphs, pwLogClust, psva, piAdvance,
2872 psa, piCP, piTrailing);
2873
2874 if (psa->fRTL && ! psa->fLogicalOrder)
2875 direction = -1;
2876
2877 /* Handle an iX < 0 */
2878 if (iX < 0)
2879 {
2880 if (direction < 0)
2881 {
2882 *piCP = cChars;
2883 *piTrailing = 0;
2884 }
2885 else
2886 {
2887 *piCP = -1;
2888 *piTrailing = 1;
2889 }
2890 return S_OK;
2891 }
2892
2893 /* Looking for non-reversed clusters in a reversed string */
2894 if (direction < 0)
2895 {
2896 int max_clust = pwLogClust[0];
2897 for (i=0; i< cChars; i++)
2898 if (pwLogClust[i] > max_clust)
2899 {
2900 FIXME("We do not handle non reversed clusters properly\n");
2901 break;
2902 }
2903 }
2904
2905 /* find the glyph_index based in iX */
2906 if (direction > 0)
2907 {
2908 for (glyph_index = -1, iPosX = iX; iPosX >=0 && glyph_index < cGlyphs; iPosX -= piAdvance[glyph_index+1], glyph_index++)
2909 ;
2910 }
2911 else
2912 {
2913 for (glyph_index = -1, iPosX = iX; iPosX > 0 && glyph_index < cGlyphs; iPosX -= piAdvance[glyph_index+1], glyph_index++)
2914 ;
2915 }
2916
2917 TRACE("iPosX %i -> glyph_index %i (%i)\n", iPosX, glyph_index, cGlyphs);
2918
2919 *piTrailing = 0;
2920 if (glyph_index >= 0 && glyph_index < cGlyphs)
2921 {
2922 /* find the cluster */
2923 if (direction > 0 )
2924 for (i = 0, cluster_index = pwLogClust[0]; i < cChars && pwLogClust[i] <= glyph_index; cluster_index=pwLogClust[i++])
2925 ;
2926 else
2927 for (i = 0, cluster_index = pwLogClust[0]; i < cChars && pwLogClust[i] >= glyph_index; cluster_index=pwLogClust[i++])
2928 ;
2929
2930 TRACE("cluster_index %i\n", cluster_index);
2931
2932 if (direction < 0 && iPosX >= 0 && glyph_index != cluster_index)
2933 {
2934 /* We are off the end of the string */
2935 *piCP = -1;
2936 *piTrailing = 1;
2937 return S_OK;
2938 }
2939
2940 get_cluster_data(pwLogClust, cChars, cluster_index, &cluster_size, &i);
2941
2942 TRACE("first char index %i\n",i);
2944 {
2945 /* Check trailing */
2946 if (glyph_index != cluster_index ||
2947 (direction > 0 && abs(iPosX) <= (piAdvance[glyph_index] / 2)) ||
2948 (direction < 0 && abs(iPosX) >= (piAdvance[glyph_index] / 2)))
2949 *piTrailing = cluster_size;
2950 }
2951 else
2952 {
2953 if (cluster_size > 1)
2954 {
2955 /* Be part way through the glyph cluster based on size and position */
2956 int cluster_advance = get_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, cluster_index, direction);
2957 double cluster_part_width = cluster_advance / (float)cluster_size;
2958 double adv;
2959 int part_index;
2960
2961 /* back up to the beginning of the cluster */
2962 for (adv = iPosX, part_index = cluster_index; part_index <= glyph_index; part_index++)
2963 adv += piAdvance[part_index];
2964 if (adv > iX) adv = iX;
2965
2966 TRACE("Multi-char cluster, no snap\n");
2967 TRACE("cluster size %i, pre-cluster iPosX %f\n",cluster_size, adv);
2968 TRACE("advance %i divides into %f per char\n", cluster_advance, cluster_part_width);
2969 if (direction > 0)
2970 {
2971 for (part_index = 0; adv >= 0; adv-=cluster_part_width, part_index++)
2972 ;
2973 if (part_index) part_index--;
2974 }
2975 else
2976 {
2977 for (part_index = 0; adv > 0; adv-=cluster_part_width, part_index++)
2978 ;
2979 if (part_index > cluster_size)
2980 {
2981 adv += cluster_part_width;
2982 part_index=cluster_size;
2983 }
2984 }
2985
2986 TRACE("base_char %i part_index %i, leftover advance %f\n",i, part_index, adv);
2987
2988 if (direction > 0)
2989 i += part_index;
2990 else
2991 i += (cluster_size - part_index);
2992
2993 /* Check trailing */
2994 if ((direction > 0 && fabs(adv) <= (cluster_part_width / 2.0)) ||
2995 (direction < 0 && adv && fabs(adv) >= (cluster_part_width / 2.0)))
2996 *piTrailing = 1;
2997 }
2998 else
2999 {
3000 /* Check trailing */
3001 if ((direction > 0 && abs(iPosX) <= (piAdvance[glyph_index] / 2)) ||
3002 (direction < 0 && abs(iPosX) >= (piAdvance[glyph_index] / 2)))
3003 *piTrailing = 1;
3004 }
3005 }
3006 }
3007 else
3008 {
3009 TRACE("Point falls outside of string\n");
3010 if (glyph_index < 0)
3011 i = cChars-1;
3012 else /* (glyph_index >= cGlyphs) */
3013 i = cChars;
3014
3015 /* If not snaping in the reverse direction (such as Hebrew) Then 0
3016 point flow to the next character */
3017 if (direction < 0)
3018 {
3019 if (!scriptInformation[psa->eScript].props.fNeedsCaretInfo && abs(iPosX) == piAdvance[glyph_index])
3020 i++;
3021 else
3022 *piTrailing = 1;
3023 }
3024 }
3025
3026 *piCP = i;
3027
3028 TRACE("*piCP=%d\n", *piCP);
3029 TRACE("*piTrailing=%d\n", *piTrailing);
3030 return S_OK;
3031}
3032
3033/***********************************************************************
3034 * ScriptBreak (USP10.@)
3035 *
3036 * Retrieve line break information.
3037 *
3038 * PARAMS
3039 * chars [I] Array of characters.
3040 * sa [I] Script analysis.
3041 * la [I] Array of logical attribute structures.
3042 *
3043 * RETURNS
3044 * Success: S_OK
3045 * Failure: S_FALSE
3046 */
3048{
3049 TRACE("(%s, %d, %p, %p)\n", debugstr_wn(chars, count), count, sa, la);
3050
3051 if (count < 0 || !la) return E_INVALIDARG;
3052 if (count == 0) return E_FAIL;
3053
3054 BREAK_line(chars, count, sa, la);
3055
3056 return S_OK;
3057}
3058
3059/***********************************************************************
3060 * ScriptIsComplex (USP10.@)
3061 *
3062 * Determine if a string is complex.
3063 *
3064 * PARAMS
3065 * chars [I] Array of characters to test.
3066 * len [I] Length in characters.
3067 * flag [I] Flag.
3068 *
3069 * RETURNS
3070 * Success: S_OK
3071 * Failure: S_FALSE
3072 *
3073 */
3075{
3076 enum usp10_script script;
3077 unsigned int i, consumed;
3078
3079 TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag);
3080
3081 if (!chars || len < 0)
3082 return E_INVALIDARG;
3083
3084 for (i = 0; i < len; i+=consumed)
3085 {
3086 if ((flag & SIC_ASCIIDIGIT) && chars[i] >= 0x30 && chars[i] <= 0x39)
3087 return S_OK;
3088
3089 script = get_char_script(chars,i,len, &consumed);
3090 if ((scriptInformation[script].props.fComplex && (flag & SIC_COMPLEX))||
3092 return S_OK;
3093 }
3094 return S_FALSE;
3095}
3096
3097/***********************************************************************
3098 * ScriptShapeOpenType (USP10.@)
3099 *
3100 * Produce glyphs and visual attributes for a run.
3101 *
3102 * PARAMS
3103 * hdc [I] Device context.
3104 * psc [I/O] Opaque pointer to a script cache.
3105 * psa [I/O] Script analysis.
3106 * tagScript [I] The OpenType tag for the Script
3107 * tagLangSys [I] The OpenType tag for the Language
3108 * rcRangeChars[I] Array of Character counts in each range
3109 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures
3110 * cRanges [I] Count of ranges
3111 * pwcChars [I] Array of characters specifying the run.
3112 * cChars [I] Number of characters in pwcChars.
3113 * cMaxGlyphs [I] Length of pwOutGlyphs.
3114 * pwLogClust [O] Array of logical cluster info.
3115 * pCharProps [O] Array of character property values
3116 * pwOutGlyphs [O] Array of glyphs.
3117 * pOutGlyphProps [O] Array of attributes for the retrieved glyphs
3118 * pcGlyphs [O] Number of glyphs returned.
3119 *
3120 * RETURNS
3121 * Success: S_OK
3122 * Failure: Non-zero HRESULT value.
3123 */
3128 int cRanges, const WCHAR *pwcChars, int cChars,
3132{
3133 HRESULT hr;
3134 int i;
3135 unsigned int g;
3136 BOOL rtl;
3137 int cluster;
3138 static int once = 0;
3139
3140 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %d, %d, %p, %p, %p, %p, %p )\n",
3141 hdc, psc, psa,
3142 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4),
3145
3146 if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL,
3147 psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder, psa->fNoGlyphIndex);
3148
3149 if (!pOutGlyphProps || !pcGlyphs || !pCharProps) return E_INVALIDARG;
3150 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
3151
3152 if (cRanges)
3153 if(!once++) FIXME("Ranges not supported yet\n");
3154
3155 rtl = (psa && !psa->fLogicalOrder && psa->fRTL);
3156
3157 *pcGlyphs = cChars;
3158 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3159 if (!pwLogClust) return E_FAIL;
3160
3161 ((ScriptCache *)*psc)->userScript = tagScript;
3162 ((ScriptCache *)*psc)->userLang = tagLangSys;
3163
3164 /* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */
3165 for (i = 0; i < cChars; i++)
3166 {
3167 int idx = i;
3168 if (rtl) idx = cChars - 1 - i;
3169 /* FIXME: set to better values */
3170 pOutGlyphProps[i].sva.uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
3171 pOutGlyphProps[i].sva.fClusterStart = 1;
3172 pOutGlyphProps[i].sva.fDiacritic = 0;
3173 pOutGlyphProps[i].sva.fZeroWidth = 0;
3174 pOutGlyphProps[i].sva.fReserved = 0;
3175 pOutGlyphProps[i].sva.fShapeReserved = 0;
3176
3177 /* FIXME: have the shaping engine set this */
3178 pCharProps[i].fCanGlyphAlone = 0;
3179
3180 pwLogClust[i] = idx;
3181 }
3182
3183 if (psa && !psa->fNoGlyphIndex && ((ScriptCache *)*psc)->sfnt)
3184 {
3185 WCHAR *rChars;
3187
3188 if (!(rChars = heap_calloc(cChars, sizeof(*rChars))))
3189 return E_OUTOFMEMORY;
3190
3191 for (i = 0, g = 0, cluster = 0; i < cChars; i++)
3192 {
3193 int idx = i;
3194 DWORD chInput;
3195
3196 if (rtl) idx = cChars - 1 - i;
3197 if (!cluster)
3198 {
3200 if (!chInput)
3201 {
3202 if (psa->fRTL)
3203 chInput = mirror_char(pwcChars[idx]);
3204 else
3205 chInput = pwcChars[idx];
3206 rChars[i] = chInput;
3207 }
3208 else
3209 {
3210 rChars[i] = pwcChars[idx];
3211 rChars[i+1] = pwcChars[(rtl)?idx-1:idx+1];
3212 cluster = 1;
3213 }
3214 if (!(pwOutGlyphs[g] = get_cache_glyph(psc, chInput)))
3215 {
3216 WORD glyph;
3217 if (!hdc)
3218 {
3219 heap_free(rChars);
3220 return E_PENDING;
3221 }
3222 if (OpenType_CMAP_GetGlyphIndex(hdc, (ScriptCache *)*psc, chInput, &glyph, 0) == GDI_ERROR)
3223 {
3224 heap_free(rChars);
3225 return S_FALSE;
3226 }
3227 pwOutGlyphs[g] = set_cache_glyph(psc, chInput, glyph);
3228 }
3229 g++;
3230 }
3231 else
3232 {
3233 int k;
3234 cluster--;
3236 for (k = (rtl)?idx-1:idx+1; k >= 0 && k < cChars; (rtl)?k--:k++)
3237 pwLogClust[k]--;
3238 }
3239 }
3240 *pcGlyphs = g;
3241
3245
3246 for (i = 0; i < cChars; ++i)
3247 {
3248 /* Special case for tabs and joiners. As control characters, ZWNJ
3249 * and ZWJ would in principle get handled by the corresponding
3250 * shaping functions. However, since ZWNJ and ZWJ can get merged
3251 * into adjoining runs during itemisation, these don't generally
3252 * get classified as Script_Control. */
3253 if (pwcChars[i] == 0x0009 || pwcChars[i] == ZWSP || pwcChars[i] == ZWNJ || pwcChars[i] == ZWJ)
3254 {
3255 pwOutGlyphs[pwLogClust[i]] = ((ScriptCache *)*psc)->sfp.wgBlank;
3256 pOutGlyphProps[pwLogClust[i]].sva.fZeroWidth = 1;
3257 }
3258 }
3259 heap_free(rChars);
3260 }
3261 else
3262 {
3263 TRACE("no glyph translation\n");
3264 for (i = 0; i < cChars; i++)
3265 {
3266 int idx = i;
3267 /* No mirroring done here */
3268 if (rtl) idx = cChars - 1 - i;
3270
3271 if (!psa)
3272 continue;
3273
3274 /* overwrite some basic control glyphs to blank */
3275 if (psa->fNoGlyphIndex)
3276 {
3277 if (pwcChars[idx] == ZWSP || pwcChars[idx] == ZWNJ || pwcChars[idx] == ZWJ)
3278 {
3279 pwOutGlyphs[i] = 0x20;
3280 pOutGlyphProps[i].sva.fZeroWidth = 1;
3281 }
3282 }
3283 else if (psa->eScript == Script_Control || pwcChars[idx] == ZWSP
3284 || pwcChars[idx] == ZWNJ || pwcChars[idx] == ZWJ)
3285 {
3286 if (pwcChars[idx] == 0x0009 || pwcChars[idx] == 0x000A ||
3287 pwcChars[idx] == 0x000D || pwcChars[idx] >= 0x001C)
3288 {
3289 pwOutGlyphs[i] = ((ScriptCache *)*psc)->sfp.wgBlank;
3290 pOutGlyphProps[i].sva.fZeroWidth = 1;
3291 }
3292 }
3293 }
3294 }
3295
3296 return S_OK;
3297}
3298
3299
3300/***********************************************************************
3301 * ScriptShape (USP10.@)
3302 *
3303 * Produce glyphs and visual attributes for a run.
3304 *
3305 * PARAMS
3306 * hdc [I] Device context.
3307 * psc [I/O] Opaque pointer to a script cache.
3308 * pwcChars [I] Array of characters specifying the run.
3309 * cChars [I] Number of characters in pwcChars.
3310 * cMaxGlyphs [I] Length of pwOutGlyphs.
3311 * psa [I/O] Script analysis.
3312 * pwOutGlyphs [O] Array of glyphs.
3313 * pwLogClust [O] Array of logical cluster info.
3314 * psva [O] Array of visual attributes.
3315 * pcGlyphs [O] Number of glyphs returned.
3316 *
3317 * RETURNS
3318 * Success: S_OK
3319 * Failure: Non-zero HRESULT value.
3320 */
3322 int cChars, int cMaxGlyphs,
3324 SCRIPT_VISATTR *psva, int *pcGlyphs)
3325{
3326 HRESULT hr;
3327 int i;
3328 SCRIPT_CHARPROP *charProps;
3329 SCRIPT_GLYPHPROP *glyphProps;
3330
3331 if (!psva || !pcGlyphs) return E_INVALIDARG;
3332 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
3333
3334 if (!(charProps = heap_calloc(cChars, sizeof(*charProps))))
3335 return E_OUTOFMEMORY;
3336
3337 if (!(glyphProps = heap_calloc(cMaxGlyphs, sizeof(*glyphProps))))
3338 {
3339 heap_free(charProps);
3340 return E_OUTOFMEMORY;
3341 }
3342
3344
3345 if (SUCCEEDED(hr))
3346 {
3347 for (i = 0; i < *pcGlyphs; i++)
3348 psva[i] = glyphProps[i].sva;
3349 }
3350
3351 heap_free(charProps);
3352 heap_free(glyphProps);
3353
3354 return hr;
3355}
3356
3357/***********************************************************************
3358 * ScriptPlaceOpenType (USP10.@)
3359 *
3360 * Produce advance widths for a run.
3361 *
3362 * PARAMS
3363 * hdc [I] Device context.
3364 * psc [I/O] Opaque pointer to a script cache.
3365 * psa [I/O] Script analysis.
3366 * tagScript [I] The OpenType tag for the Script
3367 * tagLangSys [I] The OpenType tag for the Language
3368 * rcRangeChars[I] Array of Character counts in each range
3369 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures
3370 * cRanges [I] Count of ranges
3371 * pwcChars [I] Array of characters specifying the run.
3372 * pwLogClust [I] Array of logical cluster info
3373 * pCharProps [I] Array of character property values
3374 * cChars [I] Number of characters in pwcChars.
3375 * pwGlyphs [I] Array of glyphs.
3376 * pGlyphProps [I] Array of attributes for the retrieved glyphs
3377 * cGlyphs [I] Count of Glyphs
3378 * piAdvance [O] Array of advance widths.
3379 * pGoffset [O] Glyph offsets.
3380 * pABC [O] Combined ABC width.
3381 *
3382 * RETURNS
3383 * Success: S_OK
3384 * Failure: Non-zero HRESULT value.
3385 */
3386
3390 int cRanges, const WCHAR *pwcChars, WORD *pwLogClust,
3392 const WORD *pwGlyphs, const SCRIPT_GLYPHPROP *pGlyphProps,
3393 int cGlyphs, int *piAdvance,
3394 GOFFSET *pGoffset, ABC *pABC
3395)
3396{
3397 HRESULT hr;
3398 int i;
3399 static int once = 0;
3400
3401 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %p, %p, %d, %p, %p, %d, %p %p %p)\n",
3402 hdc, psc, psa,
3403 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4),
3405 pwLogClust, pCharProps, cChars, pwGlyphs, pGlyphProps, cGlyphs, piAdvance,
3406 pGoffset, pABC);
3407
3408 if (!pGlyphProps) return E_INVALIDARG;
3409 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3410 if (!pGoffset) return E_FAIL;
3411
3412 if (cRanges)
3413 if (!once++) FIXME("Ranges not supported yet\n");
3414
3415 ((ScriptCache *)*psc)->userScript = tagScript;
3416 ((ScriptCache *)*psc)->userLang = tagLangSys;
3417
3418 if (pABC) memset(pABC, 0, sizeof(ABC));
3419 for (i = 0; i < cGlyphs; i++)
3420 {
3421 WORD glyph;
3422 ABC abc;
3423
3424 /* FIXME: set to more reasonable values */
3425 pGoffset[i].du = pGoffset[i].dv = 0;
3426
3427 if (pGlyphProps[i].sva.fZeroWidth)
3428 {
3429 abc.abcA = abc.abcB = abc.abcC = 0;
3430 if (piAdvance) piAdvance[i] = 0;
3431 continue;
3432 }
3433
3434 if (psa->fNoGlyphIndex)
3435 {
3436 if (FAILED(hr = ScriptGetCMap(hdc, psc, &pwGlyphs[i], 1, 0, &glyph))) return hr;
3437 }
3438 else
3439 {
3440 hr = S_OK;
3441 glyph = pwGlyphs[i];
3442 }
3443
3444 if (hr == S_FALSE)
3445 {
3446 if (!hdc) return E_PENDING;
3448 {
3449 if (!GetCharABCWidthsW(hdc, pwGlyphs[i], pwGlyphs[i], &abc)) return S_FALSE;
3450 }
3451 else
3452 {
3453 INT width;
3454 if (!GetCharWidthW(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return S_FALSE;
3455 abc.abcB = width;
3456 abc.abcA = abc.abcC = 0;
3457 }
3458 }
3459 else if (!get_cache_glyph_widths(psc, glyph, &abc))
3460 {
3461 if (!hdc) return E_PENDING;
3463 {
3464 if (!GetCharABCWidthsI(hdc, glyph, 1, NULL, &abc)) return S_FALSE;
3465 }
3466 else
3467 {
3468 INT width;
3469 if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
3470 abc.abcB = width;
3471 abc.abcA = abc.abcC = 0;
3472 }
3473 set_cache_glyph_widths(psc, glyph, &abc);
3474 }
3475 if (pABC)
3476 {
3477 pABC->abcA += abc.abcA;
3478 pABC->abcB += abc.abcB;
3479 pABC->abcC += abc.abcC;
3480 }
3481 if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC;
3482 }
3483
3484 SHAPE_ApplyOpenTypePositions(hdc, (ScriptCache *)*psc, psa, pwGlyphs, cGlyphs, piAdvance, pGoffset);
3485
3486 if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC);
3487 return S_OK;
3488}
3489
3490/***********************************************************************
3491 * ScriptPlace (USP10.@)
3492 *
3493 * Produce advance widths for a run.
3494 *
3495 * PARAMS
3496 * hdc [I] Device context.
3497 * psc [I/O] Opaque pointer to a script cache.
3498 * pwGlyphs [I] Array of glyphs.
3499 * cGlyphs [I] Number of glyphs in pwGlyphs.
3500 * psva [I] Array of visual attributes.
3501 * psa [I/O] String analysis.
3502 * piAdvance [O] Array of advance widths.
3503 * pGoffset [O] Glyph offsets.
3504 * pABC [O] Combined ABC width.
3505 *
3506 * RETURNS
3507 * Success: S_OK
3508 * Failure: Non-zero HRESULT value.
3509 */
3511 int cGlyphs, const SCRIPT_VISATTR *psva,
3512 SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC )
3513{
3514 HRESULT hr;
3515 SCRIPT_GLYPHPROP *glyphProps;
3516 int i;
3517
3518 TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs, cGlyphs, psva, psa,
3519 piAdvance, pGoffset, pABC);
3520
3521 if (!psva) return E_INVALIDARG;
3522 if (!pGoffset) return E_FAIL;
3523
3524 if (!(glyphProps = heap_calloc(cGlyphs, sizeof(*glyphProps))))
3525 return E_OUTOFMEMORY;
3526
3527 for (i = 0; i < cGlyphs; i++)
3528 glyphProps[i].sva = psva[i];
3529
3530 hr = ScriptPlaceOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, NULL, NULL, NULL, 0, pwGlyphs, glyphProps, cGlyphs, piAdvance, pGoffset, pABC);
3531
3532 heap_free(glyphProps);
3533
3534 return hr;
3535}
3536
3537/***********************************************************************
3538 * ScriptGetCMap (USP10.@)
3539 *
3540 * Retrieve glyph indices.
3541 *
3542 * PARAMS
3543 * hdc [I] Device context.
3544 * psc [I/O] Opaque pointer to a script cache.
3545 * pwcInChars [I] Array of Unicode characters.
3546 * cChars [I] Number of characters in pwcInChars.
3547 * dwFlags [I] Flags.
3548 * pwOutGlyphs [O] Buffer to receive the array of glyph indices.
3549 *
3550 * RETURNS
3551 * Success: S_OK
3552 * Failure: Non-zero HRESULT value.
3553 */
3556{
3557 HRESULT hr;
3558 int i;
3559
3560 TRACE("(%p,%p,%s,%d,0x%x,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars),
3562
3563 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3564
3565 hr = S_OK;
3566
3567 for (i = 0; i < cChars; i++)
3568 {
3569 WCHAR inChar;
3570 if (dwFlags == SGCM_RTL)
3571 inChar = mirror_char(pwcInChars[i]);
3572 else
3573 inChar = pwcInChars[i];
3574 if (!(pwOutGlyphs[i] = get_cache_glyph(psc, inChar)))
3575 {
3576 WORD glyph;
3577 if (!hdc) return E_PENDING;
3578 if (GetGlyphIndicesW(hdc, &inChar, 1, &glyph, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE;
3579 if (glyph == 0xffff)
3580 {
3581 hr = S_FALSE;
3582 glyph = 0x0;
3583 }
3584 pwOutGlyphs[i] = set_cache_glyph(psc, inChar, glyph);
3585 }
3586 }
3587
3588 return hr;
3589}
3590
3591/***********************************************************************
3592 * ScriptTextOut (USP10.@)
3593 *
3594 */
3595HRESULT WINAPI ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions,
3596 const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved,
3597 int iReserved, const WORD *pwGlyphs, int cGlyphs, const int *piAdvance,
3598 const int *piJustify, const GOFFSET *pGoffset)
3599{
3600 HRESULT hr = S_OK;
3601 INT i, dir = 1;
3602 INT *lpDx;
3603 WORD *reordered_glyphs = (WORD *)pwGlyphs;
3604
3605 TRACE("(%p, %p, %d, %d, %08x, %s, %p, %p, %d, %p, %d, %p, %p, %p)\n",
3606 hdc, psc, x, y, fuOptions, wine_dbgstr_rect(lprc), psa, pwcReserved, iReserved, pwGlyphs, cGlyphs,
3607 piAdvance, piJustify, pGoffset);
3608
3609 if (!hdc || !psc) return E_INVALIDARG;
3610 if (!piAdvance || !psa || !pwGlyphs) return E_INVALIDARG;
3611
3612 fuOptions &= ETO_CLIPPED + ETO_OPAQUE;
3613 fuOptions |= ETO_IGNORELANGUAGE;
3614 if (!psa->fNoGlyphIndex) /* Have Glyphs? */
3615 fuOptions |= ETO_GLYPH_INDEX; /* Say don't do translation to glyph */
3616
3617 if (!(lpDx = heap_calloc(cGlyphs, 2 * sizeof(*lpDx))))
3618 return E_OUTOFMEMORY;
3619 fuOptions |= ETO_PDY;
3620
3621 if (psa->fRTL && psa->fLogicalOrder)
3622 {
3623 if (!(reordered_glyphs = heap_calloc(cGlyphs, sizeof(*reordered_glyphs))))
3624 {
3625 heap_free( lpDx );
3626 return E_OUTOFMEMORY;
3627 }
3628
3629 for (i = 0; i < cGlyphs; i++)
3630 reordered_glyphs[i] = pwGlyphs[cGlyphs - 1 - i];
3631 dir = -1;
3632 }
3633
3634 for (i = 0; i < cGlyphs; i++)
3635 {
3636 int orig_index = (dir > 0) ? i : cGlyphs - 1 - i;
3637 lpDx[i * 2] = piAdvance[orig_index];
3638 lpDx[i * 2 + 1] = 0;
3639
3640 if (pGoffset)
3641 {
3642 if (i == 0)
3643 {
3644 x += pGoffset[orig_index].du * dir;
3645 y += pGoffset[orig_index].dv;
3646 }
3647 else
3648 {
3649 lpDx[(i - 1) * 2] += pGoffset[orig_index].du * dir;
3650 lpDx[(i - 1) * 2 + 1] += pGoffset[orig_index].dv;
3651 }
3652 lpDx[i * 2] -= pGoffset[orig_index].du * dir;
3653 lpDx[i * 2 + 1] -= pGoffset[orig_index].dv;
3654 }
3655 }
3656
3657 if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, reordered_glyphs, cGlyphs, lpDx))
3658 hr = S_FALSE;
3659
3660 if (reordered_glyphs != pwGlyphs) heap_free( reordered_glyphs );
3661 heap_free(lpDx);
3662
3663 return hr;
3664}
3665
3666/***********************************************************************
3667 * ScriptCacheGetHeight (USP10.@)
3668 *
3669 * Retrieve the height of the font in the cache.
3670 *
3671 * PARAMS
3672 * hdc [I] Device context.
3673 * psc [I/O] Opaque pointer to a script cache.
3674 * height [O] Receives font height.
3675 *
3676 * RETURNS
3677 * Success: S_OK
3678 * Failure: Non-zero HRESULT value.
3679 */
3681{
3682 HRESULT hr;
3683
3684 TRACE("(%p, %p, %p)\n", hdc, psc, height);
3685
3686 if (!height) return E_INVALIDARG;
3687 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3688
3690 return S_OK;
3691}
3692
3693/***********************************************************************
3694 * ScriptGetGlyphABCWidth (USP10.@)
3695 *
3696 * Retrieve the width of a glyph.
3697 *
3698 * PARAMS
3699 * hdc [I] Device context.
3700 * psc [I/O] Opaque pointer to a script cache.
3701 * glyph [I] Glyph to retrieve the width for.
3702 * abc [O] ABC widths of the glyph.
3703 *
3704 * RETURNS
3705 * Success: S_OK
3706 * Failure: Non-zero HRESULT value.
3707 */
3709{
3710 HRESULT hr;
3711
3712 TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc);
3713
3714 if (!abc) return E_INVALIDARG;
3715 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3716
3717 if (!get_cache_glyph_widths(psc, glyph, abc))
3718 {
3719 if (!hdc) return E_PENDING;
3721 {
3722 if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE;
3723 }
3724 else
3725 {
3726 INT width;
3727 if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
3728 abc->abcB = width;
3729 abc->abcA = abc->abcC = 0;
3730 }
3732 }
3733 return S_OK;
3734}
3735
3736/***********************************************************************
3737 * ScriptLayout (USP10.@)
3738 *
3739 * Map embedding levels to visual and/or logical order.
3740 *
3741 * PARAMS
3742 * runs [I] Size of level array.
3743 * level [I] Array of embedding levels.
3744 * vistolog [O] Map of embedding levels from visual to logical order.
3745 * logtovis [O] Map of embedding levels from logical to visual order.
3746 *
3747 * RETURNS
3748 * Success: S_OK
3749 * Failure: Non-zero HRESULT value.
3750 *
3751 */
3752HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
3753{
3754 int* indexs;
3755 int ich;
3756
3757 TRACE("(%d, %p, %p, %p)\n", runs, level, vistolog, logtovis);
3758
3759 if (!level || (!vistolog && !logtovis))
3760 return E_INVALIDARG;
3761
3762 if (!(indexs = heap_calloc(runs, sizeof(*indexs))))
3763 return E_OUTOFMEMORY;
3764
3765 if (vistolog)
3766 {
3767 for( ich = 0; ich < runs; ich++)
3768 indexs[ich] = ich;
3769
3770 ich = 0;
3771 while (ich < runs)
3772 ich += BIDI_ReorderV2lLevel(0, indexs+ich, level+ich, runs - ich, FALSE);
3773 memcpy(vistolog, indexs, runs * sizeof(*vistolog));
3774 }
3775
3776 if (logtovis)
3777 {
3778 for( ich = 0; ich < runs; ich++)
3779 indexs[ich] = ich;
3780
3781 ich = 0;
3782 while (ich < runs)
3783 ich += BIDI_ReorderL2vLevel(0, indexs+ich, level+ich, runs - ich, FALSE);
3784 memcpy(logtovis, indexs, runs * sizeof(*logtovis));
3785 }
3786 heap_free(indexs);
3787
3788 return S_OK;
3789}
3790
3791/***********************************************************************
3792 * ScriptStringGetLogicalWidths (USP10.@)
3793 *
3794 * Returns logical widths from a string analysis.
3795 *
3796 * PARAMS
3797 * ssa [I] string analysis.
3798 * piDx [O] logical widths returned.
3799 *
3800 * RETURNS
3801 * Success: S_OK
3802 * Failure: a non-zero HRESULT.
3803 */
3805{
3806 int i, j, next = 0;
3807 StringAnalysis *analysis = ssa;
3808
3809 TRACE("%p, %p\n", ssa, piDx);
3810
3811 if (!analysis) return S_FALSE;
3812 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
3813
3814 for (i = 0; i < analysis->numItems; i++)
3815 {
3816 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
3817 int direction = 1;
3818
3819 if (analysis->pItem[i].a.fRTL && ! analysis->pItem[i].a.fLogicalOrder)
3820 direction = -1;
3821
3822 for (j = 0; j < cChar; j++)
3823 {
3824 int k;
3825 int glyph = analysis->glyphs[i].pwLogClust[j];
3826 int clust_size = get_cluster_size(analysis->glyphs[i].pwLogClust,
3827 cChar, j, direction, NULL, NULL);
3828 int advance = get_glyph_cluster_advance(analysis->glyphs[i].piAdvance, analysis->glyphs[i].psva, analysis->glyphs[i].pwLogClust, analysis->glyphs[i].numGlyphs, cChar, glyph, direction);
3829
3830 for (k = 0; k < clust_size; k++)
3831 {
3832 piDx[next] = advance / clust_size;
3833 next++;
3834 if (k) j++;
3835 }
3836 }
3837 }
3838 return S_OK;
3839}
3840
3841/***********************************************************************
3842 * ScriptStringValidate (USP10.@)
3843 *
3844 * Validate a string analysis.
3845 *
3846 * PARAMS
3847 * ssa [I] string analysis.
3848 *
3849 * RETURNS
3850 * Success: S_OK
3851 * Failure: S_FALSE if invalid sequences are found
3852 * or a non-zero HRESULT if it fails.
3853 */
3855{
3856 StringAnalysis *analysis = ssa;
3857
3858 TRACE("(%p)\n", ssa);
3859
3860 if (!analysis) return E_INVALIDARG;
3862}
3863
3864/***********************************************************************
3865 * ScriptString_pSize (USP10.@)
3866 *
3867 * Retrieve width and height of an analysed string.
3868 *
3869 * PARAMS
3870 * ssa [I] string analysis.
3871 *
3872 * RETURNS
3873 * Success: Pointer to a SIZE structure.
3874 * Failure: NULL
3875 */
3877{
3878 int i, j;
3879 StringAnalysis *analysis = ssa;
3880
3881 TRACE("(%p)\n", ssa);
3882
3883 if (!analysis) return NULL;
3884 if (!(analysis->ssa_flags & SSA_GLYPHS)) return NULL;
3885
3886 if (!(analysis->flags & SCRIPT_STRING_ANALYSIS_FLAGS_SIZE))
3887 {
3888 analysis->sz.cy = analysis->glyphs[0].sc->tm.tmHeight;
3889
3890 analysis->sz.cx = 0;
3891 for (i = 0; i < analysis->numItems; i++)
3892 {
3893 if (analysis->glyphs[i].sc->tm.tmHeight > analysis->sz.cy)
3894 analysis->sz.cy = analysis->glyphs[i].sc->tm.tmHeight;
3895 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++)
3896 analysis->sz.cx += analysis->glyphs[i].piAdvance[j];
3897 }
3899 }
3900 return &analysis->sz;
3901}
3902
3903/***********************************************************************
3904 * ScriptString_pLogAttr (USP10.@)
3905 *
3906 * Retrieve logical attributes of an analysed string.
3907 *
3908 * PARAMS
3909 * ssa [I] string analysis.
3910 *
3911 * RETURNS
3912 * Success: Pointer to an array of SCRIPT_LOGATTR structures.
3913 * Failure: NULL
3914 */
3916{
3917 StringAnalysis *analysis = ssa;
3918
3919 TRACE("(%p)\n", ssa);
3920
3921 if (!analysis) return NULL;
3922 if (!(analysis->ssa_flags & SSA_BREAK)) return NULL;
3923 return analysis->logattrs;
3924}
3925
3926/***********************************************************************
3927 * ScriptString_pcOutChars (USP10.@)
3928 *
3929 * Retrieve the length of a string after clipping.
3930 *
3931 * PARAMS
3932 * ssa [I] String analysis.
3933 *
3934 * RETURNS
3935 * Success: Pointer to the length.
3936 * Failure: NULL
3937 */
3939{
3940 StringAnalysis *analysis = ssa;
3941
3942 TRACE("(%p)\n", ssa);
3943
3944 if (!analysis) return NULL;
3945 return &analysis->clip_len;
3946}
3947
3948/***********************************************************************
3949 * ScriptStringGetOrder (USP10.@)
3950 *
3951 * Retrieve a glyph order map.
3952 *
3953 * PARAMS
3954 * ssa [I] String analysis.
3955 * order [I/O] Array of glyph positions.
3956 *
3957 * RETURNS
3958 * Success: S_OK
3959 * Failure: a non-zero HRESULT.
3960 */
3962{
3963 int i, j;
3964 unsigned int k;
3965 StringAnalysis *analysis = ssa;
3966
3967 TRACE("(%p)\n", ssa);
3968
3969 if (!analysis) return S_FALSE;
3970 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
3971
3972 /* FIXME: handle RTL scripts */
3973 for (i = 0, k = 0; i < analysis->numItems; i++)
3974 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++, k++)
3975 order[k] = k;
3976
3977 return S_OK;
3978}
3979
3980/***********************************************************************
3981 * ScriptGetLogicalWidths (USP10.@)
3982 *
3983 * Convert advance widths to logical widths.
3984 *
3985 * PARAMS
3986 * sa [I] Script analysis.
3987 * nbchars [I] Number of characters.
3988 * nbglyphs [I] Number of glyphs.
3989 * glyph_width [I] Array of glyph widths.
3990 * log_clust [I] Array of logical clusters.
3991 * sva [I] Visual attributes.
3992 * widths [O] Array of logical widths.
3993 *
3994 * RETURNS
3995 * Success: S_OK
3996 * Failure: a non-zero HRESULT.
3997 */
3998HRESULT WINAPI ScriptGetLogicalWidths(const SCRIPT_ANALYSIS *sa, int nbchars, int nbglyphs,
3999 const int *advances, const WORD *log_clust,
4000 const SCRIPT_VISATTR *sva, int *widths)
4001{
4002 int i, next = 0, direction;
4003
4004 TRACE("(%p, %d, %d, %p, %p, %p, %p)\n",
4005 sa, nbchars, nbglyphs, advances, log_clust, sva, widths);
4006
4007 if (sa->fRTL && !sa->fLogicalOrder)
4008 direction = -1;
4009 else
4010 direction = 1;
4011
4012 for (i = 0; i < nbchars; i++)
4013 {
4014 int clust_size = get_cluster_size(log_clust, nbchars, i, direction, NULL, NULL);
4015 int advance = get_glyph_cluster_advance(advances, sva, log_clust, nbglyphs, nbchars, log_clust[i], direction);
4016 int j;
4017
4018 for (j = 0; j < clust_size; j++)
4019 {
4020 widths[next] = advance / clust_size;
4021 next++;
4022 if (j) i++;
4023 }
4024 }
4025
4026 return S_OK;
4027}
4028
4029/***********************************************************************
4030 * ScriptApplyLogicalWidth (USP10.@)
4031 *
4032 * Generate glyph advance widths.
4033 *
4034 * PARAMS
4035 * dx [I] Array of logical advance widths.
4036 * num_chars [I] Number of characters.
4037 * num_glyphs [I] Number of glyphs.
4038 * log_clust [I] Array of logical clusters.
4039 * sva [I] Visual attributes.
4040 * advance [I] Array of glyph advance widths.
4041 * sa [I] Script analysis.
4042 * abc [I/O] Summed ABC widths.
4043 * justify [O] Array of glyph advance widths.
4044 *
4045 * RETURNS
4046 * Success: S_OK
4047 * Failure: a non-zero HRESULT.
4048 */
4049HRESULT WINAPI ScriptApplyLogicalWidth(const int *dx, int num_chars, int num_glyphs,
4050 const WORD *log_clust, const SCRIPT_VISATTR *sva,
4051 const int *advance, const SCRIPT_ANALYSIS *sa,
4052 ABC *abc, int *justify)
4053{
4054 int i;
4055
4056 FIXME("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n",
4057 dx, num_chars, num_glyphs, log_clust, sva, advance, sa, abc, justify);
4058
4059 for (i = 0; i < num_chars; i++) justify[i] = advance[i];
4060 return S_OK;
4061}
4062
4064 int num_glyphs, int dx, int min_kashida, int *justify)
4065{
4066 int i;
4067
4068 FIXME("(%p, %p, %d, %d, %d, %p)\n", sva, advance, num_glyphs, dx, min_kashida, justify);
4069
4070 for (i = 0; i < num_glyphs; i++) justify[i] = advance[i];
4071 return S_OK;
4072}
4073
4075{
4076 HRESULT hr;
4077 if (!pScriptTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4078 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4079
4081}
4082
4084{
4085 HRESULT hr;
4086 if (!pLangSysTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4087 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4088
4090}
4091
4093{
4094 HRESULT hr;
4095 if (!pFeatureTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4096 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4097
4099}
4100
4101#ifdef __REACTOS__
4102BOOL gbLpkPresent = FALSE;
4104{
4105 gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */
4106}
4107#endif
_STLP_MOVE_TO_STD_NAMESPACE void _STLP_CALL advance(_InputIterator &__i, _Distance __n)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define __cdecl
Definition: accygwin.h:79
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
unsigned int dir
Definition: maze.c:112
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
#define RegCloseKey(hKey)
Definition: registry.h:49
void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: breaking.c:77
Definition: list.h:37
Definition: _locale.h:75
static TAGID TAGID find
Definition: db.cpp:155
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define LF_FACESIZE
Definition: dimm.idl:39
#define E_PENDING
Definition: dinput.h:172
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3263
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define HeapReAlloc
Definition: compat.h:734
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define lstrcpyW
Definition: compat.h:749
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3)
Definition: font.c:113
static BOOL script_is_numeric(enum usp10_script script)
Definition: usp10.c:1339
HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, int cGlyphs, const SCRIPT_VISATTR *psva, SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC)
Definition: usp10.c:3510
static struct list script_cache_list
Definition: usp10.c:689
HRESULT WINAPI ScriptGetFontScriptTags(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags)
Definition: usp10.c:4074
static WORD get_cache_glyph(SCRIPT_CACHE *psc, DWORD c)
Definition: usp10.c:825
HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:2556
HRESULT WINAPI ScriptGetFontFeatureTags(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags)
Definition: usp10.c:4092
static HRESULT SS_ItemOut(SCRIPT_STRING_ANALYSIS ssa, int iX, int iY, int iItem, int cStart, int cEnd, UINT uOptions, const RECT *prc, BOOL fSelected, BOOL fDisabled)
Definition: usp10.c:2200
static BOOL is_indic(enum usp10_script script)
Definition: usp10.c:1305
static int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x)
Definition: usp10.c:1860
static enum usp10_script base_indic(enum usp10_script script)
Definition: usp10.c:1310
HRESULT WINAPI ScriptApplyLogicalWidth(const int *dx, int num_chars, int num_glyphs, const WORD *log_clust, const SCRIPT_VISATTR *sva, const int *advance, const SCRIPT_ANALYSIS *sa, ABC *abc, int *justify)
Definition: usp10.c:4049
const SCRIPT_LOGATTR *WINAPI ScriptString_pLogAttr(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3915
HRESULT WINAPI ScriptShapeOpenType(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, int cRanges, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs, SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs)
Definition: usp10.c:3124
BOOL usp10_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
Definition: usp10.c:730
HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height)
Definition: usp10.c:3680
HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars, int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
Definition: usp10.c:3554
HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
Definition: usp10.c:1080
HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, int *pcItems)
Definition: usp10.c:1853
static BYTE get_cache_pitch_family(SCRIPT_CACHE *psc)
Definition: usp10.c:820
static const struct usp10_script_range script_ranges[]
static BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
Definition: usp10.c:857
HRESULT WINAPI ScriptXtoCP(int iX, int cChars, int cGlyphs, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, const int *piAdvance, const SCRIPT_ANALYSIS *psa, int *piCP, int *piTrailing)
Definition: usp10.c:2854
HRESULT WINAPI ScriptGetLogicalWidths(const SCRIPT_ANALYSIS *sa, int nbchars, int nbglyphs, const int *advances, const WORD *log_clust, const SCRIPT_VISATTR *sva, int *widths)
Definition: usp10.c:3998
static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems)
Definition: usp10.c:1344
HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, SCRIPT_VISATTR *psva, int *pcGlyphs)
Definition: usp10.c:3321
HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
Definition: usp10.c:3752
static LONG get_cache_height(SCRIPT_CACHE *psc)
Definition: usp10.c:815
const scriptData scriptInformation[]
Definition: usp10.c:305
HRESULT WINAPI ScriptStringGetLogicalWidths(SCRIPT_STRING_ANALYSIS ssa, int *piDx)
Definition: usp10.c:3804
static void get_cache_font_properties(SCRIPT_FONTPROPERTIES *sfp, ScriptCache *sc)
Definition: usp10.c:810
HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, int cGlyphs, int iCharset, DWORD dwFlags, int iReqWidth, SCRIPT_CONTROL *psControl, SCRIPT_STATE *psState, const int *piDx, SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass, SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:1985
static int get_cluster_size(const WORD *pwLogClust, int cChars, int item, int direction, int *iCluster, int *check_out)
Definition: usp10.c:2594
HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, int iX, int iY, UINT uOptions, const RECT *prc, int iMinSel, int iMaxSel, BOOL fDisabled)
Definition: usp10.c:2366
static BOOL requires_fallback(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, const WCHAR *pwcInChars, int cChars)
Definition: usp10.c:1934
static int get_cluster_advance(const int *piAdvance, const SCRIPT_VISATTR *psva, const WORD *pwLogClust, int cGlyphs, int cChars, int cluster, int direction)
Definition: usp10.c:2793
HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPROPERTIES *sfp)
Definition: usp10.c:1176
static CRITICAL_SECTION cs_script_cache
Definition: usp10.c:681
static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
Definition: usp10.c:866
HRESULT WINAPI ScriptPlaceOpenType(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, int cRanges, const WCHAR *pwcChars, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProps, int cChars, const WORD *pwGlyphs, const SCRIPT_GLYPHPROP *pGlyphProps, int cGlyphs, int *piAdvance, GOFFSET *pGoffset, ABC *pABC)
Definition: usp10.c:3387
const SIZE *WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3876
static BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
Definition: usp10.c:847
static int get_glyph_cluster_advance(const int *piAdvance, const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cGlyphs, int cChars, int glyph, int direction)
Definition: usp10.c:2618
static enum usp10_script get_char_script(const WCHAR *str, unsigned int index, unsigned int end, unsigned int *consumed)
Definition: usp10.c:969
static DWORD decode_surrogate_pair(const WCHAR *str, unsigned int index, unsigned int end)
Definition: usp10.c:946
HRESULT WINAPI ScriptGetProperties(const SCRIPT_PROPERTIES ***props, int *num)
Definition: usp10.c:1154
static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName)
Definition: usp10.c:1961
HRESULT WINAPI ScriptStringGetOrder(SCRIPT_STRING_ANALYSIS ssa, UINT *order)
Definition: usp10.c:3961
HRESULT WINAPI ScriptStringValidate(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3854
HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems)
Definition: usp10.c:1828
const int *WINAPI ScriptString_pcOutChars(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3938
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int *piCh, int *piTrailing)
Definition: usp10.c:2474
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int *pX)
Definition: usp10.c:2411
int USP10_FindGlyphInLogClust(const WORD *pwLogClust, int cChars, WORD target)
Definition: usp10.c:1044
#define Numeric_space
static int __cdecl usp10_compare_script_range(const void *key, const void *value)
Definition: usp10.c:957
HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds, SCRIPT_CONTROL *sc, SCRIPT_STATE *ss)
Definition: usp10.c:1275
static CRITICAL_SECTION_DEBUG cs_script_cache_dbg
Definition: usp10.c:682
HRESULT WINAPI ScriptRecordDigitSubstitution(LCID locale, SCRIPT_DIGITSUBSTITUTE *sds)
Definition: usp10.c:1209
static BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction)
Definition: usp10.c:2189
static int __cdecl compare_FindGlyph(const void *a, const void *b)
Definition: usp10.c:1028
HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag)
Definition: usp10.c:3074
HRESULT WINAPI ScriptGetFontLanguageTags(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags)
Definition: usp10.c:4083
static WORD set_cache_glyph(SCRIPT_CACHE *psc, WCHAR c, WORD glyph)
Definition: usp10.c:836
#define ZWJ
static WCHAR mirror_char(WCHAR ch)
Definition: usp10.c:940
HRESULT WINAPI ScriptCPtoX(int iCP, BOOL fTrailing, int cChars, int cGlyphs, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, const int *piAdvance, const SCRIPT_ANALYSIS *psa, int *piX)
Definition: usp10.c:2650
HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: usp10.c:3047
HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance, int num_glyphs, int dx, int min_kashida, int *justify)
Definition: usp10.c:4063
static BOOL get_cluster_data(const WORD *pwLogClust, int cChars, int cluster_index, int *cluster_size, int *start_index)
Definition: usp10.c:2760
static const SCRIPT_PROPERTIES * script_props[]
Definition: usp10.c:636
HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
Definition: usp10.c:3708
#define ZWSP
stringanalysis_flags
Definition: usp10.c:705
@ SCRIPT_STRING_ANALYSIS_FLAGS_SIZE
Definition: usp10.c:706
@ SCRIPT_STRING_ANALYSIS_FLAGS_INVALID
Definition: usp10.c:707
static BOOL set_cache_font_properties(const HDC hdc, ScriptCache *sc)
Definition: usp10.c:761
#define ZWNJ
HRESULT WINAPI ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions, const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved, int iReserved, const WORD *pwGlyphs, int cGlyphs, const int *piAdvance, const int *piJustify, const GOFFSET *pGoffset)
Definition: usp10.c:3595
#define swprintf
Definition: precomp.h:40
#define CP
Definition: debug.h:64
#define check(expected, result)
Definition: dplayx.c:32
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxString * pString
pKey DeleteObject()
GLint level
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum const GLvoid GLbitfield GLsizei numGlyphs
Definition: glext.h:11715
GLuint res
Definition: glext.h:9613
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLint * range
Definition: glext.h:7539
GLboolean GLboolean g
Definition: glext.h:6204
GLsizei levels
Definition: glext.h:7884
GLuint GLuint num
Definition: glext.h:9618
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLintptr offset
Definition: glext.h:5920
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define C1_CNTRL
Definition: unicode.h:36
#define C1_DIGIT
Definition: unicode.h:33
#define C1_PUNCT
Definition: unicode.h:35
#define ss
Definition: i386-dis.c:441
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_wn
Definition: kernel32.h:33
BOOL WINAPI GetStringTypeW(DWORD type, LPCWSTR src, INT count, LPWORD chartype)
Definition: lang.c:1709
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: lang.c:1558
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1108
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: lang.c:1512
GLint dx
Definition: linetemp.h:97
#define odd(x)
Definition: bidi.c:51
const WCHAR DECLSPEC_HIDDEN wine_mirror_map[3544]
Definition: mirror.c:7
__u8 cluster_size
Definition: mkdosfs.c:4
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:92
static BOOL rtl
Definition: propsheet.c:36
static UINT UINT LPWORD LPABC abc
Definition: font.c:44
static UINT UINT LPWORD glyphs
Definition: font.c:44
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static float(__cdecl *square_half_float)(float x
static const WCHAR invalid[]
Definition: assoc.c:39
static ATOM item
Definition: dde.c:856
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int cChars
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG tagScript
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
static SCRIPT_CACHE * psc
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG int OPENTYPE_TAG * pLangSysTags
Definition: usp10.c:67
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int WORD SCRIPT_CHARPROP WORD SCRIPT_GLYPHPROP int * pcGlyphs
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int OPENTYPE_TAG * pFeatureTags
Definition: usp10.c:68
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int WORD SCRIPT_CHARPROP WORD SCRIPT_GLYPHPROP * pOutGlyphProps
Definition: usp10.c:64
static int int cMaxItems
Definition: usp10.c:62
static int int const SCRIPT_CONTROL const SCRIPT_STATE SCRIPT_ITEM * pItems
Definition: usp10.c:62
static int int const SCRIPT_CONTROL const SCRIPT_STATE SCRIPT_ITEM ULONG * pScriptTags
Definition: usp10.c:62
static int int const SCRIPT_CONTROL const SCRIPT_STATE * psState
Definition: usp10.c:62
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int WORD * pwLogClust
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS int cMaxTags
Definition: usp10.c:66
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int WORD SCRIPT_CHARPROP WORD * pwOutGlyphs
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS int OPENTYPE_TAG int * pcTags
Definition: usp10.c:66
static int int const SCRIPT_CONTROL const SCRIPT_STATE SCRIPT_ITEM ULONG int * pcItems
Definition: usp10.c:62
static int cInChars
Definition: usp10.c:62
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int cMaxGlyphs
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int cRanges
Definition: usp10.c:64
static int int const SCRIPT_CONTROL * psControl
Definition: usp10.c:62
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES ** rpRangeProperties
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int * rcRangeChars
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR * pwcChars
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG tagLangSys
Definition: usp10.c:64
static SCRIPT_CACHE SCRIPT_ANALYSIS OPENTYPE_TAG OPENTYPE_TAG int TEXTRANGE_PROPERTIES int const WCHAR int int WORD SCRIPT_CHARPROP * pCharProps
Definition: usp10.c:64
int k
Definition: mpi.c:3369
script
Definition: msipriv.h:383
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_USER_DEFAULT
_Out_ LPRECT prc
Definition: ntgdi.h:1658
#define OBJ_FONT
Definition: objidl.idl:1414
DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, WORD *glyph_index, DWORD flags)
Definition: opentype.c:673
long LONG
Definition: pedump.c:60
static unsigned __int64 next
Definition: rand_nt.c:6
VOID WINAPI LpkPresent(VOID)
const WCHAR * str
int consumed
Definition: scanf.h:134
#define LANG_MALAYALAM
Definition: nls.h:93
#define LANG_HINDI
Definition: nls.h:68
#define LANG_TAMIL
Definition: nls.h:129
#define LANG_FARSI
Definition: nls.h:55
#define LANG_NEUTRAL
Definition: nls.h:22
#define LANG_THAI
Definition: nls.h:132
#define LANG_LAO
Definition: nls.h:86
#define LANG_SYRIAC
Definition: nls.h:126
#define LANG_HEBREW
Definition: nls.h:67
#define LANG_KANNADA
Definition: nls.h:77
#define LANG_ORIYA
Definition: nls.h:104
#define LANG_PERSIAN
Definition: nls.h:106
#define LANG_GEORGIAN
Definition: nls.h:61
#define LANG_GREEK
Definition: nls.h:63
#define LANG_ENGLISH
Definition: nls.h:52
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define LANG_SINHALESE
Definition: nls.h:119
#define LANG_BENGALI
Definition: nls.h:36
#define LANG_RUSSIAN
Definition: nls.h:113
#define LANG_VIETNAMESE
Definition: nls.h:143
#define LANG_PUNJABI
Definition: nls.h:109
#define LANG_ARABIC
Definition: nls.h:29
DWORD LCID
Definition: nls.h:13
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_DIVEHI
Definition: nls.h:50
#define LANG_TIBETAN
Definition: nls.h:133
#define LANG_KOREAN
Definition: nls.h:84
#define LANG_GUJARATI
Definition: nls.h:65
#define LANG_TELUGU
Definition: nls.h:131
#define LANG_ARMENIAN
Definition: nls.h:30
#define LANG_MONGOLIAN
Definition: nls.h:100
static void * heap_calloc(SIZE_T count, SIZE_T size)
Definition: heap.h:49
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define nil
Definition: compat.h:23
#define memset(x, y, z)
Definition: compat.h:39
void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, INT *pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust)
Definition: shape.c:3421
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)
Definition: shape.c:3378
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR *pwcChars, INT cChars, WORD *pwOutGlyphs, INT *pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust)
Definition: shape.c:3388
void SHAPE_ApplyOpenTypePositions(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WORD *pwGlyphs, INT cGlyphs, int *piAdvance, GOFFSET *pGoffset)
Definition: shape.c:3429
HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa)
Definition: shape.c:3454
HRESULT SHAPE_GetFontLanguageTags(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags)
Definition: shape.c:3495
HRESULT SHAPE_GetFontFeatureTags(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags)
Definition: shape.c:3523
HRESULT SHAPE_GetFontScriptTags(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags)
Definition: shape.c:3477
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
BOOL ascending
Definition: usp10.c:726
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
BYTE lfCharSet
Definition: dimm.idl:67
DWORD fComplex
Definition: usp10.h:109
DWORD fNumeric
Definition: usp10.h:108
DWORD fNeedsCaretInfo
Definition: usp10.h:111
DWORD bCharSet
Definition: usp10.h:112
OUTLINETEXTMETRICW * otm
struct list entry
SCRIPT_FONTPROPERTIES sfp
TEXTMETRICW tm
int clip_len
Definition: usp10.c:714
int cItems
Definition: usp10.c:715
StringGlyphs * glyphs
Definition: usp10.c:719
int * logical2visual
Definition: usp10.c:722
DWORD ssa_flags
Definition: usp10.c:712
DWORD flags
Definition: usp10.c:713
int cMaxGlyphs
Definition: usp10.c:716
SCRIPT_LOGATTR * logattrs
Definition: usp10.c:720
int numItems
Definition: usp10.c:718
SCRIPT_ITEM * pItem
Definition: usp10.c:717
SCRIPT_VISATTR * psva
Definition: usp10.c:697
int iMaxPosX
Definition: usp10.c:700
WORD * pwLogClust
Definition: usp10.c:695
HFONT fallbackFont
Definition: usp10.c:701
WORD * glyphs
Definition: usp10.c:694
ScriptCache * sc
Definition: usp10.c:692
ABC abc
Definition: usp10.c:699
int * piAdvance
Definition: usp10.c:696
int numGlyphs
Definition: usp10.c:693
GOFFSET * pGoffset
Definition: usp10.c:698
Definition: wingdi.h:1410
int abcA
Definition: wingdi.h:1411
UINT abcB
Definition: wingdi.h:1412
int abcC
Definition: wingdi.h:1413
LIST_ENTRY ProcessLocksList
Definition: winbase.h:883
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
OPENTYPE_TAG scriptTag
SCRIPT_ANALYSIS a
SCRIPT_PROPERTIES props
Definition: copy.c:22
Definition: module.h:576
LONG dv
Definition: usp10.h:201
LONG du
Definition: usp10.h:200
LONG left
Definition: windef.h:306
WCHAR tmBreakChar
Definition: wingdi.h:2397
WCHAR tmDefaultChar
Definition: wingdi.h:2396
LONG tmHeight
Definition: wingdi.h:2383
SCRIPT_STATE s
Definition: usp10.h:146
WORD fLogicalOrder
Definition: usp10.h:144
WORD fNoGlyphIndex
Definition: usp10.h:145
DWORD fContextDigits
Definition: usp10.h:94
DWORD fMergeNeutralItems
Definition: usp10.h:102
DWORD uDefaultLanguage
Definition: usp10.h:93
DWORD TraditionalDigitLanguage
Definition: usp10.h:156
SCRIPT_ANALYSIS a
Definition: usp10.h:151
int iCharPos
Definition: usp10.h:150
WORD uBidiLevel
Definition: usp10.h:125
int * pTabStops
Definition: usp10.h:173
enum usp10_script script
Definition: usp10.c:51
enum usp10_script numericScript
Definition: usp10.c:54
DWORD rangeLast
Definition: usp10.c:53
enum usp10_script punctScript
Definition: usp10.c:55
DWORD rangeFirst
Definition: usp10.c:52
#define max(a, b)
Definition: svc.c:63
#define LIST_INIT(head)
Definition: queue.h:197
#define bsearch
#define DWORD_PTR
Definition: treelist.c:76
SFNT_Service sfnt
Definition: ttdriver.c:206
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
Definition: pdh_main.c:94
int BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE *plevel, int cch, BOOL fReverse)
Definition: bidi.c:1215
BOOL BIDI_DetermineLevels(const WCHAR *lpString, unsigned int uCount, const SCRIPT_STATE *s, const SCRIPT_CONTROL *c, WORD *lpOutLevels, WORD *lpOutOverrides)
Definition: bidi.c:1088
BOOL BIDI_GetStrengths(const WCHAR *string, unsigned int count, const SCRIPT_CONTROL *c, WORD *strength)
Definition: bidi.c:1249
int BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE *plevel, int cch, BOOL fReverse)
Definition: bidi.c:1188
#define SCRIPT_DIGITSUBSTITUTE_TRADITIONAL
Definition: usp10.h:67
#define SSA_TAB
Definition: usp10.h:34
#define SCRIPT_DIGITSUBSTITUTE_NONE
Definition: usp10.h:65
#define SSA_FALLBACK
Definition: usp10.h:38
#define SIC_COMPLEX
Definition: usp10.h:56
#define SCRIPT_DIGITSUBSTITUTE_CONTEXT
Definition: usp10.h:64
#define SSA_LINK
Definition: usp10.h:45
#define SSA_PASSWORD
Definition: usp10.h:33
#define SCRIPT_DIGITSUBSTITUTE_NATIONAL
Definition: usp10.h:66
#define SIC_NEUTRAL
Definition: usp10.h:58
#define SIC_ASCIIDIGIT
Definition: usp10.h:57
#define SSA_GLYPHS
Definition: usp10.h:40
ULONG OPENTYPE_TAG
Definition: usp10.h:205
#define SCRIPT_UNDEFINED
Definition: usp10.h:69
#define SGCM_RTL
Definition: usp10.h:61
@ SCRIPT_JUSTIFY_BLANK
Definition: usp10.h:78
@ SCRIPT_JUSTIFY_CHARACTER
Definition: usp10.h:76
#define SSA_BREAK
Definition: usp10.h:39
#define GLYPH_BLOCK_SHIFT
usp10_script
@ Script_Kannada_Numeric
@ Script_Bengali_Numeric
@ Script_Telugu
@ Script_Yi
@ Script_Bopomofo
@ Script_Cyrillic
@ Script_Private
@ Script_Tibetan_Numeric
@ Script_Gurmukhi_Numeric
@ Script_Tai_Le
@ Script_Devanagari_Numeric
@ Script_Telugu_Numeric
@ Script_Myanmar
@ Script_NKo
@ Script_Thai_Numeric
@ Script_Khmer
@ Script_Tifinagh
@ Script_Runic
@ Script_Malayalam_Numeric
@ Script_Vietnamese_Currency
@ Script_Phags_pa
@ Script_Undefined
@ Script_Mongolian_Numeric
@ Script_Cherokee
@ Script_Vai_Numeric
@ Script_Sinhala
@ Script_Hebrew
@ Script_Ethiopic
@ Script_Ogham
@ Script_CR
@ Script_Numeric2
@ Script_Gujarati_Numeric
@ Script_Thai
@ Script_Hangul
@ Script_Diacritical
@ Script_Bengali
@ Script_Syriac
@ Script_Tamil_Numeric
@ Script_Oriya_Numeric
@ Script_Osmanya_Numeric
@ Script_Arabic_Numeric
@ Script_Oriya
@ Script_Thai_Currency
@ Script_Deseret
@ Script_Kannada
@ Script_Punctuation2
@ Script_Arabic
@ Script_Hebrew_Currency
@ Script_Control
@ Script_Georgian
@ Script_Mongolian
@ Script_Gurmukhi
@ Script_Thaana
@ Script_Tibetan
@ Script_Tamil
@ Script_New_Tai_Lue
@ Script_Latin
@ Script_Bengali_Currency
@ Script_New_Tai_Lue_Numeric
@ Script_Gujarati_Currency
@ Script_Canadian
@ Script_Greek
@ Script_Persian
@ Script_Armenian
@ Script_Surrogates
@ Script_Ideograph
@ Script_Osmanya
@ Script_Kana
@ Script_Lao_Numeric
@ Script_Myanmar_Numeric
@ Script_Numeric
@ Script_Ethiopic_Numeric
@ Script_Punctuation
@ Script_Gujarati
@ Script_Devanagari
@ Script_Lao
@ Script_Braille
@ Script_Khmer_Numeric
@ Script_CJK_Han
@ Script_Vai
@ Script_Malayalam
@ Script_MathAlpha
#define GLYPH_BLOCK_SIZE
#define BIDI_NEUTRAL
#define GLYPH_MAX
#define BIDI_STRONG
#define GLYPH_BLOCK_MASK
#define NUM_PAGES
#define BIDI_WEAK
static const WCHAR props[]
Definition: wbemdisp.c:288
DWORD WINAPI GetFontData(HDC hdc, DWORD dwTable, DWORD dwOffset, LPVOID lpvBuffer, DWORD cbData)
Definition: font.c:2654
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ FONTOBJ _In_ ULONG _In_ ULONG cGlyphs
Definition: winddi.h:3799
DWORD COLORREF
Definition: windef.h:300
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_POINTER
Definition: winerror.h:2365
int WINAPI GetBkMode(_In_ HDC)
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
#define RUSSIAN_CHARSET
Definition: wingdi.h:396
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
DWORD WINAPI GetGlyphIndicesW(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpstr, _In_ int c, _Out_writes_(c) LPWORD pgi, _In_ DWORD fl)
BOOL WINAPI GetCharWidthI(_In_ HDC hdc, _In_ UINT giFirst, _In_ UINT cgi, _In_reads_opt_(cgi) LPWORD pgi, _Out_writes_(cgi) LPINT piWidths)
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
COLORREF WINAPI GetTextColor(_In_ HDC)
Definition: text.c:861
BOOL WINAPI GetCharWidthW(_In_ HDC hdc, _In_ UINT iFirst, _In_ UINT iLast, _Out_writes_(iLast+1 - iFirst) LPINT lpBuffer)
#define ARABIC_CHARSET
Definition: wingdi.h:394
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
#define DEFAULT_CHARSET
Definition: wingdi.h:384
#define THAI_CHARSET
Definition: wingdi.h:397
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
#define GREEK_CHARSET
Definition: wingdi.h:391
COLORREF WINAPI GetBkColor(_In_ HDC)
Definition: dc.c:978
#define ETO_CLIPPED
Definition: wingdi.h:648
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCWSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
#define ETO_OPAQUE
Definition: wingdi.h:647
#define OPAQUE
Definition: wingdi.h:949
#define ANSI_CHARSET
Definition: wingdi.h:383
BOOL WINAPI GetCharABCWidthsI(_In_ HDC hdc, _In_ UINT giFirst, _In_ UINT cgi, _In_reads_opt_(cgi) LPWORD pgi, _Out_writes_(cgi) LPABC pabc)
#define GDI_ERROR
Definition: wingdi.h:1309
#define ETO_PDY
Definition: wingdi.h:657
UINT WINAPI GetOutlineTextMetricsW(_In_ HDC hdc, _In_ UINT cjCopy, _Out_writes_bytes_opt_(cjCopy) LPOUTLINETEXTMETRICW potm)
#define VIETNAMESE_CHARSET
Definition: wingdi.h:402
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
#define HEBREW_CHARSET
Definition: wingdi.h:393
#define GGI_MARK_NONEXISTING_GLYPHS
Definition: wingdi.h:1085
BOOL WINAPI GetCharABCWidthsW(_In_ HDC hdc, _In_ UINT wFirst, _In_ UINT wLast, _Out_writes_(wLast - wFirst+1) LPABC lpABC)
#define IS_SURROGATE_PAIR(high, low)
Definition: winnls.h:681
#define C2_ARABICNUMBER
Definition: winnls.h:255
#define LCID_INSTALLED
Definition: winnls.h:201
#define CT_CTYPE2
Definition: winnls.h:238
#define CT_CTYPE1
Definition: winnls.h:237
#define HKEY_CURRENT_USER
Definition: winreg.h:11
DWORD WINAPI GetSysColor(_In_ int)
BOOL WINAPI CopyRect(_Out_ LPRECT, _In_ LPCRECT)
#define COLOR_HIGHLIGHT
Definition: winuser.h:926
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:927
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4466
static unsigned int block
Definition: xmlmemory.c:101
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193