ReactOS 0.4.17-dev-966-gf06eace
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 unsigned size;
793 LOGFONTW lf;
794
795 if (!psc) return E_INVALIDARG;
796 if (*psc) return S_OK;
797 if (!hdc) return E_PENDING;
798
799 if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf))
800 {
801 return E_INVALIDARG;
802 }
803 /* Ensure canonical result by zeroing extra space in lfFaceName */
805 memset(lf.lfFaceName + size, 0, sizeof(lf.lfFaceName) - size * sizeof(WCHAR));
806
809 {
810 if (!memcmp(&sc->lf, &lf, sizeof(lf)))
811 {
812 sc->refcount++;
814 *psc = sc;
815 return S_OK;
816 }
817 }
819
820 if (!(sc = calloc(1, sizeof(ScriptCache)))) return E_OUTOFMEMORY;
821 if (!GetTextMetricsW(hdc, &sc->tm))
822 {
823 free(sc);
824 return E_INVALIDARG;
825 }
827 if (size)
828 {
829 sc->otm = malloc(size);
830 sc->otm->otmSize = size;
832 }
833 sc->sfnt = (NtGdiGetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0) != GDI_ERROR);
835 {
836 free(sc);
837 return E_INVALIDARG;
838 }
839 sc->lf = lf;
840 sc->refcount = 1;
841 *psc = sc;
842
846 {
847 if (sc != *psc && !memcmp(&sc->lf, &lf, sizeof(lf)))
848 {
849 /* Another thread won the race. Use their cache instead of ours */
850 list_remove(&sc->entry);
851 sc->refcount++;
853 free(*psc);
854 *psc = sc;
855 return S_OK;
856 }
857 }
859 TRACE("<- %p\n", sc);
860 return S_OK;
861}
862
864{
865 extern const WCHAR wine_mirror_map[];
867 return mirror ? mirror : ch;
868}
869
870static DWORD decode_surrogate_pair(const WCHAR *str, unsigned int index, unsigned int end)
871{
872 if (index < end-1 && IS_SURROGATE_PAIR(str[index],str[index+1]))
873 {
874 DWORD ch = 0x10000 + ((str[index] - 0xd800) << 10) + (str[index+1] - 0xdc00);
875 TRACE("Surrogate Pair %x %x => %lx\n",str[index], str[index+1], ch);
876 return ch;
877 }
878 return 0;
879}
880
881static int __cdecl usp10_compare_script_range(const void *key, const void *value)
882{
883 const struct usp10_script_range *range = value;
884 const DWORD *ch = key;
885
886 if (*ch < range->rangeFirst)
887 return -1;
888 if (*ch > range->rangeLast)
889 return 1;
890 return 0;
891}
892
893static enum usp10_script get_char_script(const WCHAR *str, unsigned int index,
894 unsigned int end, unsigned int *consumed)
895{
897 WORD type = 0, type2 = 0;
898 DWORD ch;
899
900 *consumed = 1;
901
902 if (str[index] == 0xc || str[index] == 0x20 || str[index] == 0x202f)
903 return Script_CR;
904
905 /* These punctuation characters are separated out as Latin punctuation */
906 if (wcschr(L"#$&',;<>?@\\^_`{|}~\x00a0", str[index]))
907 return Script_Punctuation2;
908
909 /* These chars are itemized as Punctuation by Windows */
910 if (str[index] == 0x2212 || str[index] == 0x2044)
911 return Script_Punctuation;
912
913 /* Currency Symbols by Unicode point */
914 switch (str[index])
915 {
916 case 0x09f2:
917 case 0x09f3: return Script_Bengali_Currency;
918 case 0x0af1: return Script_Gujarati_Currency;
919 case 0x0e3f: return Script_Thai_Currency;
920 case 0x20aa: return Script_Hebrew_Currency;
921 case 0x20ab: return Script_Vietnamese_Currency;
922 case 0xfb29: return Script_Hebrew_Currency;
923 }
924
926 GetStringTypeW(CT_CTYPE2, &str[index], 1, &type2);
927
928 if (type == 0)
929 return SCRIPT_UNDEFINED;
930
931 if (type & C1_CNTRL)
932 return Script_Control;
933
935 if (ch)
936 *consumed = 2;
937 else
938 ch = str[index];
939
943
944 if (range->numericScript && (type & C1_DIGIT || type2 == C2_ARABICNUMBER))
945 return range->numericScript;
946 if (range->punctScript && type & C1_PUNCT)
947 return range->punctScript;
948 return range->script;
949}
950
951static int __cdecl compare_FindGlyph(const void *a, const void* b)
952{
954 const WORD *idx= (WORD*)b;
955 int rc = 0;
956
957 if ( find->target > *idx)
958 rc = 1;
959 else if (find->target < *idx)
960 rc = -1;
961
962 if (!find->ascending)
963 rc *= -1;
964 return rc;
965}
966
967int USP10_FindGlyphInLogClust(const WORD* pwLogClust, int cChars, WORD target)
968{
970 WORD *ptr;
971 INT k;
972
973 if (pwLogClust[0] < pwLogClust[cChars-1])
974 fgs.ascending = TRUE;
975 else
976 fgs.ascending = FALSE;
977
978 fgs.target = target;
979 ptr = bsearch(&fgs, pwLogClust, cChars, sizeof(WORD), compare_FindGlyph);
980
981 if (!ptr)
982 return -1;
983
984 for (k = (ptr - pwLogClust)-1; k >= 0 && pwLogClust[k] == target; k--)
985 ;
986 k++;
987
988 return k;
989}
990
991/***********************************************************************
992 * ScriptFreeCache (USP10.@)
993 *
994 * Free a script cache.
995 *
996 * PARAMS
997 * psc [I/O] Script cache.
998 *
999 * RETURNS
1000 * Success: S_OK
1001 * Failure: Non-zero HRESULT value.
1002 */
1004{
1005 TRACE("%p\n", psc);
1006
1007 if (psc && *psc)
1008 {
1009 ScriptCache *sc = *psc;
1010 unsigned int i;
1011 INT n;
1012
1014 if (--sc->refcount > 0)
1015 {
1017 *psc = NULL;
1018 return S_OK;
1019 }
1020 list_remove(&sc->entry);
1022
1023 for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++)
1024 {
1025 free(sc->widths[i]);
1026 }
1027 for (i = 0; i < NUM_PAGES; i++)
1028 {
1029 unsigned int j;
1030 if (sc->page[i])
1031 for (j = 0; j < GLYPH_MAX / GLYPH_BLOCK_SIZE; j++)
1032 free(sc->page[i]->glyphs[j]);
1033 free(sc->page[i]);
1034 }
1035 free(sc->GSUB_Table);
1036 free(sc->GDEF_Table);
1037 free(sc->CMAP_Table);
1038 free(sc->GPOS_Table);
1039 for (n = 0; n < sc->script_count; n++)
1040 {
1041 int j;
1042 for (j = 0; j < sc->scripts[n].language_count; j++)
1043 {
1044 int k;
1045 for (k = 0; k < sc->scripts[n].languages[j].feature_count; k++)
1048 }
1049 for (j = 0; j < sc->scripts[n].default_language.feature_count; j++)
1052 free(sc->scripts[n].languages);
1053 }
1054 free(sc->scripts);
1055 free(sc->otm);
1056 free(sc);
1057 *psc = NULL;
1058 }
1059 return S_OK;
1060}
1061
1062/***********************************************************************
1063 * ScriptGetProperties (USP10.@)
1064 *
1065 * Retrieve a list of script properties.
1066 *
1067 * PARAMS
1068 * props [I] Pointer to an array of SCRIPT_PROPERTIES pointers.
1069 * num [I] Pointer to the number of scripts.
1070 *
1071 * RETURNS
1072 * Success: S_OK
1073 * Failure: Non-zero HRESULT value.
1074 *
1075 * NOTES
1076 * Behaviour matches WinXP.
1077 */
1079{
1080 TRACE("(%p,%p)\n", props, num);
1081
1082 if (!props && !num) return E_INVALIDARG;
1083
1084 if (num) *num = ARRAY_SIZE(script_props);
1085 if (props) *props = script_props;
1086
1087 return S_OK;
1088}
1089
1090/***********************************************************************
1091 * ScriptGetFontProperties (USP10.@)
1092 *
1093 * Get information on special glyphs.
1094 *
1095 * PARAMS
1096 * hdc [I] Device context.
1097 * psc [I/O] Opaque pointer to a script cache.
1098 * sfp [O] Font properties structure.
1099 */
1101{
1102 HRESULT hr;
1103
1104 TRACE("%p,%p,%p\n", hdc, psc, sfp);
1105
1106 if (!sfp) return E_INVALIDARG;
1107 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
1108
1109 if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES))
1110 return E_INVALIDARG;
1111
1112 get_cache_font_properties(sfp, *psc);
1113
1114 return S_OK;
1115}
1116
1117/***********************************************************************
1118 * ScriptRecordDigitSubstitution (USP10.@)
1119 *
1120 * Record digit substitution settings for a given locale.
1121 *
1122 * PARAMS
1123 * locale [I] Locale identifier.
1124 * sds [I] Structure to record substitution settings.
1125 *
1126 * RETURNS
1127 * Success: S_OK
1128 * Failure: E_POINTER if sds is NULL, E_INVALIDARG otherwise.
1129 *
1130 * SEE ALSO
1131 * http://blogs.msdn.com/michkap/archive/2006/02/22/536877.aspx
1132 */
1134{
1135 DWORD plgid, sub;
1136
1137 TRACE("0x%lx, %p\n", locale, sds);
1138
1139 /* This implementation appears to be correct for all languages, but it's
1140 * not clear if sds->DigitSubstitute is ever set to anything except
1141 * CONTEXT or NONE in reality */
1142
1143 if (!sds) return E_POINTER;
1144
1146
1148 return E_INVALIDARG;
1149
1151 sds->TraditionalDigitLanguage = plgid;
1152
1153 if (plgid == LANG_ARABIC || plgid == LANG_FARSI)
1154 sds->NationalDigitLanguage = plgid;
1155 else
1157
1158 if (!GetLocaleInfoW(locale, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER,
1159 (WCHAR *)&sub, sizeof(sub) / sizeof(WCHAR)))
1160 return E_INVALIDARG;
1161
1162 switch (sub)
1163 {
1164 case 0:
1165 if (plgid == LANG_ARABIC || plgid == LANG_FARSI)
1167 else
1169 break;
1170 case 1:
1172 break;
1173 case 2:
1175 break;
1176 default:
1178 break;
1179 }
1180
1181 sds->dwReserved = 0;
1182 return S_OK;
1183}
1184
1185/***********************************************************************
1186 * ScriptApplyDigitSubstitution (USP10.@)
1187 *
1188 * Apply digit substitution settings.
1189 *
1190 * PARAMS
1191 * sds [I] Structure with recorded substitution settings.
1192 * sc [I] Script control structure.
1193 * ss [I] Script state structure.
1194 *
1195 * RETURNS
1196 * Success: S_OK
1197 * Failure: E_INVALIDARG if sds is invalid. Otherwise an HRESULT.
1198 */
1201{
1203
1204 TRACE("%p, %p, %p\n", sds, sc, ss);
1205
1206 if (!sc || !ss) return E_POINTER;
1207 if (!sds)
1208 {
1209 sds = &psds;
1211 return E_INVALIDARG;
1212 }
1213
1215 sc->fContextDigits = 0;
1216 ss->fDigitSubstitute = 0;
1217
1218 switch (sds->DigitSubstitute) {
1223 return S_OK;
1224 default:
1225 return E_INVALIDARG;
1226 }
1227}
1228
1230{
1232}
1233
1235{
1236 switch (script)
1237 {
1238 case Script_Devanagari:
1240 case Script_Bengali:
1243 case Script_Gurmukhi:
1245 case Script_Gujarati:
1248 case Script_Oriya:
1250 case Script_Tamil:
1252 case Script_Telugu:
1254 case Script_Kannada:
1256 case Script_Malayalam:
1258 default:
1259 return Script_Undefined;
1260 };
1261}
1262
1264{
1266}
1267
1268static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars,
1269 int cMaxItems, const SCRIPT_CONTROL *psControl,
1270 const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems,
1271 OPENTYPE_TAG *pScriptTags, int *pcItems)
1272{
1273
1274#define Numeric_space 0x0020
1275#define ZWSP 0x200B
1276#define ZWNJ 0x200C
1277#define ZWJ 0x200D
1278
1279 enum usp10_script last_indic = Script_Undefined;
1280 int cnt = 0, index = 0, str = 0;
1281 enum usp10_script New_Script = -1;
1282 int i;
1283 WORD *levels = NULL;
1284 WORD *layout_levels = NULL;
1285 WORD *overrides = NULL;
1286 WORD *strength = NULL;
1287 enum usp10_script *scripts;
1288 WORD baselevel = 0;
1289 WORD baselayout = 0;
1290 BOOL new_run;
1291 WORD layoutRTL = 0;
1292 BOOL forceLevels = FALSE;
1293 unsigned int consumed = 0;
1295
1296 TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems,
1297 psControl, psState, pItems, pcItems);
1298
1299 if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2)
1300 return E_INVALIDARG;
1301
1302 if (!(scripts = calloc(cInChars, sizeof(*scripts))))
1303 return E_OUTOFMEMORY;
1304
1305 for (i = 0; i < cInChars; i++)
1306 {
1307 if (!consumed)
1308 {
1309 scripts[i] = get_char_script(pwcInChars,i,cInChars,&consumed);
1310 consumed --;
1311 }
1312 else
1313 {
1314 scripts[i] = scripts[i-1];
1315 consumed --;
1316 }
1317 /* Devanagari danda (U+0964) and double danda (U+0965) are used for
1318 all Indic scripts */
1319 if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic != Script_Undefined)
1320 scripts[i] = last_indic;
1321 else if (is_indic(scripts[i]))
1322 last_indic = base_indic(scripts[i]);
1323
1324 /* Some unicode points :
1325 (Zero Width Space U+200B - Right-to-Left Mark U+200F)
1326 (Left Right Embed U+202A - Left Right Override U+202D)
1327 (Left Right Isolate U+2066 - Pop Directional Isolate U+2069)
1328 will force us into bidi mode */
1329 if (!forceLevels && ((pwcInChars[i] >= 0x200B && pwcInChars[i] <= 0x200F) ||
1330 (pwcInChars[i] >= 0x202A && pwcInChars[i] <= 0x202E) ||
1331 (pwcInChars[i] >= 0x2066 && pwcInChars[i] <= 0x2069)))
1332
1333 forceLevels = TRUE;
1334
1335 /* Diacritical marks merge with other scripts */
1336 if (scripts[i] == Script_Diacritical)
1337 {
1338 if (i > 0)
1339 {
1340 if (pScriptTags)
1341 scripts[i] = scripts[i-1];
1342 else
1343 {
1344 int j;
1345 BOOL asian = FALSE;
1346 enum usp10_script first_script = scripts[i-1];
1347 for (j = i-1; j >= 0 && scripts[j] == first_script && pwcInChars[j] != Numeric_space; j--)
1348 {
1349 enum usp10_script original = scripts[j];
1350 if (original == Script_Ideograph || original == Script_Kana || original == Script_Yi || original == Script_CJK_Han || original == Script_Bopomofo)
1351 {
1352 asian = TRUE;
1353 break;
1354 }
1355 if (original != Script_MathAlpha && scriptInformation[scripts[j]].props.fComplex)
1356 break;
1357 scripts[j] = scripts[i];
1358 if (original == Script_Punctuation2)
1359 break;
1360 }
1361 if (j >= 0 && (scriptInformation[scripts[j]].props.fComplex || asian))
1362 scripts[i] = scripts[j];
1363 }
1364 }
1365 }
1366 }
1367
1368 for (i = 0; i < cInChars; i++)
1369 {
1370 /* Joiners get merged preferencially right */
1371 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ || pwcInChars[i] == ZWSP))
1372 {
1373 int j;
1374 if (i+1 == cInChars)
1375 scripts[i] = scripts[i-1];
1376 else
1377 {
1378 for (j = i+1; j < cInChars; j++)
1379 {
1380 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
1381 && pwcInChars[j] != ZWSP && pwcInChars[j] != Numeric_space)
1382 {
1383 scripts[i] = scripts[j];
1384 break;
1385 }
1386 }
1387 }
1388 }
1389 }
1390
1391 if (psState && psControl)
1392 {
1393 if (!(levels = calloc(cInChars, sizeof(*levels))))
1394 goto nomemory;
1395
1396 if (!(overrides = calloc(cInChars, sizeof(*overrides))))
1397 goto nomemory;
1398
1399 if (!(layout_levels = calloc(cInChars, sizeof(*layout_levels))))
1400 goto nomemory;
1401
1402 if (psState->fOverrideDirection)
1403 {
1404 if (!forceLevels)
1405 {
1406 SCRIPT_STATE s = *psState;
1408 BIDI_DetermineLevels(pwcInChars, cInChars, &s, psControl, layout_levels, overrides);
1409 if (odd(layout_levels[0]))
1410 forceLevels = TRUE;
1411 else for (i = 0; i < cInChars; i++)
1412 if (layout_levels[i]!=layout_levels[0])
1413 {
1414 forceLevels = TRUE;
1415 break;
1416 }
1417 }
1418
1419 BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels, overrides);
1420 }
1421 else
1422 {
1423 BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels, overrides);
1424 memcpy(layout_levels, levels, cInChars * sizeof(WORD));
1425 }
1426 baselevel = levels[0];
1427 baselayout = layout_levels[0];
1428 for (i = 0; i < cInChars; i++)
1429 if (levels[i]!=levels[0])
1430 break;
1431 if (i >= cInChars && !odd(baselevel) && !odd(psState->uBidiLevel) && !forceLevels)
1432 {
1433 free(levels);
1434 free(overrides);
1435 free(layout_levels);
1436 overrides = NULL;
1437 levels = NULL;
1438 layout_levels = NULL;
1439 }
1440 else
1441 {
1442 if (!(strength = calloc(cInChars, sizeof(*strength))))
1443 goto nomemory;
1444 BIDI_GetStrengths(pwcInChars, cInChars, psControl, strength);
1445
1446 /* We currently mis-level leading Diacriticals */
1447 if (scripts[0] == Script_Diacritical)
1448 for (i = 0; i < cInChars && scripts[0] == Script_Diacritical; i++)
1449 {
1450 levels[i] = odd(levels[i])?levels[i]+1:levels[i];
1451 strength[i] = BIDI_STRONG;
1452 }
1453
1454 /* Math punctuation bordered on both sides by numbers can be
1455 merged into the number */
1456 for (i = 0; i < cInChars; i++)
1457 {
1458 if (i > 0 && i < cInChars-1 &&
1459 script_is_numeric(scripts[i-1]) &&
1460 wcschr(L"#$%+,-./:\x2212\x2044\x00a0", pwcInChars[i]))
1461 {
1462 if (script_is_numeric(scripts[i+1]))
1463 {
1464 scripts[i] = scripts[i+1];
1465 levels[i] = levels[i-1];
1466 strength[i] = strength[i-1];
1467 i++;
1468 }
1469 else if (wcschr(L"#$%+-/\x2212\x2044", pwcInChars[i]))
1470 {
1471 int j;
1472 for (j = i+1; j < cInChars; j++)
1473 {
1474 if (script_is_numeric(scripts[j]))
1475 {
1476 for(;i<j; i++)
1477 {
1478 scripts[i] = scripts[j];
1479 levels[i] = levels[i-1];
1480 strength[i] = strength[i-1];
1481 }
1482 }
1483 else if (pwcInChars[i] != pwcInChars[j]) break;
1484 }
1485 }
1486 }
1487 }
1488
1489 for (i = 0; i < cInChars; i++)
1490 {
1491 /* Numerics at level 0 get bumped to level 2 */
1492 if (!overrides[i] && (levels[i] == 0 || (odd(psState->uBidiLevel)
1493 && levels[i] == psState->uBidiLevel + 1)) && script_is_numeric(scripts[i]))
1494 {
1495 levels[i] = 2;
1496 }
1497
1498 /* Joiners get merged preferencially right */
1499 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ || pwcInChars[i] == ZWSP))
1500 {
1501 int j;
1502 if (i+1 == cInChars && levels[i-1] == levels[i])
1503 strength[i] = strength[i-1];
1504 else
1505 for (j = i+1; j < cInChars && levels[i] == levels[j]; j++)
1506 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ
1507 && pwcInChars[j] != ZWSP && pwcInChars[j] != Numeric_space)
1508 {
1509 strength[i] = strength[j];
1510 break;
1511 }
1512 }
1513 }
1514 if (psControl->fMergeNeutralItems)
1515 {
1516 /* Merge the neutrals */
1517 for (i = 0; i < cInChars; i++)
1518 {
1519 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK)
1520 {
1521 int j;
1522 for (j = i; j > 0; j--)
1523 {
1524 if (levels[i] != levels[j])
1525 break;
1526 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK))
1527 {
1528 scripts[i] = scripts[j];
1529 strength[i] = strength[j];
1530 break;
1531 }
1532 }
1533 }
1534 /* Try going the other way */
1535 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK)
1536 {
1537 int j;
1538 for (j = i; j < cInChars; j++)
1539 {
1540 if (levels[i] != levels[j])
1541 break;
1542 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK))
1543 {
1544 scripts[i] = scripts[j];
1545 strength[i] = strength[j];
1546 break;
1547 }
1548 }
1549 }
1550 }
1551 }
1552 }
1553 }
1554
1555 while ((!levels || (levels && cnt+1 < cInChars && levels[cnt+1] == levels[0]))
1556 && (cnt < cInChars && pwcInChars[cnt] == Numeric_space))
1557 cnt++;
1558
1559 if (cnt == cInChars) /* All Spaces */
1560 {
1561 cnt = 0;
1562 New_Script = scripts[cnt];
1563 }
1564
1565 pItems[index].iCharPos = 0;
1566 pItems[index].a = scriptInformation[scripts[cnt]].a;
1567 if (pScriptTags)
1568 pScriptTags[index] = scriptInformation[scripts[cnt]].scriptTag;
1569
1570 if (strength && strength[cnt] == BIDI_STRONG)
1571 str = strength[cnt];
1572 else if (strength)
1573 str = strength[0];
1574
1575 cnt = 0;
1576
1577 if (levels)
1578 {
1579 if (strength[cnt] == BIDI_STRONG)
1580 layoutRTL = odd(layout_levels[cnt]);
1581 else
1582 layoutRTL = (psState->uBidiLevel || odd(layout_levels[cnt]));
1583 if (overrides)
1584 pItems[index].a.s.fOverrideDirection = (overrides[cnt] != 0);
1585 pItems[index].a.fRTL = odd(levels[cnt]);
1586 if (script_is_numeric(pItems[index].a.eScript))
1587 pItems[index].a.fLayoutRTL = layoutRTL;
1588 else
1589 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1590 pItems[index].a.s.uBidiLevel = levels[cnt];
1591 }
1592 else if (!pItems[index].a.s.uBidiLevel || (overrides && overrides[cnt]))
1593 {
1594 if (pItems[index].a.s.uBidiLevel != baselevel)
1595 pItems[index].a.s.fOverrideDirection = TRUE;
1596 layoutRTL = odd(baselayout);
1597 pItems[index].a.s.uBidiLevel = baselevel;
1598 pItems[index].a.fRTL = odd(baselevel);
1599 if (script_is_numeric(pItems[index].a.eScript))
1600 pItems[index].a.fLayoutRTL = odd(baselayout);
1601 else
1602 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1603 }
1604
1605 TRACE("New_Level=%i New_Strength=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n",
1606 levels?levels[cnt]:-1, str, New_Script, pItems[index].a.eScript, index, cnt,
1607 pItems[index].iCharPos);
1608
1609 for (cnt=1; cnt < cInChars; cnt++)
1610 {
1611 if(pwcInChars[cnt] != Numeric_space)
1612 New_Script = scripts[cnt];
1613 else if (levels)
1614 {
1615 int j = 1;
1616 while (cnt + j < cInChars - 1 && pwcInChars[cnt+j] == Numeric_space && levels[cnt] == levels[cnt+j])
1617 j++;
1618 if (cnt + j < cInChars && levels[cnt] == levels[cnt+j])
1619 New_Script = scripts[cnt+j];
1620 else
1621 New_Script = scripts[cnt];
1622 }
1623
1624 new_run = FALSE;
1625 /* merge space strengths*/
1626 if (strength && strength[cnt] == BIDI_STRONG && str != BIDI_STRONG && New_Script == pItems[index].a.eScript)
1627 str = BIDI_STRONG;
1628
1629 if (strength && strength[cnt] == BIDI_NEUTRAL && str == BIDI_STRONG && pwcInChars[cnt] != Numeric_space && New_Script == pItems[index].a.eScript)
1630 str = BIDI_NEUTRAL;
1631
1632 /* changes in level */
1633 if (levels && (levels[cnt] != pItems[index].a.s.uBidiLevel))
1634 {
1635 TRACE("Level break(%i/%i)\n",pItems[index].a.s.uBidiLevel,levels[cnt]);
1636 new_run = TRUE;
1637 }
1638 /* changes in strength */
1639 else if (strength && pwcInChars[cnt] != Numeric_space && str != strength[cnt])
1640 {
1641 TRACE("Strength break (%i/%i)\n",str,strength[cnt]);
1642 new_run = TRUE;
1643 }
1644 /* changes in script */
1645 else if (((pwcInChars[cnt] != Numeric_space) && (New_Script != -1) && (New_Script != pItems[index].a.eScript)) || (New_Script == Script_Control))
1646 {
1647 TRACE("Script break(%i/%i)\n",pItems[index].a.eScript,New_Script);
1648 new_run = TRUE;
1649 }
1650
1651 if (!new_run && strength && str == BIDI_STRONG)
1652 {
1653 layoutRTL = odd(layout_levels[cnt]);
1654 if (script_is_numeric(pItems[index].a.eScript))
1655 pItems[index].a.fLayoutRTL = layoutRTL;
1656 }
1657
1658 if (new_run)
1659 {
1660 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);
1661
1662 index++;
1663 if (index+1 > cMaxItems)
1664 goto nomemory;
1665
1666 if (strength)
1667 str = strength[cnt];
1668
1669 pItems[index].iCharPos = cnt;
1670 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
1671
1672 pItems[index].a = scriptInformation[New_Script].a;
1673 if (pScriptTags)
1674 pScriptTags[index] = scriptInformation[New_Script].scriptTag;
1675 if (levels)
1676 {
1677 if (overrides)
1678 pItems[index].a.s.fOverrideDirection = (overrides[cnt] != 0);
1679 if (layout_levels[cnt] == 0)
1680 layoutRTL = 0;
1681 else
1682 layoutRTL = (layoutRTL || odd(layout_levels[cnt]));
1683 pItems[index].a.fRTL = odd(levels[cnt]);
1684 if (script_is_numeric(pItems[index].a.eScript))
1685 pItems[index].a.fLayoutRTL = layoutRTL;
1686 else
1687 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1688 pItems[index].a.s.uBidiLevel = levels[cnt];
1689 }
1690 else if (!pItems[index].a.s.uBidiLevel || (overrides && overrides[cnt]))
1691 {
1692 if (pItems[index].a.s.uBidiLevel != baselevel)
1693 pItems[index].a.s.fOverrideDirection = TRUE;
1694 pItems[index].a.s.uBidiLevel = baselevel;
1695 pItems[index].a.fRTL = odd(baselevel);
1696 if (script_is_numeric(pItems[index].a.eScript))
1697 pItems[index].a.fLayoutRTL = layoutRTL;
1698 else
1699 pItems[index].a.fLayoutRTL = pItems[index].a.fRTL;
1700 }
1701
1702 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos);
1703 }
1704 }
1705
1706 /* While not strictly necessary according to the spec, make sure the n+1
1707 * item is set up to prevent random behaviour if the caller erroneously
1708 * checks the n+1 structure */
1709 index++;
1710 if (index + 1 > cMaxItems) goto nomemory;
1711 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
1712
1713 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos);
1714
1715 /* Set one SCRIPT_STATE item being returned */
1716 if (pcItems) *pcItems = index;
1717
1718 /* Set SCRIPT_ITEM */
1719 pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */
1720 res = S_OK;
1721nomemory:
1722 free(levels);
1723 free(overrides);
1724 free(layout_levels);
1725 free(strength);
1726 free(scripts);
1727 return res;
1728}
1729
1730/***********************************************************************
1731 * ScriptItemizeOpenType (USP10.@)
1732 *
1733 * Split a Unicode string into shapeable parts.
1734 *
1735 * PARAMS
1736 * pwcInChars [I] String to split.
1737 * cInChars [I] Number of characters in pwcInChars.
1738 * cMaxItems [I] Maximum number of items to return.
1739 * psControl [I] Pointer to a SCRIPT_CONTROL structure.
1740 * psState [I] Pointer to a SCRIPT_STATE structure.
1741 * pItems [O] Buffer to receive SCRIPT_ITEM structures.
1742 * pScriptTags [O] Buffer to receive OPENTYPE_TAGs.
1743 * pcItems [O] Number of script items returned.
1744 *
1745 * RETURNS
1746 * Success: S_OK
1747 * Failure: Non-zero HRESULT value.
1748 */
1749HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems,
1750 const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState,
1751 SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems)
1752{
1753 return _ItemizeInternal(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, pScriptTags, pcItems);
1754}
1755
1756/***********************************************************************
1757 * ScriptItemize (USP10.@)
1758 *
1759 * Split a Unicode string into shapeable parts.
1760 *
1761 * PARAMS
1762 * pwcInChars [I] String to split.
1763 * cInChars [I] Number of characters in pwcInChars.
1764 * cMaxItems [I] Maximum number of items to return.
1765 * psControl [I] Pointer to a SCRIPT_CONTROL structure.
1766 * psState [I] Pointer to a SCRIPT_STATE structure.
1767 * pItems [O] Buffer to receive SCRIPT_ITEM structures.
1768 * pcItems [O] Number of script items returned.
1769 *
1770 * RETURNS
1771 * Success: S_OK
1772 * Failure: Non-zero HRESULT value.
1773 */
1774HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems,
1775 const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState,
1776 SCRIPT_ITEM *pItems, int *pcItems)
1777{
1778 return _ItemizeInternal(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, NULL, pcItems);
1779}
1780
1781static inline int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x)
1782{
1783 int defWidth;
1784 int cTabStops=0;
1785 INT *lpTabPos = NULL;
1786 INT nTabOrg = 0;
1787 INT x = 0;
1788
1789 if (pTabdef)
1790 lpTabPos = pTabdef->pTabStops;
1791
1792 if (pTabdef && pTabdef->iTabOrigin)
1793 {
1794 if (pTabdef->iScale)
1795 nTabOrg = (pTabdef->iTabOrigin * pTabdef->iScale)/4;
1796 else
1797 nTabOrg = pTabdef->iTabOrigin * psc->tm.tmAveCharWidth;
1798 }
1799
1800 if (pTabdef)
1801 cTabStops = pTabdef->cTabStops;
1802
1803 if (cTabStops == 1)
1804 {
1805 if (pTabdef->iScale)
1806 defWidth = ((pTabdef->pTabStops[0])*pTabdef->iScale) / 4;
1807 else
1808 defWidth = (pTabdef->pTabStops[0])*psc->tm.tmAveCharWidth;
1809 cTabStops = 0;
1810 }
1811 else
1812 {
1813 if (pTabdef->iScale)
1814 defWidth = (32 * pTabdef->iScale) / 4;
1815 else
1816 defWidth = 8 * psc->tm.tmAveCharWidth;
1817 }
1818
1819 for (; cTabStops>0 ; lpTabPos++, cTabStops--)
1820 {
1821 int position = *lpTabPos;
1822 if (position < 0)
1823 position = -1 * position;
1824 if (pTabdef->iScale)
1825 position = (position * pTabdef->iScale) / 4;
1826 else
1827 position = position * psc->tm.tmAveCharWidth;
1828
1829 if( nTabOrg + position > current_x)
1830 {
1831 if( position >= 0)
1832 {
1833 /* a left aligned tab */
1834 x = (nTabOrg + position) - current_x;
1835 break;
1836 }
1837 else
1838 {
1839 FIXME("Negative tabstop\n");
1840 break;
1841 }
1842 }
1843 }
1844 if ((!cTabStops) && (defWidth > 0))
1845 x =((((current_x - nTabOrg) / defWidth)+1) * defWidth) - current_x;
1846 else if ((!cTabStops) && (defWidth < 0))
1847 FIXME("TODO: Negative defWidth\n");
1848
1849 return x;
1850}
1851
1852/***********************************************************************
1853 * Helper function for ScriptStringAnalyse
1854 */
1856 const WCHAR *pwcInChars, int cChars )
1857{
1858 /* FIXME: When to properly fallback is still a bit of a mystery */
1859 WORD *glyphs;
1860
1861 if (psa->fNoGlyphIndex)
1862 return FALSE;
1863
1864 if (init_script_cache(hdc, psc) != S_OK)
1865 return FALSE;
1866
1868 return TRUE;
1869
1870 if (!(glyphs = calloc(cChars, sizeof(*glyphs))))
1871 return FALSE;
1872 if (ScriptGetCMap(hdc, psc, pwcInChars, cChars, 0, glyphs) != S_OK)
1873 {
1874 free(glyphs);
1875 return TRUE;
1876 }
1877 free(glyphs);
1878
1879 return FALSE;
1880}
1881
1882static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName)
1883{
1884 HKEY hkey;
1885
1886 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Uniscribe\\Fallback", &hkey))
1887 {
1888 WCHAR value[10];
1889 DWORD count = LF_FACESIZE * sizeof(WCHAR);
1890 DWORD type;
1891
1892 swprintf(value, ARRAY_SIZE(value), L"%x", scriptInformation[scriptid].scriptTag);
1893 if (RegQueryValueExW(hkey, value, 0, &type, (BYTE *)FaceName, &count))
1894 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont);
1895 RegCloseKey(hkey);
1896 }
1897 else
1898 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont);
1899}
1900
1901/***********************************************************************
1902 * ScriptStringAnalyse (USP10.@)
1903 *
1904 */
1906 int cGlyphs, int iCharset, DWORD dwFlags,
1907 int iReqWidth, SCRIPT_CONTROL *psControl,
1908 SCRIPT_STATE *psState, const int *piDx,
1909 SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass,
1911{
1913 StringAnalysis *analysis = NULL;
1914 SCRIPT_CONTROL sControl;
1915 SCRIPT_STATE sState;
1916 int i, num_items = cString + 1;
1917 BYTE *BidiLevel = NULL;
1918 WCHAR *iString = NULL;
1920
1921 TRACE("(%p,%p,%d,%d,%d,0x%lx,%d,%p,%p,%p,%p,%p,%p)\n",
1922 hdc, pString, cString, cGlyphs, iCharset, dwFlags, iReqWidth,
1923 psControl, psState, piDx, pTabdef, pbInClass, pssa);
1924
1925 if (iCharset != -1)
1926 {
1927 FIXME("Only Unicode strings are supported\n");
1928 return E_INVALIDARG;
1929 }
1930 if (cString < 1 || !pString) return E_INVALIDARG;
1931 if ((dwFlags & SSA_GLYPHS) && !hdc) return E_PENDING;
1932
1933 if (!(analysis = calloc(1, sizeof(*analysis))))
1934 return E_OUTOFMEMORY;
1935 if (!(analysis->pItem = calloc(num_items, sizeof(*analysis->pItem))))
1936 goto error;
1937
1938 /* FIXME: handle clipping */
1939 analysis->clip_len = cString;
1940 analysis->hdc = hdc;
1941 analysis->ssa_flags = dwFlags;
1942
1943 if (psState)
1944 sState = *psState;
1945 else
1946 memset(&sState, 0, sizeof(SCRIPT_STATE));
1947
1948 if (psControl)
1949 sControl = *psControl;
1950 else
1951 memset(&sControl, 0, sizeof(SCRIPT_CONTROL));
1952
1953 if (dwFlags & SSA_PASSWORD)
1954 {
1955 if (!(iString = calloc(cString, sizeof(*iString))))
1956 {
1957 hr = E_OUTOFMEMORY;
1958 goto error;
1959 }
1960 for (i = 0; i < cString; i++)
1961 iString[i] = *((const WCHAR *)pString);
1962 pString = iString;
1963 }
1964
1965 hr = ScriptItemize(pString, cString, num_items, &sControl, &sState, analysis->pItem,
1966 &analysis->numItems);
1967 if (FAILED(hr))
1968 goto error;
1969
1970 /* Having as many items as codepoints is the worst case scenario, try to reclaim some memory. */
1971 if ((items = realloc(analysis->pItem, (analysis->numItems + 1) * sizeof(*analysis->pItem))))
1972 analysis->pItem = items;
1973
1974 /* set back to out of memory for default goto error behaviour */
1975 hr = E_OUTOFMEMORY;
1976
1977 if (dwFlags & SSA_BREAK)
1978 {
1979 if (!(analysis->logattrs = calloc(cString, sizeof(*analysis->logattrs))))
1980 goto error;
1981
1982 for (i = 0; i < analysis->numItems; ++i)
1983 ScriptBreak(&((const WCHAR *)pString)[analysis->pItem[i].iCharPos],
1984 analysis->pItem[i + 1].iCharPos - analysis->pItem[i].iCharPos,
1985 &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]);
1986 }
1987
1988 if (!(analysis->logical2visual = calloc(analysis->numItems, sizeof(*analysis->logical2visual))))
1989 goto error;
1990 if (!(BidiLevel = calloc(analysis->numItems, sizeof(*BidiLevel))))
1991 goto error;
1992
1993 if (dwFlags & SSA_GLYPHS)
1994 {
1995 int tab_x = 0;
1996
1997 if (!(analysis->glyphs = calloc(analysis->numItems, sizeof(*analysis->glyphs))))
1998 goto error;
1999
2000 for (i = 0; i < analysis->numItems; i++)
2001 {
2002 SCRIPT_CACHE *sc = (SCRIPT_CACHE*)&analysis->glyphs[i].sc;
2003 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2004 int multiplier = 2;
2005 int numGlyphs;
2006 WORD *glyphs = NULL;
2007 WORD *pwLogClust = calloc(cChar, sizeof(*pwLogClust));
2008 int *piAdvance = NULL;
2009 SCRIPT_VISATTR *psva = NULL;
2010 GOFFSET *pGoffset = NULL;
2011 int numGlyphsReturned;
2012 HFONT originalFont = 0x0;
2013
2014 /* FIXME: non unicode strings */
2015 const WCHAR* pStr = (const WCHAR*)pString;
2016 analysis->glyphs[i].fallbackFont = NULL;
2017
2018 if (!pwLogClust)
2019 {
2020 hr = E_OUTOFMEMORY;
2021 goto error;
2022 }
2023
2024 if ((dwFlags & SSA_FALLBACK) && requires_fallback(hdc, sc, &analysis->pItem[i].a, &pStr[analysis->pItem[i].iCharPos], cChar))
2025 {
2026 LOGFONTW lf;
2027 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), & lf);
2029 lf.lfFaceName[0] = 0;
2030 find_fallback_font(analysis->pItem[i].a.eScript, lf.lfFaceName);
2031 if (lf.lfFaceName[0])
2032 {
2033 analysis->glyphs[i].fallbackFont = CreateFontIndirectW(&lf);
2034 if (analysis->glyphs[i].fallbackFont)
2035 {
2036 ScriptFreeCache(sc);
2037 originalFont = SelectObject(hdc, analysis->glyphs[i].fallbackFont);
2038 }
2039 }
2040 }
2041
2042 /* FIXME: When we properly shape Hangul remove this check */
2043 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && analysis->pItem[i].a.eScript == Script_Hangul)
2044 analysis->pItem[i].a.fNoGlyphIndex = TRUE;
2045
2046 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex && !analysis->pItem[i].a.fRTL)
2047 analysis->pItem[i].a.fNoGlyphIndex = TRUE;
2048
2049 while (TRUE)
2050 {
2051 if (multiplier > 8)
2052 {
2053 hr = E_OUTOFMEMORY;
2054 break;
2055 }
2056
2057 free(glyphs);
2058 free(piAdvance);
2059 free(psva);
2060 free(pGoffset);
2061
2062 numGlyphs = multiplier * cChar + 16;
2063 glyphs = calloc(numGlyphs, sizeof(*glyphs));
2064 piAdvance = calloc(numGlyphs, sizeof(*piAdvance));
2065 psva = calloc(numGlyphs, sizeof(*psva));
2066 pGoffset = calloc(numGlyphs, sizeof(*pGoffset));
2067
2068 if (!glyphs || !piAdvance || !psva || !pGoffset)
2069 {
2070 hr = E_OUTOFMEMORY;
2071 break;
2072 }
2073
2074 hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], cChar, numGlyphs,
2075 &analysis->pItem[i].a, glyphs, pwLogClust, psva, &numGlyphsReturned);
2076 if (hr == E_OUTOFMEMORY)
2077 {
2078 multiplier *= 2;
2079 continue;
2080 }
2081
2082 hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a,
2083 piAdvance, pGoffset, &analysis->glyphs[i].abc);
2084 break;
2085 }
2086
2087 if (originalFont)
2088 SelectObject(hdc,originalFont);
2089
2090 if (FAILED(hr))
2091 {
2092 free(glyphs);
2093 free(pwLogClust);
2094 free(piAdvance);
2095 free(psva);
2096 free(pGoffset);
2097 goto error;
2098 }
2099
2100 if (dwFlags & SSA_TAB)
2101 {
2102 int tabi = 0;
2103 for (tabi = 0; tabi < cChar; tabi++)
2104 {
2105 if (pStr[analysis->pItem[i].iCharPos+tabi] == 0x0009)
2106 piAdvance[tabi] = getGivenTabWidth(analysis->glyphs[i].sc, pTabdef, analysis->pItem[i].iCharPos+tabi, tab_x);
2107 tab_x+=piAdvance[tabi];
2108 }
2109 }
2110
2111 analysis->glyphs[i].numGlyphs = numGlyphsReturned;
2112 analysis->glyphs[i].glyphs = glyphs;
2113 analysis->glyphs[i].pwLogClust = pwLogClust;
2114 analysis->glyphs[i].piAdvance = piAdvance;
2115 analysis->glyphs[i].psva = psva;
2116 analysis->glyphs[i].pGoffset = pGoffset;
2117 analysis->glyphs[i].iMaxPosX= -1;
2118
2119 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel;
2120 }
2121 }
2122 else
2123 {
2124 for (i = 0; i < analysis->numItems; i++)
2125 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel;
2126 }
2127
2128 ScriptLayout(analysis->numItems, BidiLevel, NULL, analysis->logical2visual);
2129 free(BidiLevel);
2130
2131 *pssa = analysis;
2132 free(iString);
2133 return S_OK;
2134
2135error:
2136 free(iString);
2137 free(BidiLevel);
2138 free(analysis->glyphs);
2139 free(analysis->logattrs);
2140 free(analysis->pItem);
2141 free(analysis->logical2visual);
2142 free(analysis);
2143 return hr;
2144}
2145
2146static inline BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction)
2147{
2148 if (pva[glyph].fClusterStart)
2149 return TRUE;
2150 if (USP10_FindGlyphInLogClust(pwLogClust, cChars, glyph) >= 0)
2151 return TRUE;
2152
2153 return FALSE;
2154}
2155
2157 int iX,
2158 int iY,
2159 int iItem,
2160 int cStart,
2161 int cEnd,
2162 UINT uOptions,
2163 const RECT *prc,
2164 BOOL fSelected,
2165 BOOL fDisabled)
2166{
2167 StringAnalysis *analysis;
2168 int off_x = 0;
2169 HRESULT hr;
2170 COLORREF BkColor = 0x0;
2171 COLORREF TextColor = 0x0;
2172 INT BkMode = 0;
2173 INT runStart, runEnd;
2174 INT iGlyph, cGlyphs;
2175 HFONT oldFont = 0x0;
2176 RECT crc;
2177 int i;
2178
2179 TRACE("(%p,%d,%d,%d,%d,%d, 0x%1x, %d, %d)\n",
2180 ssa, iX, iY, iItem, cStart, cEnd, uOptions, fSelected, fDisabled);
2181
2182 if (!(analysis = ssa)) return E_INVALIDARG;
2183
2184 if ((cStart >= 0 && analysis->pItem[iItem+1].iCharPos <= cStart) ||
2185 (cEnd >= 0 && analysis->pItem[iItem].iCharPos >= cEnd))
2186 return S_OK;
2187
2188 if (prc)
2189 memcpy(&crc, prc, sizeof(crc));
2190 if (fSelected)
2191 {
2192 BkMode = GetBkMode(analysis->hdc);
2193 SetBkMode( analysis->hdc, OPAQUE);
2194 BkColor = GetBkColor(analysis->hdc);
2196 if (!fDisabled)
2197 {
2198 TextColor = GetTextColor(analysis->hdc);
2200 }
2201 }
2202 if (analysis->glyphs[iItem].fallbackFont)
2203 oldFont = SelectObject(analysis->hdc, analysis->glyphs[iItem].fallbackFont);
2204
2205 if (cStart >= 0 && analysis->pItem[iItem+1].iCharPos > cStart && analysis->pItem[iItem].iCharPos <= cStart)
2206 runStart = cStart - analysis->pItem[iItem].iCharPos;
2207 else
2208 runStart = 0;
2209 if (cEnd >= 0 && analysis->pItem[iItem+1].iCharPos > cEnd && analysis->pItem[iItem].iCharPos <= cEnd)
2210 runEnd = (cEnd-1) - analysis->pItem[iItem].iCharPos;
2211 else
2212 runEnd = (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos) - 1;
2213
2214 if (analysis->pItem[iItem].a.fRTL)
2215 {
2216 if (cEnd >= 0 && cEnd < analysis->pItem[iItem+1].iCharPos)
2217 ScriptStringCPtoX(ssa, cEnd, FALSE, &off_x);
2218 else
2219 ScriptStringCPtoX(ssa, analysis->pItem[iItem+1].iCharPos-1, TRUE, &off_x);
2220 crc.left = iX + off_x;
2221 }
2222 else
2223 {
2224 if (cStart >=0 && runStart)
2225 ScriptStringCPtoX(ssa, cStart, FALSE, &off_x);
2226 else
2227 ScriptStringCPtoX(ssa, analysis->pItem[iItem].iCharPos, FALSE, &off_x);
2228 crc.left = iX + off_x;
2229 }
2230
2231 if (analysis->pItem[iItem].a.fRTL)
2232 iGlyph = analysis->glyphs[iItem].pwLogClust[runEnd];
2233 else
2234 iGlyph = analysis->glyphs[iItem].pwLogClust[runStart];
2235
2236 if (analysis->pItem[iItem].a.fRTL)
2237 cGlyphs = analysis->glyphs[iItem].pwLogClust[runStart] - iGlyph;
2238 else
2239 cGlyphs = analysis->glyphs[iItem].pwLogClust[runEnd] - iGlyph;
2240
2241 cGlyphs++;
2242
2243 /* adjust for cluster glyphs when starting */
2244 if (analysis->pItem[iItem].a.fRTL)
2245 i = analysis->pItem[iItem+1].iCharPos - 1;
2246 else
2247 i = analysis->pItem[iItem].iCharPos;
2248
2249 for (; i >=analysis->pItem[iItem].iCharPos && i < analysis->pItem[iItem+1].iCharPos; (analysis->pItem[iItem].a.fRTL)?i--:i++)
2250 {
2251 if (analysis->glyphs[iItem].pwLogClust[i - analysis->pItem[iItem].iCharPos] == iGlyph)
2252 {
2253 if (analysis->pItem[iItem].a.fRTL)
2254 ScriptStringCPtoX(ssa, i, TRUE, &off_x);
2255 else
2256 ScriptStringCPtoX(ssa, i, FALSE, &off_x);
2257 break;
2258 }
2259 }
2260
2261 if (cEnd < 0 || scriptInformation[analysis->pItem[iItem].a.eScript].props.fNeedsCaretInfo)
2262 {
2263 INT direction;
2264 INT clust_glyph;
2265
2266 clust_glyph = iGlyph + cGlyphs;
2267 if (analysis->pItem[iItem].a.fRTL)
2268 direction = -1;
2269 else
2270 direction = 1;
2271
2272 while(clust_glyph < analysis->glyphs[iItem].numGlyphs &&
2273 !does_glyph_start_cluster(analysis->glyphs[iItem].psva, analysis->glyphs[iItem].pwLogClust, (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos), clust_glyph, direction))
2274 {
2275 cGlyphs++;
2276 clust_glyph++;
2277 }
2278 }
2279
2280 hr = ScriptTextOut(analysis->hdc,
2281 (SCRIPT_CACHE *)&analysis->glyphs[iItem].sc, iX + off_x,
2282 iY, uOptions, &crc, &analysis->pItem[iItem].a, NULL, 0,
2283 &analysis->glyphs[iItem].glyphs[iGlyph], cGlyphs,
2284 &analysis->glyphs[iItem].piAdvance[iGlyph], NULL,
2285 &analysis->glyphs[iItem].pGoffset[iGlyph]);
2286
2287 TRACE("ScriptTextOut hr=%08lx\n", hr);
2288
2289 if (fSelected)
2290 {
2291 SetBkColor(analysis->hdc, BkColor);
2292 SetBkMode( analysis->hdc, BkMode);
2293 if (!fDisabled)
2294 SetTextColor(analysis->hdc, TextColor);
2295 }
2296 if (analysis->glyphs[iItem].fallbackFont)
2297 SelectObject(analysis->hdc, oldFont);
2298
2299 return hr;
2300}
2301
2302/***********************************************************************
2303 * ScriptStringOut (USP10.@)
2304 *
2305 * This function takes the output of ScriptStringAnalyse and joins the segments
2306 * of glyphs and passes the resulting string to ScriptTextOut. ScriptStringOut
2307 * only processes glyphs.
2308 *
2309 * Parameters:
2310 * ssa [I] buffer to hold the analysed string components
2311 * iX [I] X axis displacement for output
2312 * iY [I] Y axis displacement for output
2313 * uOptions [I] flags controlling output processing
2314 * prc [I] rectangle coordinates
2315 * iMinSel [I] starting pos for substringing output string
2316 * iMaxSel [I] ending pos for substringing output string
2317 * fDisabled [I] controls text highlighting
2318 *
2319 * RETURNS
2320 * Success: S_OK
2321 * Failure: is the value returned by ScriptTextOut
2322 */
2324 int iX,
2325 int iY,
2326 UINT uOptions,
2327 const RECT *prc,
2328 int iMinSel,
2329 int iMaxSel,
2330 BOOL fDisabled)
2331{
2332 StringAnalysis *analysis;
2333 int item;
2334 HRESULT hr;
2335
2336 TRACE("(%p,%d,%d,0x%08x,%s,%d,%d,%d)\n",
2337 ssa, iX, iY, uOptions, wine_dbgstr_rect(prc), iMinSel, iMaxSel, fDisabled);
2338
2339 if (!(analysis = ssa)) return E_INVALIDARG;
2340 if (!(analysis->ssa_flags & SSA_GLYPHS)) return E_INVALIDARG;
2341
2342 for (item = 0; item < analysis->numItems; item++)
2343 {
2344 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], -1, -1, uOptions, prc, FALSE, fDisabled);
2345 if (FAILED(hr))
2346 return hr;
2347 }
2348
2349 if (iMinSel < iMaxSel && (iMinSel > 0 || iMaxSel > 0))
2350 {
2351 if (iMaxSel > 0 && iMinSel < 0)
2352 iMinSel = 0;
2353 for (item = 0; item < analysis->numItems; item++)
2354 {
2355 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], iMinSel, iMaxSel, uOptions, prc, TRUE, fDisabled);
2356 if (FAILED(hr))
2357 return hr;
2358 }
2359 }
2360
2361 return S_OK;
2362}
2363
2364/***********************************************************************
2365 * ScriptStringCPtoX (USP10.@)
2366 *
2367 */
2369{
2370 int item;
2371 int runningX = 0;
2372 StringAnalysis* analysis = ssa;
2373
2374 TRACE("(%p), %d, %d, (%p)\n", ssa, icp, fTrailing, pX);
2375
2376 if (!ssa || !pX) return S_FALSE;
2377 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
2378
2379 /* icp out of range */
2380 if(icp < 0)
2381 {
2383 return E_INVALIDARG;
2384 }
2385
2386 for(item=0; item<analysis->numItems; item++)
2387 {
2388 int CP, i;
2389 int offset;
2390
2391 i = analysis->logical2visual[item];
2392 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2393 /* initialize max extents for uninitialized runs */
2394 if (analysis->glyphs[i].iMaxPosX == -1)
2395 {
2396 if (analysis->pItem[i].a.fRTL)
2397 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2398 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2399 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2400 else
2401 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2402 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2403 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2404 }
2405
2406 if (icp >= analysis->pItem[i+1].iCharPos || icp < analysis->pItem[i].iCharPos)
2407 {
2408 runningX += analysis->glyphs[i].iMaxPosX;
2409 continue;
2410 }
2411
2412 icp -= analysis->pItem[i].iCharPos;
2413 ScriptCPtoX(icp, fTrailing, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2414 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2415 &analysis->pItem[i].a, &offset);
2416 runningX += offset;
2417
2418 *pX = runningX;
2419 return S_OK;
2420 }
2421
2422 /* icp out of range */
2424 return E_INVALIDARG;
2425}
2426
2427/***********************************************************************
2428 * ScriptStringXtoCP (USP10.@)
2429 *
2430 */
2431HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing)
2432{
2433 StringAnalysis* analysis = ssa;
2434 int item;
2435
2436 TRACE("(%p), %d, (%p), (%p)\n", ssa, iX, piCh, piTrailing);
2437
2438 if (!ssa || !piCh || !piTrailing) return S_FALSE;
2439 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
2440
2441 /* out of range */
2442 if(iX < 0)
2443 {
2444 if (analysis->pItem[0].a.fRTL)
2445 {
2446 *piCh = 1;
2447 *piTrailing = FALSE;
2448 }
2449 else
2450 {
2451 *piCh = -1;
2452 *piTrailing = TRUE;
2453 }
2454 return S_OK;
2455 }
2456
2457 for(item=0; item<analysis->numItems; item++)
2458 {
2459 int i;
2460 int CP;
2461
2462 for (i = 0; i < analysis->numItems && analysis->logical2visual[i] != item; i++)
2463 /* nothing */;
2464
2465 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
2466 /* initialize max extents for uninitialized runs */
2467 if (analysis->glyphs[i].iMaxPosX == -1)
2468 {
2469 if (analysis->pItem[i].a.fRTL)
2470 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2471 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2472 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2473 else
2474 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2475 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2476 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX);
2477 }
2478
2479 if (iX > analysis->glyphs[i].iMaxPosX)
2480 {
2481 iX -= analysis->glyphs[i].iMaxPosX;
2482 continue;
2483 }
2484
2485 ScriptXtoCP(iX, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust,
2486 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance,
2487 &analysis->pItem[i].a, piCh, piTrailing);
2488 *piCh += analysis->pItem[i].iCharPos;
2489
2490 return S_OK;
2491 }
2492
2493 /* out of range */
2494 *piCh = analysis->pItem[analysis->numItems].iCharPos;
2495 *piTrailing = FALSE;
2496
2497 return S_OK;
2498}
2499
2500
2501/***********************************************************************
2502 * ScriptStringFree (USP10.@)
2503 *
2504 * Free a string analysis.
2505 *
2506 * PARAMS
2507 * pssa [I] string analysis.
2508 *
2509 * RETURNS
2510 * Success: S_OK
2511 * Failure: Non-zero HRESULT value.
2512 */
2514{
2515 StringAnalysis* analysis;
2516 BOOL invalid;
2517 int i;
2518
2519 TRACE("(%p)\n", pssa);
2520
2521 if (!pssa || !(analysis = *pssa)) return E_INVALIDARG;
2522
2523 invalid = analysis->flags & SCRIPT_STRING_ANALYSIS_FLAGS_INVALID;
2524
2525 if (analysis->glyphs)
2526 {
2527 for (i = 0; i < analysis->numItems; i++)
2528 {
2529 free(analysis->glyphs[i].glyphs);
2530 free(analysis->glyphs[i].pwLogClust);
2531 free(analysis->glyphs[i].piAdvance);
2532 free(analysis->glyphs[i].psva);
2533 free(analysis->glyphs[i].pGoffset);
2534 if (analysis->glyphs[i].fallbackFont)
2535 DeleteObject(analysis->glyphs[i].fallbackFont);
2536 ScriptFreeCache((SCRIPT_CACHE *)&analysis->glyphs[i].sc);
2537 }
2538 free(analysis->glyphs);
2539 }
2540
2541 free(analysis->pItem);
2542 free(analysis->logattrs);
2543 free(analysis->logical2visual);
2544 free(analysis);
2545
2546 if (invalid) return E_INVALIDARG;
2547 return S_OK;
2548}
2549
2550static inline int get_cluster_size(const WORD *pwLogClust, int cChars, int item,
2551 int direction, int* iCluster, int *check_out)
2552{
2553 int clust_size = 1;
2554 int check;
2555 WORD clust = pwLogClust[item];
2556
2557 for (check = item+direction; check < cChars && check >= 0; check+=direction)
2558 {
2559 if (pwLogClust[check] == clust)
2560 {
2561 clust_size ++;
2562 if (iCluster && *iCluster == -1)
2563 *iCluster = item;
2564 }
2565 else break;
2566 }
2567
2568 if (check_out)
2569 *check_out = check;
2570
2571 return clust_size;
2572}
2573
2574static inline int get_glyph_cluster_advance(const int* piAdvance, const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cGlyphs, int cChars, int glyph, int direction)
2575{
2576 int advance;
2577 int log_clust_max;
2578
2579 advance = piAdvance[glyph];
2580
2581 if (pwLogClust[0] > pwLogClust[cChars-1])
2582 log_clust_max = pwLogClust[0];
2583 else
2584 log_clust_max = pwLogClust[cChars-1];
2585
2586 if (glyph > log_clust_max)
2587 return advance;
2588
2589 for (glyph+=direction; glyph < cGlyphs && glyph >= 0; glyph +=direction)
2590 {
2591
2592 if (does_glyph_start_cluster(pva, pwLogClust, cChars, glyph, direction))
2593 break;
2594 if (glyph > log_clust_max)
2595 break;
2596 advance += piAdvance[glyph];
2597 }
2598
2599 return advance;
2600}
2601
2602/***********************************************************************
2603 * ScriptCPtoX (USP10.@)
2604 *
2605 */
2607 BOOL fTrailing,
2608 int cChars,
2609 int cGlyphs,
2610 const WORD *pwLogClust,
2611 const SCRIPT_VISATTR *psva,
2612 const int *piAdvance,
2613 const SCRIPT_ANALYSIS *psa,
2614 int *piX)
2615{
2616 int item;
2617 float iPosX;
2618 int iSpecial = -1;
2619 int iCluster = -1;
2620 int clust_size = 1;
2621 float special_size = 0.0;
2622 int iMaxPos = 0;
2623 int advance = 0;
2624 BOOL rtl = FALSE;
2625
2626 TRACE("(%d,%d,%d,%d,%p,%p,%p,%p,%p)\n",
2627 iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance,
2628 psa, piX);
2629
2630 if (psa->fRTL && ! psa->fLogicalOrder)
2631 rtl = TRUE;
2632
2633 if (fTrailing)
2634 iCP++;
2635
2636 if (rtl)
2637 {
2638 int max_clust = pwLogClust[0];
2639
2640 for (item=0; item < cGlyphs; item++)
2641 if (pwLogClust[item] > max_clust)
2642 {
2643 ERR("We do not handle non reversed clusters properly\n");
2644 break;
2645 }
2646
2647 iMaxPos = 0;
2648 for (item = max_clust; item >=0; item --)
2649 iMaxPos += piAdvance[item];
2650 }
2651
2652 iPosX = 0.0;
2653 for (item=0; item < iCP && item < cChars; item++)
2654 {
2655 if (iSpecial == -1 && (iCluster == -1 || iCluster+clust_size <= item))
2656 {
2657 int check;
2658 int clust = pwLogClust[item];
2659
2660 iCluster = -1;
2661 clust_size = get_cluster_size(pwLogClust, cChars, item, 1, &iCluster,
2662 &check);
2663
2664 advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, 1);
2665
2666 if (check >= cChars && !iMaxPos)
2667 {
2668 int glyph;
2669 for (glyph = clust; glyph < cGlyphs; glyph++)
2670 special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, glyph, 1);
2671 iSpecial = item;
2672 special_size /= (cChars - item);
2673 iPosX += special_size;
2674 }
2675 else
2676 {
2678 {
2679 clust_size --;
2680 if (clust_size == 0)
2681 iPosX += advance;
2682 }
2683 else
2684 iPosX += advance / (float)clust_size;
2685 }
2686 }
2687 else if (iSpecial != -1)
2688 iPosX += special_size;
2689 else /* (iCluster != -1) */
2690 {
2691 int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], 1);
2693 {
2694 clust_size --;
2695 if (clust_size == 0)
2696 iPosX += adv;
2697 }
2698 else
2699 iPosX += adv / (float)clust_size;
2700 }
2701 }
2702
2703 if (iMaxPos > 0)
2704 {
2705 iPosX = iMaxPos - iPosX;
2706 if (iPosX < 0)
2707 iPosX = 0;
2708 }
2709
2710 *piX = iPosX;
2711 TRACE("*piX=%d\n", *piX);
2712 return S_OK;
2713}
2714
2715/* Count the number of characters in a cluster and its starting index*/
2716static inline BOOL get_cluster_data(const WORD *pwLogClust, int cChars, int cluster_index, int *cluster_size, int *start_index)
2717{
2718 int size = 0;
2719 int i;
2720
2721 for (i = 0; i < cChars; i++)
2722 {
2723 if (pwLogClust[i] == cluster_index)
2724 {
2725 if (!size && start_index)
2726 {
2727 *start_index = i;
2728 if (!cluster_size)
2729 return TRUE;
2730 }
2731 size++;
2732 }
2733 else if (size) break;
2734 }
2735 if (cluster_size)
2736 *cluster_size = size;
2737
2738 return (size > 0);
2739}
2740
2741/*
2742 To handle multi-glyph clusters we need to find all the glyphs that are
2743 represented in the cluster. This involves finding the glyph whose
2744 index is the cluster index as well as whose glyph indices are greater than
2745 our cluster index but not part of a new cluster.
2746
2747 Then we sum all those glyphs' advances.
2748*/
2749static inline int get_cluster_advance(const int* piAdvance,
2750 const SCRIPT_VISATTR *psva,
2751 const WORD *pwLogClust, int cGlyphs,
2752 int cChars, int cluster, int direction)
2753{
2754 int glyph_start;
2755 int glyph_end;
2756 int i, advance;
2757
2758 if (direction > 0)
2759 i = 0;
2760 else
2761 i = (cChars - 1);
2762
2763 for (glyph_start = -1, glyph_end = -1; i < cChars && i >= 0 && (glyph_start < 0 || glyph_end < 0); i+=direction)
2764 {
2765 if (glyph_start < 0 && pwLogClust[i] != cluster) continue;
2766 if (pwLogClust[i] == cluster && glyph_start < 0) glyph_start = pwLogClust[i];
2767 if (glyph_start >= 0 && glyph_end < 0 && pwLogClust[i] != cluster) glyph_end = pwLogClust[i];
2768 }
2769 if (glyph_end < 0)
2770 {
2771 if (direction > 0)
2772 glyph_end = cGlyphs;
2773 else
2774 {
2775 /* Don't fully understand multi-glyph reversed clusters yet,
2776 * do they occur for real or just in our test? */
2777 FIXME("multi-glyph reversed clusters found\n");
2778 glyph_end = glyph_start + 1;
2779 }
2780 }
2781
2782 /* Check for fClusterStart, finding this generally would mean a malformed set of data */
2783 for (i = glyph_start+1; i< glyph_end; i++)
2784 {
2785 if (psva[i].fClusterStart)
2786 {
2787 glyph_end = i;
2788 break;
2789 }
2790 }
2791
2792 for (advance = 0, i = glyph_start; i < glyph_end; i++)
2793 advance += piAdvance[i];
2794
2795 return advance;
2796}
2797
2798
2799/***********************************************************************
2800 * ScriptXtoCP (USP10.@)
2801 *
2802 * Basic algorithm :
2803 * Use piAdvance to find the cluster we are looking at.
2804 * Find the character that is the first character of the cluster.
2805 * That is our base piCP.
2806 * If the script snaps to cluster boundaries (Hebrew, Indic, Thai) then we
2807 * are good. Otherwise if the cluster is larger than 1 glyph we need to
2808 * determine how far through the cluster to advance the cursor.
2809 */
2811 int cChars,
2812 int cGlyphs,
2813 const WORD *pwLogClust,
2814 const SCRIPT_VISATTR *psva,
2815 const int *piAdvance,
2816 const SCRIPT_ANALYSIS *psa,
2817 int *piCP,
2818 int *piTrailing)
2819{
2820 int direction = 1;
2821 int iPosX;
2822 int i;
2823 int glyph_index, cluster_index;
2824 int cluster_size;
2825
2826 TRACE("(%d,%d,%d,%p,%p,%p,%p,%p,%p)\n",
2827 iX, cChars, cGlyphs, pwLogClust, psva, piAdvance,
2828 psa, piCP, piTrailing);
2829
2830 if (psa->fRTL && ! psa->fLogicalOrder)
2831 direction = -1;
2832
2833 /* Handle an iX < 0 */
2834 if (iX < 0)
2835 {
2836 if (direction < 0)
2837 {
2838 *piCP = cChars;
2839 *piTrailing = 0;
2840 }
2841 else
2842 {
2843 *piCP = -1;
2844 *piTrailing = 1;
2845 }
2846 return S_OK;
2847 }
2848
2849 /* Looking for non-reversed clusters in a reversed string */
2850 if (direction < 0)
2851 {
2852 int max_clust = pwLogClust[0];
2853 for (i=0; i< cChars; i++)
2854 if (pwLogClust[i] > max_clust)
2855 {
2856 FIXME("We do not handle non reversed clusters properly\n");
2857 break;
2858 }
2859 }
2860
2861 /* find the glyph_index based in iX */
2862 if (direction > 0)
2863 {
2864 for (glyph_index = -1, iPosX = iX; iPosX >=0 && glyph_index < cGlyphs; iPosX -= piAdvance[glyph_index+1], glyph_index++)
2865 ;
2866 }
2867 else
2868 {
2869 for (glyph_index = -1, iPosX = iX; iPosX > 0 && glyph_index < cGlyphs; iPosX -= piAdvance[glyph_index+1], glyph_index++)
2870 ;
2871 }
2872
2873 TRACE("iPosX %i -> glyph_index %i (%i)\n", iPosX, glyph_index, cGlyphs);
2874
2875 *piTrailing = 0;
2876 if (glyph_index >= 0 && glyph_index < cGlyphs)
2877 {
2878 /* find the cluster */
2879 if (direction > 0 )
2880 for (i = 0, cluster_index = pwLogClust[0]; i < cChars && pwLogClust[i] <= glyph_index; cluster_index=pwLogClust[i++])
2881 ;
2882 else
2883 for (i = 0, cluster_index = pwLogClust[0]; i < cChars && pwLogClust[i] >= glyph_index; cluster_index=pwLogClust[i++])
2884 ;
2885
2886 TRACE("cluster_index %i\n", cluster_index);
2887
2888 if (direction < 0 && iPosX >= 0 && glyph_index != cluster_index)
2889 {
2890 /* We are off the end of the string */
2891 *piCP = -1;
2892 *piTrailing = 1;
2893 return S_OK;
2894 }
2895
2896 get_cluster_data(pwLogClust, cChars, cluster_index, &cluster_size, &i);
2897
2898 TRACE("first char index %i\n",i);
2900 {
2901 /* Check trailing */
2902 if (glyph_index != cluster_index ||
2903 (direction > 0 && abs(iPosX) <= (piAdvance[glyph_index] / 2)) ||
2904 (direction < 0 && abs(iPosX) >= (piAdvance[glyph_index] / 2)))
2905 *piTrailing = cluster_size;
2906 }
2907 else
2908 {
2909 if (cluster_size > 1)
2910 {
2911 /* Be part way through the glyph cluster based on size and position */
2912 int cluster_advance = get_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, cluster_index, direction);
2913 double cluster_part_width = cluster_advance / (float)cluster_size;
2914 double adv;
2915 int part_index;
2916
2917 /* back up to the beginning of the cluster */
2918 for (adv = iPosX, part_index = cluster_index; part_index <= glyph_index; part_index++)
2919 adv += piAdvance[part_index];
2920 if (adv > iX) adv = iX;
2921
2922 TRACE("Multi-char cluster, no snap\n");
2923 TRACE("cluster size %i, pre-cluster iPosX %f\n",cluster_size, adv);
2924 TRACE("advance %i divides into %f per char\n", cluster_advance, cluster_part_width);
2925 if (direction > 0)
2926 {
2927 for (part_index = 0; adv >= 0; adv-=cluster_part_width, part_index++)
2928 ;
2929 if (part_index) part_index--;
2930 }
2931 else
2932 {
2933 for (part_index = 0; adv > 0; adv-=cluster_part_width, part_index++)
2934 ;
2935 if (part_index > cluster_size)
2936 {
2937 adv += cluster_part_width;
2938 part_index=cluster_size;
2939 }
2940 }
2941
2942 TRACE("base_char %i part_index %i, leftover advance %f\n",i, part_index, adv);
2943
2944 if (direction > 0)
2945 i += part_index;
2946 else
2947 i += (cluster_size - part_index);
2948
2949 /* Check trailing */
2950 if ((direction > 0 && fabs(adv) <= (cluster_part_width / 2.0)) ||
2951 (direction < 0 && adv && fabs(adv) >= (cluster_part_width / 2.0)))
2952 *piTrailing = 1;
2953 }
2954 else
2955 {
2956 /* Check trailing */
2957 if ((direction > 0 && abs(iPosX) <= (piAdvance[glyph_index] / 2)) ||
2958 (direction < 0 && abs(iPosX) >= (piAdvance[glyph_index] / 2)))
2959 *piTrailing = 1;
2960 }
2961 }
2962 }
2963 else
2964 {
2965 TRACE("Point falls outside of string\n");
2966 if (glyph_index < 0)
2967 i = cChars-1;
2968 else /* (glyph_index >= cGlyphs) */
2969 i = cChars;
2970
2971 /* If not snapping in the reverse direction (such as Hebrew) Then 0
2972 point flow to the next character */
2973 if (direction < 0)
2974 {
2975 if (!scriptInformation[psa->eScript].props.fNeedsCaretInfo && abs(iPosX) == piAdvance[glyph_index])
2976 i++;
2977 else
2978 *piTrailing = 1;
2979 }
2980 }
2981
2982 *piCP = i;
2983
2984 TRACE("*piCP=%d\n", *piCP);
2985 TRACE("*piTrailing=%d\n", *piTrailing);
2986 return S_OK;
2987}
2988
2989/***********************************************************************
2990 * ScriptBreak (USP10.@)
2991 *
2992 * Retrieve line break information.
2993 *
2994 * PARAMS
2995 * chars [I] Array of characters.
2996 * sa [I] Script analysis.
2997 * la [I] Array of logical attribute structures.
2998 *
2999 * RETURNS
3000 * Success: S_OK
3001 * Failure: S_FALSE
3002 */
3004{
3005 TRACE("(%s, %d, %p, %p)\n", debugstr_wn(chars, count), count, sa, la);
3006
3007 if (count < 0 || !la) return E_INVALIDARG;
3008 if (count == 0) return E_FAIL;
3009
3010 BREAK_line(chars, count, sa, la);
3011
3012 return S_OK;
3013}
3014
3015/***********************************************************************
3016 * ScriptIsComplex (USP10.@)
3017 *
3018 * Determine if a string is complex.
3019 *
3020 * PARAMS
3021 * chars [I] Array of characters to test.
3022 * len [I] Length in characters.
3023 * flag [I] Flag.
3024 *
3025 * RETURNS
3026 * Success: S_OK
3027 * Failure: S_FALSE
3028 *
3029 */
3031{
3032 enum usp10_script script;
3033 unsigned int i, consumed;
3034
3035 TRACE("(%s,%d,0x%lx)\n", debugstr_wn(chars, len), len, flag);
3036
3037 if (!chars || len < 0)
3038 return E_INVALIDARG;
3039
3040 for (i = 0; i < len; i+=consumed)
3041 {
3042 if ((flag & SIC_ASCIIDIGIT) && chars[i] >= 0x30 && chars[i] <= 0x39)
3043 return S_OK;
3044
3045 script = get_char_script(chars,i,len, &consumed);
3046 if ((scriptInformation[script].props.fComplex && (flag & SIC_COMPLEX))||
3048 return S_OK;
3049 }
3050 return S_FALSE;
3051}
3052
3053/***********************************************************************
3054 * ScriptShapeOpenType (USP10.@)
3055 *
3056 * Produce glyphs and visual attributes for a run.
3057 *
3058 * PARAMS
3059 * hdc [I] Device context.
3060 * psc [I/O] Opaque pointer to a script cache.
3061 * psa [I/O] Script analysis.
3062 * tagScript [I] The OpenType tag for the Script
3063 * tagLangSys [I] The OpenType tag for the Language
3064 * rcRangeChars[I] Array of Character counts in each range
3065 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures
3066 * cRanges [I] Count of ranges
3067 * pwcChars [I] Array of characters specifying the run.
3068 * cChars [I] Number of characters in pwcChars.
3069 * cMaxGlyphs [I] Length of pwOutGlyphs.
3070 * pwLogClust [O] Array of logical cluster info.
3071 * pCharProps [O] Array of character property values
3072 * pwOutGlyphs [O] Array of glyphs.
3073 * pOutGlyphProps [O] Array of attributes for the retrieved glyphs
3074 * pcGlyphs [O] Number of glyphs returned.
3075 *
3076 * RETURNS
3077 * Success: S_OK
3078 * Failure: Non-zero HRESULT value.
3079 */
3081 SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript,
3082 OPENTYPE_TAG tagLangSys, int *rcRangeChars,
3083 TEXTRANGE_PROPERTIES **rpRangeProperties,
3084 int cRanges, const WCHAR *pwcChars, int cChars,
3085 int cMaxGlyphs, WORD *pwLogClust,
3086 SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs,
3087 SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs)
3088{
3089 HRESULT hr;
3090 int i;
3091 unsigned int g;
3092 BOOL rtl;
3093 int cluster;
3094 static int once = 0;
3095
3096 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %d, %d, %p, %p, %p, %p, %p )\n",
3097 hdc, psc, psa,
3098 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4),
3099 rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars),
3100 cChars, cMaxGlyphs, pwLogClust, pCharProps, pwOutGlyphs, pOutGlyphProps, pcGlyphs);
3101
3102 if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL,
3103 psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder, psa->fNoGlyphIndex);
3104
3105 if (!pOutGlyphProps || !pcGlyphs || !pCharProps) return E_INVALIDARG;
3106 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
3107
3108 if (cRanges)
3109 if(!once++) FIXME("Ranges not supported yet\n");
3110
3111 rtl = (psa && !psa->fLogicalOrder && psa->fRTL);
3112
3113 *pcGlyphs = cChars;
3114 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3115 if (!pwLogClust) return E_FAIL;
3116
3117 ((ScriptCache *)*psc)->userScript = tagScript;
3118 ((ScriptCache *)*psc)->userLang = tagLangSys;
3119
3120 /* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */
3121 for (i = 0; i < cChars; i++)
3122 {
3123 int idx = i;
3124 if (rtl) idx = cChars - 1 - i;
3125 /* FIXME: set to better values */
3126 pOutGlyphProps[i].sva.uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
3127 pOutGlyphProps[i].sva.fClusterStart = 1;
3128 pOutGlyphProps[i].sva.fDiacritic = 0;
3129 pOutGlyphProps[i].sva.fZeroWidth = 0;
3130 pOutGlyphProps[i].sva.fReserved = 0;
3131 pOutGlyphProps[i].sva.fShapeReserved = 0;
3132
3133 /* FIXME: have the shaping engine set this */
3134 pCharProps[i].fCanGlyphAlone = 0;
3135
3136 pwLogClust[i] = idx;
3137 }
3138
3139 if (psa && !psa->fNoGlyphIndex && ((ScriptCache *)*psc)->sfnt)
3140 {
3141 WCHAR *rChars;
3142 if ((hr = SHAPE_CheckFontForRequiredFeatures(hdc, (ScriptCache *)*psc, psa)) != S_OK) return hr;
3143
3144 if (!(rChars = calloc(cChars, sizeof(*rChars))))
3145 return E_OUTOFMEMORY;
3146
3147 for (i = 0, g = 0, cluster = 0; i < cChars; i++)
3148 {
3149 int idx = i;
3150 DWORD chInput;
3151
3152 if (rtl) idx = cChars - 1 - i;
3153 if (!cluster)
3154 {
3155 chInput = decode_surrogate_pair(pwcChars, idx, cChars);
3156 if (!chInput)
3157 {
3158 if (psa->fRTL)
3159 chInput = mirror_char(pwcChars[idx]);
3160 else
3161 chInput = pwcChars[idx];
3162 rChars[i] = chInput;
3163 }
3164 else
3165 {
3166 rChars[i] = pwcChars[idx];
3167 rChars[i+1] = pwcChars[(rtl)?idx-1:idx+1];
3168 cluster = 1;
3169 }
3170 if (!(pwOutGlyphs[g] = get_cache_glyph(psc, chInput)))
3171 {
3172 WORD glyph;
3173 if (!hdc)
3174 {
3175 free(rChars);
3176 return E_PENDING;
3177 }
3178 if (OpenType_CMAP_GetGlyphIndex(hdc, (ScriptCache *)*psc, chInput, &glyph, 0) == GDI_ERROR)
3179 {
3180 free(rChars);
3181 return S_FALSE;
3182 }
3183 pwOutGlyphs[g] = set_cache_glyph(psc, chInput, glyph);
3184 }
3185 g++;
3186 }
3187 else
3188 {
3189 int k;
3190 cluster--;
3191 pwLogClust[idx] = (rtl)?pwLogClust[idx+1]:pwLogClust[idx-1];
3192 for (k = (rtl)?idx-1:idx+1; k >= 0 && k < cChars; (rtl)?k--:k++)
3193 pwLogClust[k]--;
3194 }
3195 }
3196 *pcGlyphs = g;
3197
3198 hr = SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust);
3199 if (FAILED(hr))
3200 {
3201 free(rChars);
3202 return hr;
3203 }
3204 SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust);
3205 SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs, *pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps);
3206
3207 for (i = 0; i < cChars; ++i)
3208 {
3209 /* Special case for tabs and joiners. As control characters, ZWNJ
3210 * and ZWJ would in principle get handled by the corresponding
3211 * shaping functions. However, since ZWNJ and ZWJ can get merged
3212 * into adjoining runs during itemisation, these don't generally
3213 * get classified as Script_Control. */
3214 if (pwcChars[i] == 0x0009 || pwcChars[i] == ZWSP || pwcChars[i] == ZWNJ || pwcChars[i] == ZWJ)
3215 {
3216 pwOutGlyphs[pwLogClust[i]] = ((ScriptCache *)*psc)->sfp.wgBlank;
3217 pOutGlyphProps[pwLogClust[i]].sva.fZeroWidth = 1;
3218 }
3219 }
3220 free(rChars);
3221 }
3222 else
3223 {
3224 TRACE("no glyph translation\n");
3225 for (i = 0; i < cChars; i++)
3226 {
3227 int idx = i;
3228 /* No mirroring done here */
3229 if (rtl) idx = cChars - 1 - i;
3230 pwOutGlyphs[i] = pwcChars[idx];
3231
3232 if (!psa)
3233 continue;
3234
3235 /* overwrite some basic control glyphs to blank */
3236 if (psa->fNoGlyphIndex)
3237 {
3238 if (pwcChars[idx] == ZWSP || pwcChars[idx] == ZWNJ || pwcChars[idx] == ZWJ)
3239 {
3240 pwOutGlyphs[i] = 0x20;
3241 pOutGlyphProps[i].sva.fZeroWidth = 1;
3242 }
3243 }
3244 else if (psa->eScript == Script_Control || pwcChars[idx] == ZWSP
3245 || pwcChars[idx] == ZWNJ || pwcChars[idx] == ZWJ)
3246 {
3247 if (pwcChars[idx] == 0x0009 || pwcChars[idx] == 0x000A ||
3248 pwcChars[idx] == 0x000D || pwcChars[idx] >= 0x001C)
3249 {
3250 pwOutGlyphs[i] = ((ScriptCache *)*psc)->sfp.wgBlank;
3251 pOutGlyphProps[i].sva.fZeroWidth = 1;
3252 }
3253 }
3254 }
3255 }
3256
3257 return S_OK;
3258}
3259
3260
3261/***********************************************************************
3262 * ScriptShape (USP10.@)
3263 *
3264 * Produce glyphs and visual attributes for a run.
3265 *
3266 * PARAMS
3267 * hdc [I] Device context.
3268 * psc [I/O] Opaque pointer to a script cache.
3269 * pwcChars [I] Array of characters specifying the run.
3270 * cChars [I] Number of characters in pwcChars.
3271 * cMaxGlyphs [I] Length of pwOutGlyphs.
3272 * psa [I/O] Script analysis.
3273 * pwOutGlyphs [O] Array of glyphs.
3274 * pwLogClust [O] Array of logical cluster info.
3275 * psva [O] Array of visual attributes.
3276 * pcGlyphs [O] Number of glyphs returned.
3277 *
3278 * RETURNS
3279 * Success: S_OK
3280 * Failure: Non-zero HRESULT value.
3281 */
3283 int cChars, int cMaxGlyphs,
3284 SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust,
3285 SCRIPT_VISATTR *psva, int *pcGlyphs)
3286{
3287 HRESULT hr;
3288 int i;
3289 SCRIPT_CHARPROP *charProps;
3290 SCRIPT_GLYPHPROP *glyphProps;
3291
3292 if (!psva || !pcGlyphs) return E_INVALIDARG;
3293 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
3294
3295 if (!(charProps = calloc(cChars, sizeof(*charProps))))
3296 return E_OUTOFMEMORY;
3297
3298 if (!(glyphProps = calloc(cMaxGlyphs, sizeof(*glyphProps))))
3299 {
3300 free(charProps);
3301 return E_OUTOFMEMORY;
3302 }
3303
3304 hr = ScriptShapeOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, pwcChars, cChars, cMaxGlyphs, pwLogClust, charProps, pwOutGlyphs, glyphProps, pcGlyphs);
3305
3306 if (SUCCEEDED(hr))
3307 {
3308 for (i = 0; i < *pcGlyphs; i++)
3309 psva[i] = glyphProps[i].sva;
3310 }
3311
3312 free(charProps);
3313 free(glyphProps);
3314
3315 return hr;
3316}
3317
3318/***********************************************************************
3319 * ScriptPlaceOpenType (USP10.@)
3320 *
3321 * Produce advance widths for a run.
3322 *
3323 * PARAMS
3324 * hdc [I] Device context.
3325 * psc [I/O] Opaque pointer to a script cache.
3326 * psa [I/O] Script analysis.
3327 * tagScript [I] The OpenType tag for the Script
3328 * tagLangSys [I] The OpenType tag for the Language
3329 * rcRangeChars[I] Array of Character counts in each range
3330 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures
3331 * cRanges [I] Count of ranges
3332 * pwcChars [I] Array of characters specifying the run.
3333 * pwLogClust [I] Array of logical cluster info
3334 * pCharProps [I] Array of character property values
3335 * cChars [I] Number of characters in pwcChars.
3336 * pwGlyphs [I] Array of glyphs.
3337 * pGlyphProps [I] Array of attributes for the retrieved glyphs
3338 * cGlyphs [I] Count of Glyphs
3339 * piAdvance [O] Array of advance widths.
3340 * pGoffset [O] Glyph offsets.
3341 * pABC [O] Combined ABC width.
3342 *
3343 * RETURNS
3344 * Success: S_OK
3345 * Failure: Non-zero HRESULT value.
3346 */
3347
3349 OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys,
3350 int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties,
3351 int cRanges, const WCHAR *pwcChars, WORD *pwLogClust,
3352 SCRIPT_CHARPROP *pCharProps, int cChars,
3353 const WORD *pwGlyphs, const SCRIPT_GLYPHPROP *pGlyphProps,
3354 int cGlyphs, int *piAdvance,
3355 GOFFSET *pGoffset, ABC *pABC
3356)
3357{
3358 HRESULT hr;
3359 int i;
3360 static int once = 0;
3361
3362 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %p, %p, %d, %p, %p, %d, %p %p %p)\n",
3363 hdc, psc, psa,
3364 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4),
3365 rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars),
3366 pwLogClust, pCharProps, cChars, pwGlyphs, pGlyphProps, cGlyphs, piAdvance,
3367 pGoffset, pABC);
3368
3369 if (!pGlyphProps) return E_INVALIDARG;
3370 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3371 if (!pGoffset) return E_FAIL;
3372
3373 if (cRanges)
3374 if (!once++) FIXME("Ranges not supported yet\n");
3375
3376 ((ScriptCache *)*psc)->userScript = tagScript;
3377 ((ScriptCache *)*psc)->userLang = tagLangSys;
3378
3379 if (pABC) memset(pABC, 0, sizeof(ABC));
3380 for (i = 0; i < cGlyphs; i++)
3381 {
3382 WORD glyph;
3383 ABC abc;
3384
3385 /* FIXME: set to more reasonable values */
3386 pGoffset[i].du = pGoffset[i].dv = 0;
3387
3388 if (pGlyphProps[i].sva.fZeroWidth)
3389 {
3390 abc.abcA = abc.abcB = abc.abcC = 0;
3391 if (piAdvance) piAdvance[i] = 0;
3392 continue;
3393 }
3394
3395 if (psa->fNoGlyphIndex)
3396 {
3397 if (FAILED(hr = ScriptGetCMap(hdc, psc, &pwGlyphs[i], 1, 0, &glyph))) return hr;
3398 }
3399 else
3400 {
3401 hr = S_OK;
3402 glyph = pwGlyphs[i];
3403 }
3404
3405 if (hr == S_FALSE)
3406 {
3407 if (!hdc) return E_PENDING;
3409 {
3410 if (!GetCharABCWidthsW(hdc, pwGlyphs[i], pwGlyphs[i], &abc)) return S_FALSE;
3411 }
3412 else
3413 {
3414 INT width;
3415 if (!GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return S_FALSE;
3416 abc.abcB = width;
3417 abc.abcA = abc.abcC = 0;
3418 }
3419 }
3420 else if (!get_cache_glyph_widths(psc, glyph, &abc))
3421 {
3422 if (!hdc) return E_PENDING;
3424 {
3425 if (!GetCharABCWidthsI(hdc, glyph, 1, NULL, &abc)) return S_FALSE;
3426 }
3427 else
3428 {
3429 INT width;
3430 if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
3431 abc.abcB = width;
3432 abc.abcA = abc.abcC = 0;
3433 }
3434 set_cache_glyph_widths(psc, glyph, &abc);
3435 }
3436 if (pABC)
3437 {
3438 pABC->abcA += abc.abcA;
3439 pABC->abcB += abc.abcB;
3440 pABC->abcC += abc.abcC;
3441 }
3442 if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC;
3443 }
3444
3445 SHAPE_ApplyOpenTypePositions(hdc, (ScriptCache *)*psc, psa, pwGlyphs, cGlyphs, piAdvance, pGoffset);
3446
3447 if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC);
3448 return S_OK;
3449}
3450
3451/***********************************************************************
3452 * ScriptPlace (USP10.@)
3453 *
3454 * Produce advance widths for a run.
3455 *
3456 * PARAMS
3457 * hdc [I] Device context.
3458 * psc [I/O] Opaque pointer to a script cache.
3459 * pwGlyphs [I] Array of glyphs.
3460 * cGlyphs [I] Number of glyphs in pwGlyphs.
3461 * psva [I] Array of visual attributes.
3462 * psa [I/O] String analysis.
3463 * piAdvance [O] Array of advance widths.
3464 * pGoffset [O] Glyph offsets.
3465 * pABC [O] Combined ABC width.
3466 *
3467 * RETURNS
3468 * Success: S_OK
3469 * Failure: Non-zero HRESULT value.
3470 */
3472 int cGlyphs, const SCRIPT_VISATTR *psva,
3473 SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC )
3474{
3475 HRESULT hr;
3476 SCRIPT_GLYPHPROP *glyphProps;
3477 int i;
3478
3479 TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs, cGlyphs, psva, psa,
3480 piAdvance, pGoffset, pABC);
3481
3482 if (!psva) return E_INVALIDARG;
3483 if (!pGoffset) return E_FAIL;
3484
3485 if (!(glyphProps = calloc(cGlyphs, sizeof(*glyphProps))))
3486 return E_OUTOFMEMORY;
3487
3488 for (i = 0; i < cGlyphs; i++)
3489 glyphProps[i].sva = psva[i];
3490
3491 hr = ScriptPlaceOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, NULL, NULL, NULL, 0, pwGlyphs, glyphProps, cGlyphs, piAdvance, pGoffset, pABC);
3492
3493 free(glyphProps);
3494
3495 return hr;
3496}
3497
3498/***********************************************************************
3499 * ScriptGetCMap (USP10.@)
3500 *
3501 * Retrieve glyph indices.
3502 *
3503 * PARAMS
3504 * hdc [I] Device context.
3505 * psc [I/O] Opaque pointer to a script cache.
3506 * pwcInChars [I] Array of Unicode characters.
3507 * cChars [I] Number of characters in pwcInChars.
3508 * dwFlags [I] Flags.
3509 * pwOutGlyphs [O] Buffer to receive the array of glyph indices.
3510 *
3511 * RETURNS
3512 * Success: S_OK
3513 * Failure: Non-zero HRESULT value.
3514 */
3516 int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
3517{
3518 HRESULT hr;
3519 int i;
3520
3521 TRACE("(%p,%p,%s,%d,0x%lx,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars),
3522 cChars, dwFlags, pwOutGlyphs);
3523
3524 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3525
3526 hr = S_OK;
3527
3528 for (i = 0; i < cChars; i++)
3529 {
3530 WCHAR inChar;
3531 if (dwFlags == SGCM_RTL)
3532 inChar = mirror_char(pwcInChars[i]);
3533 else
3534 inChar = pwcInChars[i];
3535 if (!(pwOutGlyphs[i] = get_cache_glyph(psc, inChar)))
3536 {
3537 WORD glyph;
3538 if (!hdc) return E_PENDING;
3540 return S_FALSE;
3541 if (glyph == 0xffff)
3542 {
3543 hr = S_FALSE;
3544 glyph = 0x0;
3545 }
3546 pwOutGlyphs[i] = set_cache_glyph(psc, inChar, glyph);
3547 }
3548 }
3549
3550 return hr;
3551}
3552
3553/***********************************************************************
3554 * ScriptTextOut (USP10.@)
3555 *
3556 */
3557HRESULT WINAPI ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions,
3558 const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved,
3559 int iReserved, const WORD *pwGlyphs, int cGlyphs, const int *piAdvance,
3560 const int *piJustify, const GOFFSET *pGoffset)
3561{
3562 HRESULT hr;
3563 INT i, dir = 1;
3564 INT *lpDx;
3565 WORD *reordered_glyphs = (WORD *)pwGlyphs;
3566
3567 TRACE("(%p, %p, %d, %d, %08x, %s, %p, %p, %d, %p, %d, %p, %p, %p)\n",
3568 hdc, psc, x, y, fuOptions, wine_dbgstr_rect(lprc), psa, pwcReserved, iReserved, pwGlyphs, cGlyphs,
3569 piAdvance, piJustify, pGoffset);
3570
3571 if (!hdc || !psc) return E_INVALIDARG;
3572 if (!piAdvance || !psa || !pwGlyphs) return E_INVALIDARG;
3573 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3574
3575 fuOptions &= ETO_CLIPPED | ETO_OPAQUE;
3576 fuOptions |= ETO_IGNORELANGUAGE;
3577 if (!psa->fNoGlyphIndex && *psc && ((ScriptCache *)*psc)->sfnt)
3578 fuOptions |= ETO_GLYPH_INDEX; /* We do actually have glyph indices */
3579
3580 if (!(lpDx = calloc(cGlyphs, 2 * sizeof(*lpDx))))
3581 return E_OUTOFMEMORY;
3582 fuOptions |= ETO_PDY;
3583
3584 if (psa->fRTL && psa->fLogicalOrder)
3585 {
3586 if (!(reordered_glyphs = calloc(cGlyphs, sizeof(*reordered_glyphs))))
3587 {
3588 free( lpDx );
3589 return E_OUTOFMEMORY;
3590 }
3591
3592 for (i = 0; i < cGlyphs; i++)
3593 reordered_glyphs[i] = pwGlyphs[cGlyphs - 1 - i];
3594 dir = -1;
3595 }
3596
3597 for (i = 0; i < cGlyphs; i++)
3598 {
3599 int orig_index = (dir > 0) ? i : cGlyphs - 1 - i;
3600 lpDx[i * 2] = piAdvance[orig_index];
3601 lpDx[i * 2 + 1] = 0;
3602
3603 if (pGoffset)
3604 {
3605 if (i == 0)
3606 {
3607 x += pGoffset[orig_index].du * dir;
3608 y += pGoffset[orig_index].dv;
3609 }
3610 else
3611 {
3612 lpDx[(i - 1) * 2] += pGoffset[orig_index].du * dir;
3613 lpDx[(i - 1) * 2 + 1] += pGoffset[orig_index].dv;
3614 }
3615 lpDx[i * 2] -= pGoffset[orig_index].du * dir;
3616 lpDx[i * 2 + 1] -= pGoffset[orig_index].dv;
3617 }
3618 }
3619
3620 if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, reordered_glyphs, cGlyphs, lpDx))
3621 hr = S_FALSE;
3622
3623 if (reordered_glyphs != pwGlyphs) free( reordered_glyphs );
3624 free(lpDx);
3625
3626 return hr;
3627}
3628
3629/***********************************************************************
3630 * ScriptCacheGetHeight (USP10.@)
3631 *
3632 * Retrieve the height of the font in the cache.
3633 *
3634 * PARAMS
3635 * hdc [I] Device context.
3636 * psc [I/O] Opaque pointer to a script cache.
3637 * height [O] Receives font height.
3638 *
3639 * RETURNS
3640 * Success: S_OK
3641 * Failure: Non-zero HRESULT value.
3642 */
3644{
3645 HRESULT hr;
3646
3647 TRACE("(%p, %p, %p)\n", hdc, psc, height);
3648
3649 if (!height) return E_INVALIDARG;
3650 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3651
3652 *height = get_cache_height(psc);
3653 return S_OK;
3654}
3655
3656/***********************************************************************
3657 * ScriptGetGlyphABCWidth (USP10.@)
3658 *
3659 * Retrieve the width of a glyph.
3660 *
3661 * PARAMS
3662 * hdc [I] Device context.
3663 * psc [I/O] Opaque pointer to a script cache.
3664 * glyph [I] Glyph to retrieve the width for.
3665 * abc [O] ABC widths of the glyph.
3666 *
3667 * RETURNS
3668 * Success: S_OK
3669 * Failure: Non-zero HRESULT value.
3670 */
3672{
3673 HRESULT hr;
3674
3675 TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc);
3676
3677 if (!abc) return E_INVALIDARG;
3678 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
3679
3680 if (!get_cache_glyph_widths(psc, glyph, abc))
3681 {
3682 if (!hdc) return E_PENDING;
3684 {
3685 if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE;
3686 }
3687 else
3688 {
3689 INT width;
3690 if (!GetCharWidthI(hdc, glyph, 1, NULL, &width)) return S_FALSE;
3691 abc->abcB = width;
3692 abc->abcA = abc->abcC = 0;
3693 }
3694 set_cache_glyph_widths(psc, glyph, abc);
3695 }
3696 return S_OK;
3697}
3698
3699/***********************************************************************
3700 * ScriptLayout (USP10.@)
3701 *
3702 * Map embedding levels to visual and/or logical order.
3703 *
3704 * PARAMS
3705 * runs [I] Size of level array.
3706 * level [I] Array of embedding levels.
3707 * vistolog [O] Map of embedding levels from visual to logical order.
3708 * logtovis [O] Map of embedding levels from logical to visual order.
3709 *
3710 * RETURNS
3711 * Success: S_OK
3712 * Failure: Non-zero HRESULT value.
3713 *
3714 */
3715HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
3716{
3717 int* indices;
3718 int ich;
3719
3720 TRACE("(%d, %p, %p, %p)\n", runs, level, vistolog, logtovis);
3721
3722 if (!level || (!vistolog && !logtovis))
3723 return E_INVALIDARG;
3724
3725 if (!(indices = calloc(runs, sizeof(*indices))))
3726 return E_OUTOFMEMORY;
3727
3728 if (vistolog)
3729 {
3730 for( ich = 0; ich < runs; ich++)
3731 indices[ich] = ich;
3732
3733 ich = 0;
3734 while (ich < runs)
3735 ich += BIDI_ReorderV2lLevel(0, indices+ich, level+ich, runs - ich, FALSE);
3736 memcpy(vistolog, indices, runs * sizeof(*vistolog));
3737 }
3738
3739 if (logtovis)
3740 {
3741 for( ich = 0; ich < runs; ich++)
3742 indices[ich] = ich;
3743
3744 ich = 0;
3745 while (ich < runs)
3746 ich += BIDI_ReorderL2vLevel(0, indices+ich, level+ich, runs - ich, FALSE);
3747 memcpy(logtovis, indices, runs * sizeof(*logtovis));
3748 }
3749 free(indices);
3750
3751 return S_OK;
3752}
3753
3754/***********************************************************************
3755 * ScriptStringGetLogicalWidths (USP10.@)
3756 *
3757 * Returns logical widths from a string analysis.
3758 *
3759 * PARAMS
3760 * ssa [I] string analysis.
3761 * piDx [O] logical widths returned.
3762 *
3763 * RETURNS
3764 * Success: S_OK
3765 * Failure: a non-zero HRESULT.
3766 */
3768{
3769 int i, j, next = 0;
3770 StringAnalysis *analysis = ssa;
3771
3772 TRACE("%p, %p\n", ssa, piDx);
3773
3774 if (!analysis) return S_FALSE;
3775 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
3776
3777 for (i = 0; i < analysis->numItems; i++)
3778 {
3779 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
3780 int direction = 1;
3781
3782 if (analysis->pItem[i].a.fRTL && ! analysis->pItem[i].a.fLogicalOrder)
3783 direction = -1;
3784
3785 for (j = 0; j < cChar; j++)
3786 {
3787 int k;
3788 int glyph = analysis->glyphs[i].pwLogClust[j];
3789 int clust_size = get_cluster_size(analysis->glyphs[i].pwLogClust,
3790 cChar, j, direction, NULL, NULL);
3791 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);
3792
3793 for (k = 0; k < clust_size; k++)
3794 {
3795 piDx[next] = advance / clust_size;
3796 next++;
3797 if (k) j++;
3798 }
3799 }
3800 }
3801 return S_OK;
3802}
3803
3804/***********************************************************************
3805 * ScriptStringValidate (USP10.@)
3806 *
3807 * Validate a string analysis.
3808 *
3809 * PARAMS
3810 * ssa [I] string analysis.
3811 *
3812 * RETURNS
3813 * Success: S_OK
3814 * Failure: S_FALSE if invalid sequences are found
3815 * or a non-zero HRESULT if it fails.
3816 */
3818{
3819 StringAnalysis *analysis = ssa;
3820
3821 TRACE("(%p)\n", ssa);
3822
3823 if (!analysis) return E_INVALIDARG;
3825}
3826
3827/***********************************************************************
3828 * ScriptString_pSize (USP10.@)
3829 *
3830 * Retrieve width and height of an analysed string.
3831 *
3832 * PARAMS
3833 * ssa [I] string analysis.
3834 *
3835 * RETURNS
3836 * Success: Pointer to a SIZE structure.
3837 * Failure: NULL
3838 */
3840{
3841 int i, j;
3842 StringAnalysis *analysis = ssa;
3843
3844 TRACE("(%p)\n", ssa);
3845
3846 if (!analysis) return NULL;
3847 if (!(analysis->ssa_flags & SSA_GLYPHS)) return NULL;
3848
3849 if (!(analysis->flags & SCRIPT_STRING_ANALYSIS_FLAGS_SIZE))
3850 {
3851 analysis->sz.cy = analysis->glyphs[0].sc->tm.tmHeight;
3852
3853 analysis->sz.cx = 0;
3854 for (i = 0; i < analysis->numItems; i++)
3855 {
3856 if (analysis->glyphs[i].sc->tm.tmHeight > analysis->sz.cy)
3857 analysis->sz.cy = analysis->glyphs[i].sc->tm.tmHeight;
3858 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++)
3859 analysis->sz.cx += analysis->glyphs[i].piAdvance[j];
3860 }
3862 }
3863 return &analysis->sz;
3864}
3865
3866/***********************************************************************
3867 * ScriptString_pLogAttr (USP10.@)
3868 *
3869 * Retrieve logical attributes of an analysed string.
3870 *
3871 * PARAMS
3872 * ssa [I] string analysis.
3873 *
3874 * RETURNS
3875 * Success: Pointer to an array of SCRIPT_LOGATTR structures.
3876 * Failure: NULL
3877 */
3879{
3880 StringAnalysis *analysis = ssa;
3881
3882 TRACE("(%p)\n", ssa);
3883
3884 if (!analysis) return NULL;
3885 if (!(analysis->ssa_flags & SSA_BREAK)) return NULL;
3886 return analysis->logattrs;
3887}
3888
3889/***********************************************************************
3890 * ScriptString_pcOutChars (USP10.@)
3891 *
3892 * Retrieve the length of a string after clipping.
3893 *
3894 * PARAMS
3895 * ssa [I] String analysis.
3896 *
3897 * RETURNS
3898 * Success: Pointer to the length.
3899 * Failure: NULL
3900 */
3902{
3903 StringAnalysis *analysis = ssa;
3904
3905 TRACE("(%p)\n", ssa);
3906
3907 if (!analysis) return NULL;
3908 return &analysis->clip_len;
3909}
3910
3911/***********************************************************************
3912 * ScriptStringGetOrder (USP10.@)
3913 *
3914 * Retrieve a glyph order map.
3915 *
3916 * PARAMS
3917 * ssa [I] String analysis.
3918 * order [I/O] Array of glyph positions.
3919 *
3920 * RETURNS
3921 * Success: S_OK
3922 * Failure: a non-zero HRESULT.
3923 */
3925{
3926 int i, j;
3927 unsigned int k;
3928 StringAnalysis *analysis = ssa;
3929
3930 TRACE("(%p)\n", ssa);
3931
3932 if (!analysis) return S_FALSE;
3933 if (!(analysis->ssa_flags & SSA_GLYPHS)) return S_FALSE;
3934
3935 /* FIXME: handle RTL scripts */
3936 for (i = 0, k = 0; i < analysis->numItems; i++)
3937 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++, k++)
3938 order[k] = k;
3939
3940 return S_OK;
3941}
3942
3943/***********************************************************************
3944 * ScriptGetLogicalWidths (USP10.@)
3945 *
3946 * Convert advance widths to logical widths.
3947 *
3948 * PARAMS
3949 * sa [I] Script analysis.
3950 * nbchars [I] Number of characters.
3951 * nbglyphs [I] Number of glyphs.
3952 * glyph_width [I] Array of glyph widths.
3953 * log_clust [I] Array of logical clusters.
3954 * sva [I] Visual attributes.
3955 * widths [O] Array of logical widths.
3956 *
3957 * RETURNS
3958 * Success: S_OK
3959 * Failure: a non-zero HRESULT.
3960 */
3961HRESULT WINAPI ScriptGetLogicalWidths(const SCRIPT_ANALYSIS *sa, int nbchars, int nbglyphs,
3962 const int *advances, const WORD *log_clust,
3963 const SCRIPT_VISATTR *sva, int *widths)
3964{
3965 int i, next = 0, direction;
3966
3967 TRACE("(%p, %d, %d, %p, %p, %p, %p)\n",
3968 sa, nbchars, nbglyphs, advances, log_clust, sva, widths);
3969
3970 if (sa->fRTL && !sa->fLogicalOrder)
3971 direction = -1;
3972 else
3973 direction = 1;
3974
3975 for (i = 0; i < nbchars; i++)
3976 {
3977 int clust_size = get_cluster_size(log_clust, nbchars, i, direction, NULL, NULL);
3978 int advance = get_glyph_cluster_advance(advances, sva, log_clust, nbglyphs, nbchars, log_clust[i], direction);
3979 int j;
3980
3981 for (j = 0; j < clust_size; j++)
3982 {
3983 widths[next] = advance / clust_size;
3984 next++;
3985 if (j) i++;
3986 }
3987 }
3988
3989 return S_OK;
3990}
3991
3992/***********************************************************************
3993 * ScriptApplyLogicalWidth (USP10.@)
3994 *
3995 * Generate glyph advance widths.
3996 *
3997 * PARAMS
3998 * dx [I] Array of logical advance widths.
3999 * num_chars [I] Number of characters.
4000 * num_glyphs [I] Number of glyphs.
4001 * log_clust [I] Array of logical clusters.
4002 * sva [I] Visual attributes.
4003 * advance [I] Array of glyph advance widths.
4004 * sa [I] Script analysis.
4005 * abc [I/O] Summed ABC widths.
4006 * justify [O] Array of glyph advance widths.
4007 *
4008 * RETURNS
4009 * Success: S_OK
4010 * Failure: a non-zero HRESULT.
4011 */
4012HRESULT WINAPI ScriptApplyLogicalWidth(const int *dx, int num_chars, int num_glyphs,
4013 const WORD *log_clust, const SCRIPT_VISATTR *sva,
4014 const int *advance, const SCRIPT_ANALYSIS *sa,
4015 ABC *abc, int *justify)
4016{
4017 int i;
4018
4019 FIXME("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n",
4020 dx, num_chars, num_glyphs, log_clust, sva, advance, sa, abc, justify);
4021
4022 for (i = 0; i < num_chars; i++) justify[i] = advance[i];
4023 return S_OK;
4024}
4025
4027 int num_glyphs, int dx, int min_kashida, int *justify)
4028{
4029 int i;
4030
4031 FIXME("(%p, %p, %d, %d, %d, %p)\n", sva, advance, num_glyphs, dx, min_kashida, justify);
4032
4033 for (i = 0; i < num_glyphs; i++) justify[i] = advance[i];
4034 return S_OK;
4035}
4036
4037HRESULT WINAPI ScriptGetFontScriptTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags)
4038{
4039 HRESULT hr;
4040 if (!pScriptTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4041 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4042
4043 return SHAPE_GetFontScriptTags(hdc, (ScriptCache *)*psc, psa, cMaxTags, pScriptTags, pcTags);
4044}
4045
4046HRESULT WINAPI ScriptGetFontLanguageTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags)
4047{
4048 HRESULT hr;
4049 if (!pLangSysTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4050 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4051
4052 return SHAPE_GetFontLanguageTags(hdc, (ScriptCache *)*psc, psa, tagScript, cMaxTags, pLangSysTags, pcTags);
4053}
4054
4055HRESULT WINAPI ScriptGetFontFeatureTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags)
4056{
4057 HRESULT hr;
4058 if (!pFeatureTags || !pcTags || cMaxTags == 0) return E_INVALIDARG;
4059 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
4060
4061 return SHAPE_GetFontFeatureTags(hdc, (ScriptCache *)*psc, psa, tagScript, tagLangSys, cMaxTags, pFeatureTags, pcTags);
4062}
4063
4065 WORD id, int size, WORD *list, int *count )
4066{
4067 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),
4068 debugstr_an((char*)&tag_feature,4), id, size, list, count);
4069
4070 if(count)
4071 *count = 0;
4072
4073 return E_NOTIMPL;
4074}
4075
4076#ifdef __REACTOS__
4077BOOL gbLpkPresent = FALSE;
4079{
4080 gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */
4081}
4082#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
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:1263
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:3471
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:4064
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:4037
static WORD get_cache_glyph(SCRIPT_CACHE *psc, DWORD c)
Definition: usp10.c:748
HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:2513
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:4055
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:2156
static BOOL is_indic(enum usp10_script script)
Definition: usp10.c:1229
static int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x)
Definition: usp10.c:1781
static enum usp10_script base_indic(enum usp10_script script)
Definition: usp10.c:1234
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:4012
const SCRIPT_LOGATTR *WINAPI ScriptString_pLogAttr(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3878
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:3080
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:3643
HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars, int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
Definition: usp10.c:3515
HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc)
Definition: usp10.c:1003
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:1774
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:2810
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:3961
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:1268
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:3282
HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
Definition: usp10.c:3715
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:3767
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:1905
static int get_cluster_size(const WORD *pwLogClust, int cChars, int item, int direction, int *iCluster, int *check_out)
Definition: usp10.c:2550
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:2323
static BOOL requires_fallback(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, const WCHAR *pwcInChars, int cChars)
Definition: usp10.c:1855
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:2749
HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPROPERTIES *sfp)
Definition: usp10.c:1100
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:3348
const SIZE *WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3839
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:2574
static enum usp10_script get_char_script(const WCHAR *str, unsigned int index, unsigned int end, unsigned int *consumed)
Definition: usp10.c:893
static DWORD decode_surrogate_pair(const WCHAR *str, unsigned int index, unsigned int end)
Definition: usp10.c:870
HRESULT WINAPI ScriptGetProperties(const SCRIPT_PROPERTIES ***props, int *num)
Definition: usp10.c:1078
static void find_fallback_font(enum usp10_script scriptid, WCHAR *FaceName)
Definition: usp10.c:1882
HRESULT WINAPI ScriptStringGetOrder(SCRIPT_STRING_ANALYSIS ssa, UINT *order)
Definition: usp10.c:3924
HRESULT WINAPI ScriptStringValidate(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3817
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:1749
const int *WINAPI ScriptString_pcOutChars(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3901
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int *piCh, int *piTrailing)
Definition: usp10.c:2431
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int *pX)
Definition: usp10.c:2368
int USP10_FindGlyphInLogClust(const WORD *pwLogClust, int cChars, WORD target)
Definition: usp10.c:967
#define Numeric_space
static int __cdecl usp10_compare_script_range(const void *key, const void *value)
Definition: usp10.c:881
HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds, SCRIPT_CONTROL *sc, SCRIPT_STATE *ss)
Definition: usp10.c:1199
static CRITICAL_SECTION_DEBUG cs_script_cache_dbg
Definition: usp10.c:607
HRESULT WINAPI ScriptRecordDigitSubstitution(LCID locale, SCRIPT_DIGITSUBSTITUTE *sds)
Definition: usp10.c:1133
static BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction)
Definition: usp10.c:2146
static int __cdecl compare_FindGlyph(const void *a, const void *b)
Definition: usp10.c:951
HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag)
Definition: usp10.c:3030
HRESULT WINAPI ScriptGetFontLanguageTags(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags)
Definition: usp10.c:4046
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:863
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:2606
HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: usp10.c:3003
HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance, int num_glyphs, int dx, int min_kashida, int *justify)
Definition: usp10.c:4026
static BOOL get_cluster_data(const WORD *pwLogClust, int cChars, int cluster_index, int *cluster_size, int *start_index)
Definition: usp10.c:2716
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:3671
#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:3557
#define swprintf
Definition: precomp.h:40
#define CP
Definition: debug.h:64
#define check(expected, result)
Definition: dplayx.c:43
#define L(x)
Definition: resources.c:13
#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
static float(__cdecl *square_half_float)(float x
int k
Definition: mpi.c:3369
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:1658
#define COLOR_HIGHLIGHT
Definition: winuser.h:937
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:938
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4620
static unsigned __int64 next
Definition: rand_nt.c:6
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
#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 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