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