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