Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenusp10.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of Uniscribe Script Processor (usp10.dll) 00003 * 00004 * Copyright 2005 Steven Edwards for CodeWeavers 00005 * Copyright 2006 Hans Leidekker 00006 * Copyright 2010 CodeWeavers, Aric Stewart 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 * 00022 * Notes: 00023 * Uniscribe allows for processing of complex scripts such as joining 00024 * and filtering characters and bi-directional text with custom line breaks. 00025 */ 00026 00027 #include <stdarg.h> 00028 #include <stdlib.h> 00029 00030 #include "windef.h" 00031 #include "winbase.h" 00032 #include "wingdi.h" 00033 #include "winuser.h" 00034 #include "winnls.h" 00035 #include "winreg.h" 00036 #include "usp10.h" 00037 00038 #include "usp10_internal.h" 00039 00040 #include "wine/debug.h" 00041 #include "wine/unicode.h" 00042 00043 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); 00044 00045 typedef struct _scriptRange 00046 { 00047 WORD script; 00048 DWORD rangeFirst; 00049 DWORD rangeLast; 00050 WORD numericScript; 00051 WORD punctScript; 00052 } scriptRange; 00053 00054 static const scriptRange scriptRanges[] = { 00055 /* Basic Latin: U+0000–U+007A */ 00056 { Script_Latin, 0x00, 0x07a , Script_Numeric, Script_Punctuation}, 00057 /* Latin-1 Supplement: U+0080–U+00FF */ 00058 /* Latin Extended-A: U+0100–U+017F */ 00059 /* Latin Extended-B: U+0180–U+024F */ 00060 /* IPA Extensions: U+0250–U+02AF */ 00061 /* Spacing Modifier Letters:U+02B0–U+02FF */ 00062 { Script_Latin, 0x80, 0x2ff , Script_Numeric2, Script_Punctuation}, 00063 /* Combining Diacritical Marks : U+0300–U+036F */ 00064 { Script_Diacritical,0x300, 0x36f, 0, 0}, 00065 /* Greek: U+0370–U+03FF */ 00066 { Script_Greek, 0x370, 0x3ff, 0, 0}, 00067 /* Cyrillic: U+0400–U+04FF */ 00068 /* Cyrillic Supplement: U+0500–U+052F */ 00069 { Script_Cyrillic, 0x400, 0x52f, 0, 0}, 00070 /* Armenian: U+0530–U+058F */ 00071 { Script_Armenian, 0x530, 0x58f, 0, 0}, 00072 /* Hebrew: U+0590–U+05FF */ 00073 { Script_Hebrew, 0x590, 0x5ff, 0, 0}, 00074 /* Arabic: U+0600–U+06FF */ 00075 { Script_Arabic, 0x600, 0x6ef, Script_Arabic_Numeric, 0}, 00076 /* Defined by Windows */ 00077 { Script_Persian, 0x6f0, 0x6f9, 0, 0}, 00078 /* Continue Arabic: U+0600–U+06FF */ 00079 { Script_Arabic, 0x6fa, 0x6ff, 0, 0}, 00080 /* Syriac: U+0700–U+074F*/ 00081 { Script_Syriac, 0x700, 0x74f, 0, 0}, 00082 /* Arabic Supplement: U+0750–U+077F */ 00083 { Script_Arabic, 0x750, 0x77f, 0, 0}, 00084 /* Thaana: U+0780–U+07BF */ 00085 { Script_Thaana, 0x780, 0x7bf, 0, 0}, 00086 /* N’Ko: U+07C0–U+07FF */ 00087 { Script_NKo, 0x7c0, 0x7ff, 0, 0}, 00088 /* Devanagari: U+0900–U+097F */ 00089 { Script_Devanagari, 0x900, 0x97f, Script_Devanagari_Numeric, 0}, 00090 /* Bengali: U+0980–U+09FF */ 00091 { Script_Bengali, 0x980, 0x9ff, Script_Bengali_Numeric, 0}, 00092 /* Gurmukhi: U+0A00–U+0A7F*/ 00093 { Script_Gurmukhi, 0xa00, 0xa7f, Script_Gurmukhi_Numeric, 0}, 00094 /* Gujarati: U+0A80–U+0AFF*/ 00095 { Script_Gujarati, 0xa80, 0xaff, Script_Gujarati_Numeric, 0}, 00096 /* Oriya: U+0B00–U+0B7F */ 00097 { Script_Oriya, 0xb00, 0xb7f, Script_Oriya_Numeric, 0}, 00098 /* Tamil: U+0B80–U+0BFF */ 00099 { Script_Tamil, 0xb80, 0xbff, Script_Tamil_Numeric, 0}, 00100 /* Telugu: U+0C00–U+0C7F */ 00101 { Script_Telugu, 0xc00, 0xc7f, Script_Telugu_Numeric, 0}, 00102 /* Kannada: U+0C80–U+0CFF */ 00103 { Script_Kannada, 0xc80, 0xcff, Script_Kannada_Numeric, 0}, 00104 /* Malayalam: U+0D00–U+0D7F */ 00105 { Script_Malayalam, 0xd00, 0xd7f, Script_Malayalam_Numeric, 0}, 00106 /* Sinhala: U+0D80–U+0DFF */ 00107 { Script_Sinhala, 0xd80, 0xdff, 0, 0}, 00108 /* Thai: U+0E00–U+0E7F */ 00109 { Script_Thai, 0xe00, 0xe7f, Script_Thai_Numeric, 0}, 00110 /* Lao: U+0E80–U+0EFF */ 00111 { Script_Lao, 0xe80, 0xeff, Script_Lao_Numeric, 0}, 00112 /* Tibetan: U+0F00–U+0FFF */ 00113 { Script_Tibetan, 0xf00, 0xfff, 0, 0}, 00114 /* Myanmar: U+1000–U+109F */ 00115 { Script_Myanmar, 0x1000, 0x109f, Script_Myanmar_Numeric, 0}, 00116 /* Georgian: U+10A0–U+10FF */ 00117 { Script_Georgian, 0x10a0, 0x10ff, 0, 0}, 00118 /* Hangul Jamo: U+1100–U+11FF */ 00119 { Script_Hangul, 0x1100, 0x11ff, 0, 0}, 00120 /* Ethiopic: U+1200–U+137F */ 00121 /* Ethiopic Extensions: U+1380–U+139F */ 00122 { Script_Ethiopic, 0x1200, 0x139f, 0, 0}, 00123 /* Cherokee: U+13A0–U+13FF */ 00124 { Script_Cherokee, 0x13a0, 0x13ff, 0, 0}, 00125 /* Canadian Aboriginal Syllabics: U+1400–U+167F */ 00126 { Script_Canadian, 0x1400, 0x167f, 0, 0}, 00127 /* Ogham: U+1680–U+169F */ 00128 { Script_Ogham, 0x1680, 0x169f, 0, 0}, 00129 /* Runic: U+16A0–U+16F0 */ 00130 { Script_Runic, 0x16a0, 0x16f0, 0, 0}, 00131 /* Khmer: U+1780–U+17FF */ 00132 { Script_Khmer, 0x1780, 0x17ff, Script_Khmer_Numeric, 0}, 00133 /* Mongolian: U+1800–U+18AF */ 00134 { Script_Mongolian, 0x1800, 0x18af, Script_Mongolian_Numeric, 0}, 00135 /* Canadian Aboriginal Syllabics Extended: U+18B0–U+18FF */ 00136 { Script_Canadian, 0x18b0, 0x18ff, 0, 0}, 00137 /* Tai Le: U+1950–U+197F */ 00138 { Script_Tai_Le, 0x1950, 0x197f, 0, 0}, 00139 /* New Tai Lue: U+1980–U+19DF */ 00140 { Script_New_Tai_Lue,0x1980, 0x19df, Script_New_Tai_Lue_Numeric, 0}, 00141 /* Khmer Symbols: U+19E0–U+19FF */ 00142 { Script_Khmer, 0x19e0, 0x19ff, Script_Khmer_Numeric, 0}, 00143 /* Vedic Extensions: U+1CD0-U+1CFF */ 00144 { Script_Devanagari, 0x1cd0, 0x1cff, Script_Devanagari_Numeric, 0}, 00145 /* Phonetic Extensions: U+1D00–U+1DBF */ 00146 { Script_Latin, 0x1d00, 0x1dbf, 0, 0}, 00147 /* Combining Diacritical Marks Supplement: U+1DC0–U+1DFF */ 00148 { Script_Diacritical,0x1dc0, 0x1dff, 0, 0}, 00149 /* Latin Extended Additional: U+1E00–U+1EFF */ 00150 { Script_Latin, 0x1e00, 0x1eff, 0, 0}, 00151 /* Greek Extended: U+1F00–U+1FFF */ 00152 { Script_Greek, 0x1f00, 0x1fff, 0, 0}, 00153 /* General Punctuation: U+2000 –U+206f */ 00154 { Script_Latin, 0x2000, 0x206f, 0, 0}, 00155 /* Superscripts and Subscripts : U+2070 –U+209f */ 00156 /* Currency Symbols : U+20a0 –U+20cf */ 00157 { Script_Numeric2, 0x2070, 0x2070, 0, 0}, 00158 { Script_Latin, 0x2071, 0x2073, 0, 0}, 00159 { Script_Numeric2, 0x2074, 0x2079, 0, 0}, 00160 { Script_Latin, 0x207a, 0x207f, 0, 0}, 00161 { Script_Numeric2, 0x2080, 0x2089, 0, 0}, 00162 { Script_Latin, 0x208a, 0x20cf, 0, 0}, 00163 /* Letterlike Symbols : U+2100 –U+214f */ 00164 /* Number Forms : U+2150 –U+218f */ 00165 /* Arrows : U+2190 –U+21ff */ 00166 /* Mathematical Operators : U+2200 –U+22ff */ 00167 /* Miscellaneous Technical : U+2300 –U+23ff */ 00168 /* Control Pictures : U+2400 –U+243f */ 00169 /* Optical Character Recognition : U+2440 –U+245f */ 00170 /* Enclosed Alphanumerics : U+2460 –U+24ff */ 00171 /* Box Drawing : U+2500 –U+25ff */ 00172 /* Block Elements : U+2580 –U+259f */ 00173 /* Geometric Shapes : U+25a0 –U+25ff */ 00174 /* Miscellaneous Symbols : U+2600 –U+26ff */ 00175 /* Dingbats : U+2700 –U+27bf */ 00176 /* Miscellaneous Mathematical Symbols-A : U+27c0 –U+27ef */ 00177 /* Supplemental Arrows-A : U+27f0 –U+27ff */ 00178 { Script_Latin, 0x2100, 0x27ff, 0, 0}, 00179 /* Braille Patterns: U+2800–U+28FF */ 00180 { Script_Braille, 0x2800, 0x28ff, 0, 0}, 00181 /* Supplemental Arrows-B : U+2900 –U+297f */ 00182 /* Miscellaneous Mathematical Symbols-B : U+2980 –U+29ff */ 00183 /* Supplemental Mathematical Operators : U+2a00 –U+2aff */ 00184 /* Miscellaneous Symbols and Arrows : U+2b00 –U+2bff */ 00185 { Script_Latin, 0x2900, 0x2bff, 0, 0}, 00186 /* Latin Extended-C: U+2C60–U+2C7F */ 00187 { Script_Latin, 0x2c60, 0x2c7f, 0, 0}, 00188 /* Georgian: U+2D00–U+2D2F */ 00189 { Script_Georgian, 0x2d00, 0x2d2f, 0, 0}, 00190 /* Tifinagh: U+2D30–U+2D7F */ 00191 { Script_Tifinagh, 0x2d30, 0x2d7f, 0, 0}, 00192 /* Ethiopic Extensions: U+2D80–U+2DDF */ 00193 { Script_Ethiopic, 0x2d80, 0x2ddf, 0, 0}, 00194 /* Cyrillic Extended-A: U+2DE0–U+2DFF */ 00195 { Script_Cyrillic, 0x2de0, 0x2dff, 0, 0}, 00196 /* CJK Radicals Supplement: U+2E80–U+2EFF */ 00197 /* Kangxi Radicals: U+2F00–U+2FDF */ 00198 { Script_CJK_Han, 0x2e80, 0x2fdf, 0, 0}, 00199 /* Ideographic Description Characters: U+2FF0–U+2FFF */ 00200 { Script_Ideograph ,0x2ff0, 0x2fff, 0, 0}, 00201 /* CJK Symbols and Punctuation: U+3000–U+303F */ 00202 { Script_Ideograph ,0x3000, 0x3004, 0, 0}, 00203 { Script_CJK_Han ,0x3005, 0x3005, 0, 0}, 00204 { Script_Ideograph ,0x3006, 0x3006, 0, 0}, 00205 { Script_CJK_Han ,0x3007, 0x3007, 0, 0}, 00206 { Script_Ideograph ,0x3008, 0x3020, 0, 0}, 00207 { Script_CJK_Han ,0x3021, 0x3029, 0, 0}, 00208 { Script_Ideograph ,0x302a, 0x3030, 0, 0}, 00209 /* Kana Marks: */ 00210 { Script_Kana ,0x3031, 0x3035, 0, 0}, 00211 { Script_Ideograph ,0x3036, 0x3037, 0, 0}, 00212 { Script_CJK_Han ,0x3038, 0x303b, 0, 0}, 00213 { Script_Ideograph ,0x303c, 0x303f, 0, 0}, 00214 /* Hiragana: U+3040–U+309F */ 00215 /* Katakana: U+30A0–U+30FF */ 00216 { Script_Kana ,0x3040, 0x30ff, 0, 0}, 00217 /* Bopomofo: U+3100–U+312F */ 00218 { Script_Bopomofo ,0x3100, 0x312f, 0, 0}, 00219 /* Hangul Compatibility Jamo: U+3130–U+318F */ 00220 { Script_Hangul ,0x3130, 0x318f, 0, 0}, 00221 /* Kanbun: U+3190–U+319F */ 00222 { Script_Ideograph ,0x3190, 0x319f, 0, 0}, 00223 /* Bopomofo Extended: U+31A0–U+31BF */ 00224 { Script_Bopomofo ,0x31a0, 0x31bf, 0, 0}, 00225 /* CJK Strokes: U+31C0–U+31EF */ 00226 { Script_Ideograph ,0x31c0, 0x31ef, 0, 0}, 00227 /* Katakana Phonetic Extensions: U+31F0–U+31FF */ 00228 { Script_Kana ,0x31f0, 0x31ff, 0, 0}, 00229 /* Enclosed CJK Letters and Months: U+3200–U+32FF */ 00230 { Script_Hangul ,0x3200, 0x321f, 0, 0}, 00231 { Script_Ideograph ,0x3220, 0x325f, 0, 0}, 00232 { Script_Hangul ,0x3260, 0x327f, 0, 0}, 00233 { Script_Ideograph ,0x3280, 0x32ef, 0, 0}, 00234 { Script_Kana ,0x32d0, 0x31ff, 0, 0}, 00235 /* CJK Compatibility: U+3300–U+33FF*/ 00236 { Script_Kana ,0x3300, 0x3357, 0, 0}, 00237 { Script_Ideograph ,0x3358, 0x33ff, 0, 0}, 00238 /* CJK Unified Ideographs Extension A: U+3400–U+4DBF */ 00239 { Script_CJK_Han ,0x3400, 0x4dbf, 0, 0}, 00240 /* CJK Unified Ideographs: U+4E00–U+9FFF */ 00241 { Script_CJK_Han ,0x4e00, 0x9fff, 0, 0}, 00242 /* Yi: U+A000–U+A4CF */ 00243 { Script_Yi ,0xa000, 0xa4cf, 0, 0}, 00244 /* Vai: U+A500–U+A63F */ 00245 { Script_Vai ,0xa500, 0xa63f, Script_Vai_Numeric, 0}, 00246 /* Cyrillic Extended-B: U+A640–U+A69F */ 00247 { Script_Cyrillic, 0xa640, 0xa69f, 0, 0}, 00248 /* Modifier Tone Letters: U+A700–U+A71F */ 00249 /* Latin Extended-D: U+A720–U+A7FF */ 00250 { Script_Latin, 0xa700, 0xa7ff, 0, 0}, 00251 /* Phags-pa: U+A840–U+A87F */ 00252 { Script_Phags_pa, 0xa840, 0xa87f, 0, 0}, 00253 /* Devanagari Extended: U+A8E0-U+A8FF */ 00254 { Script_Devanagari, 0xa8e0, 0xa8ff, Script_Devanagari_Numeric, 0}, 00255 /* Myanmar Extended-A: U+AA60–U+AA7F */ 00256 { Script_Myanmar, 0xaa60, 0xaa7f, Script_Myanmar_Numeric, 0}, 00257 /* Hangul Jamo Extended-A: U+A960–U+A97F */ 00258 { Script_Hangul, 0xa960, 0xa97f, 0, 0}, 00259 /* Hangul Syllables: U+AC00–U+D7A3 */ 00260 { Script_Hangul, 0xac00, 0xd7a3, 0, 0}, 00261 /* Hangul Jamo Extended-B: U+D7B0–U+D7FF */ 00262 { Script_Hangul, 0xd7b0, 0xd7ff, 0, 0}, 00263 /* Surrogates Area: U+D800–U+DFFF */ 00264 { Script_Surrogates, 0xd800, 0xdbfe, 0, 0}, 00265 { Script_Private, 0xdbff, 0xdc00, 0, 0}, 00266 { Script_Surrogates, 0xdc01, 0xdfff, 0, 0}, 00267 /* Private Use Area: U+E000–U+F8FF */ 00268 { Script_Private, 0xe000, 0xf8ff, 0, 0}, 00269 /* CJK Compatibility Ideographs: U+F900–U+FAFF */ 00270 { Script_CJK_Han ,0xf900, 0xfaff, 0, 0}, 00271 /* Latin Ligatures: U+FB00–U+FB06 */ 00272 { Script_Latin, 0xfb00, 0xfb06, 0, 0}, 00273 /* Armenian ligatures U+FB13..U+FB17 */ 00274 { Script_Armenian, 0xfb13, 0xfb17, 0, 0}, 00275 /* Alphabetic Presentation Forms: U+FB1D–U+FB4F */ 00276 { Script_Hebrew, 0xfb1d, 0xfb4f, 0, 0}, 00277 /* Arabic Presentation Forms-A: U+FB50–U+FDFF*/ 00278 { Script_Arabic, 0xfb50, 0xfdff, 0, 0}, 00279 /* Vertical Forms: U+FE10–U+FE1F */ 00280 /* Combining Half Marks: U+FE20–U+FE2F */ 00281 /* CJK Compatibility Forms: U+FE30–U+FE4F */ 00282 /* Small Form Variants: U+FE50–U+FE6F */ 00283 { Script_Ideograph ,0xfe10, 0xfe6f, 0, 0}, 00284 /* Arabic Presentation Forms-B: U+FE70–U+FEFF*/ 00285 { Script_Arabic, 0xfe70, 0xfeff, 0, 0}, 00286 /* Halfwidth and Fullwidth Forms: U+FF00–FFEF */ 00287 { Script_Ideograph ,0xff00, 0xff64, Script_Numeric2, 0}, 00288 { Script_Kana ,0xff65, 0xff9f, 0, 0}, 00289 { Script_Hangul ,0xffa0, 0xffdf, 0, 0}, 00290 { Script_Ideograph ,0xffe0, 0xffef, 0, 0}, 00291 /* Plane - 1 */ 00292 /* Deseret: U+10400–U+1044F */ 00293 { Script_Deseret, 0x10400, 0x1044F, 0, 0}, 00294 /* Osmanya: U+10480–U+104AF */ 00295 { Script_Osmanya, 0x10480, 0x104AF, Script_Osmanya_Numeric, 0}, 00296 /* Mathematical Alphanumeric Symbols: U+1D400–U+1D7FF */ 00297 { Script_MathAlpha, 0x1D400, 0x1D7FF, 0, 0}, 00298 /* END */ 00299 { SCRIPT_UNDEFINED, 0, 0, 0} 00300 }; 00301 00302 /* the must be in order so that the index matches the Script value */ 00303 const scriptData scriptInformation[] = { 00304 {{SCRIPT_UNDEFINED, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00305 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00306 0x00000000, 00307 {0}}, 00308 {{Script_Latin, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00309 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00310 MS_MAKE_TAG('l','a','t','n'), 00311 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00312 {{Script_CR, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00313 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00314 0x00000000, 00315 {0}}, 00316 {{Script_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00317 {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00318 0x00000000, 00319 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00320 {{Script_Control, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00321 {LANG_ENGLISH, 0, 1, 0, 0, ANSI_CHARSET, 1, 0, 0, 0, 0, 0, 1, 0, 0}, 00322 0x00000000, 00323 {0}}, 00324 {{Script_Punctuation, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00325 {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00326 0x00000000, 00327 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00328 {{Script_Arabic, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00329 {LANG_ARABIC, 0, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 1, 0}, 00330 MS_MAKE_TAG('a','r','a','b'), 00331 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00332 {{Script_Arabic_Numeric, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00333 {LANG_ARABIC, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00334 MS_MAKE_TAG('a','r','a','b'), 00335 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00336 {{Script_Hebrew, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00337 {LANG_HEBREW, 0, 1, 0, 1, HEBREW_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00338 MS_MAKE_TAG('h','e','b','r'), 00339 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00340 {{Script_Syriac, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00341 {LANG_SYRIAC, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 1, 0}, 00342 MS_MAKE_TAG('s','y','r','c'), 00343 {'E','s','t','r','a','n','g','e','l','o',' ','E','d','e','s','s','a',0}}, 00344 {{Script_Persian, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00345 {LANG_PERSIAN, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00346 MS_MAKE_TAG('s','y','r','c'), 00347 {'E','s','t','r','a','n','g','e','l','o',' ','E','d','e','s','s','a',0}}, 00348 {{Script_Thaana, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00349 {LANG_DIVEHI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00350 MS_MAKE_TAG('t','h','a','a'), 00351 {'M','V',' ','B','o','l','i',0}}, 00352 {{Script_Greek, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00353 {LANG_GREEK, 0, 0, 0, 0, GREEK_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00354 MS_MAKE_TAG('g','r','e','k'), 00355 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00356 {{Script_Cyrillic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00357 {LANG_RUSSIAN, 0, 0, 0, 0, RUSSIAN_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00358 MS_MAKE_TAG('c','y','r','l'), 00359 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00360 {{Script_Armenian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00361 {LANG_ARMENIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00362 MS_MAKE_TAG('a','r','m','n'), 00363 {'S','y','l','f','a','e','n',0}}, 00364 {{Script_Georgian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00365 {LANG_GEORGIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00366 MS_MAKE_TAG('g','e','o','r'), 00367 {'S','y','l','f','a','e','n',0}}, 00368 {{Script_Sinhala, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00369 {LANG_SINHALESE, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00370 MS_MAKE_TAG('s','i','n','h'), 00371 {'I','s','k','o','o','l','a',' ','P','o','t','a',0}}, 00372 {{Script_Tibetan, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00373 {LANG_TIBETAN, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0}, 00374 MS_MAKE_TAG('t','i','b','t'), 00375 {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}}, 00376 {{Script_Tibetan_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00377 {LANG_TIBETAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00378 MS_MAKE_TAG('t','i','b','t'), 00379 {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}}, 00380 {{Script_Phags_pa, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00381 {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00382 MS_MAKE_TAG('p','h','a','g'), 00383 {'M','i','c','r','o','s','o','f','t',' ','P','h','a','g','s','P','a',0}}, 00384 {{Script_Thai, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00385 {LANG_THAI, 0, 1, 1, 1, THAI_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 1}, 00386 MS_MAKE_TAG('t','h','a','i'), 00387 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00388 {{Script_Thai_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00389 {LANG_THAI, 1, 1, 0, 0, THAI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00390 MS_MAKE_TAG('t','h','a','i'), 00391 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00392 {{Script_Lao, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00393 {LANG_LAO, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0}, 00394 MS_MAKE_TAG('l','a','o',' '), 00395 {'D','o','k','C','h','a','m','p','a',0}}, 00396 {{Script_Lao_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00397 {LANG_LAO, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00398 MS_MAKE_TAG('l','a','o',' '), 00399 {'D','o','k','C','h','a','m','p','a',0}}, 00400 {{Script_Devanagari, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00401 {LANG_HINDI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00402 MS_MAKE_TAG('d','e','v','a'), 00403 {'M','a','n','g','a','l',0}}, 00404 {{Script_Devanagari_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00405 {LANG_HINDI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00406 MS_MAKE_TAG('d','e','v','a'), 00407 {'M','a','n','g','a','l',0}}, 00408 {{Script_Bengali, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00409 {LANG_BENGALI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00410 MS_MAKE_TAG('b','e','n','g'), 00411 {'V','r','i','n','d','a',0}}, 00412 {{Script_Bengali_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00413 {LANG_BENGALI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00414 MS_MAKE_TAG('b','e','n','g'), 00415 {'V','r','i','n','d','a',0}}, 00416 {{Script_Bengali_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00417 {LANG_BENGALI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00418 MS_MAKE_TAG('b','e','n','g'), 00419 {'V','r','i','n','d','a',0}}, 00420 {{Script_Gurmukhi, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00421 {LANG_PUNJABI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00422 MS_MAKE_TAG('g','u','r','u'), 00423 {'R','a','a','v','i',0}}, 00424 {{Script_Gurmukhi_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00425 {LANG_PUNJABI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00426 MS_MAKE_TAG('g','u','r','u'), 00427 {'R','a','a','v','i',0}}, 00428 {{Script_Gujarati, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00429 {LANG_GUJARATI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00430 MS_MAKE_TAG('g','u','j','r'), 00431 {'S','h','r','u','t','i',0}}, 00432 {{Script_Gujarati_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00433 {LANG_GUJARATI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00434 MS_MAKE_TAG('g','u','j','r'), 00435 {'S','h','r','u','t','i',0}}, 00436 {{Script_Gujarati_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00437 {LANG_GUJARATI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00438 MS_MAKE_TAG('g','u','j','r'), 00439 {'S','h','r','u','t','i',0}}, 00440 {{Script_Oriya, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00441 {LANG_ORIYA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00442 MS_MAKE_TAG('o','r','y','a'), 00443 {'K','a','l','i','n','g','a',0}}, 00444 {{Script_Oriya_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00445 {LANG_ORIYA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00446 MS_MAKE_TAG('o','r','y','a'), 00447 {'K','a','l','i','n','g','a',0}}, 00448 {{Script_Tamil, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00449 {LANG_TAMIL, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00450 MS_MAKE_TAG('t','a','m','l'), 00451 {'L','a','t','h','a',0}}, 00452 {{Script_Tamil_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00453 {LANG_TAMIL, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00454 MS_MAKE_TAG('t','a','m','l'), 00455 {'L','a','t','h','a',0}}, 00456 {{Script_Telugu, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00457 {LANG_TELUGU, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00458 MS_MAKE_TAG('t','e','l','u'), 00459 {'G','a','u','t','a','m','i',0}}, 00460 {{Script_Telugu_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00461 {LANG_TELUGU, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00462 MS_MAKE_TAG('t','e','l','u'), 00463 {'G','a','u','t','a','m','i',0}}, 00464 {{Script_Kannada, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00465 {LANG_KANNADA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00466 MS_MAKE_TAG('k','n','d','a'), 00467 {'T','u','n','g','a',0}}, 00468 {{Script_Kannada_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00469 {LANG_KANNADA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00470 MS_MAKE_TAG('k','n','d','a'), 00471 {'T','u','n','g','a',0}}, 00472 {{Script_Malayalam, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00473 {LANG_MALAYALAM, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00474 MS_MAKE_TAG('m','l','y','m'), 00475 {'K','a','r','t','i','k','a',0}}, 00476 {{Script_Malayalam_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00477 {LANG_MALAYALAM, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00478 MS_MAKE_TAG('m','l','y','m'), 00479 {'K','a','r','t','i','k','a',0}}, 00480 {{Script_Diacritical, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00481 {LANG_ENGLISH, 0, 1, 0, 1, ANSI_CHARSET, 0, 0, 0, 0, 0, 1, 1, 0, 0}, 00482 0x00000000, 00483 {0}}, 00484 {{Script_Punctuation2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00485 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00486 MS_MAKE_TAG('l','a','t','n'), 00487 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00488 {{Script_Numeric2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00489 {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00490 0x00000000, 00491 {0}}, 00492 {{Script_Myanmar, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00493 {0x55, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00494 MS_MAKE_TAG('m','y','m','r'), 00495 {'M','y','a','n','m','a','r',' ','T','e','x','t',0}}, 00496 {{Script_Myanmar_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00497 {0x55, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00498 MS_MAKE_TAG('m','y','m','r'), 00499 {0}}, 00500 {{Script_Tai_Le, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00501 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00502 MS_MAKE_TAG('t','a','l','e'), 00503 {'M','i','c','r','o','s','o','f','t',' ','T','a','i',' ','L','e'}}, 00504 {{Script_New_Tai_Lue, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00505 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00506 MS_MAKE_TAG('t','a','l','u'), 00507 {'M','i','c','r','o','s','o','f','t',' ','N','e','w',' ','T','a','i',' ','L','u','e'}}, 00508 {{Script_New_Tai_Lue_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00509 {0, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00510 MS_MAKE_TAG('t','a','l','u'), 00511 {'M','i','c','r','o','s','o','f','t',' ','N','e','w',' ','T','a','i',' ','L','u','e'}}, 00512 {{Script_Khmer, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00513 {0x53, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, 00514 MS_MAKE_TAG('k','h','m','r'), 00515 {'D','a','u','n','P','e','n','h'}}, 00516 {{Script_Khmer, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00517 {0x53, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00518 MS_MAKE_TAG('k','h','m','r'), 00519 {'D','a','u','n','P','e','n','h'}}, 00520 {{Script_CJK_Han, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00521 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00522 MS_MAKE_TAG('h','a','n','i'), 00523 {0}}, 00524 {{Script_Ideograph, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00525 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00526 MS_MAKE_TAG('h','a','n','i'), 00527 {0}}, 00528 {{Script_Bopomofo, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00529 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00530 MS_MAKE_TAG('b','o','p','o'), 00531 {0}}, 00532 {{Script_Kana, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00533 {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00534 MS_MAKE_TAG('k','a','n','a'), 00535 {0}}, 00536 {{Script_Hangul, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00537 {LANG_KOREAN, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00538 MS_MAKE_TAG('h','a','n','g'), 00539 {0}}, 00540 {{Script_Yi, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00541 {LANG_ENGLISH, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00542 MS_MAKE_TAG('y','i',' ',' '), 00543 {'M','i','c','r','o','s','o','f','t',' ','Y','i',' ','B','a','i','t','i'}}, 00544 {{Script_Ethiopic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00545 {0x5e, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00546 MS_MAKE_TAG('e','t','h','i'), 00547 {'N','y','a','l','a'}}, 00548 {{Script_Ethiopic_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00549 {0x5e, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00550 MS_MAKE_TAG('e','t','h','i'), 00551 {'N','y','a','l','a'}}, 00552 {{Script_Mongolian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00553 {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00554 MS_MAKE_TAG('m','o','n','g'), 00555 {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i'}}, 00556 {{Script_Mongolian_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00557 {LANG_MONGOLIAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00558 MS_MAKE_TAG('m','o','n','g'), 00559 {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i'}}, 00560 {{Script_Tifinagh, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00561 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00562 MS_MAKE_TAG('t','f','n','g'), 00563 {'E','b','r','i','m','a'}}, 00564 {{Script_NKo, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, 00565 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00566 MS_MAKE_TAG('n','k','o',' '), 00567 {'E','b','r','i','m','a'}}, 00568 {{Script_Vai, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00569 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00570 MS_MAKE_TAG('v','a','i',' '), 00571 {'E','b','r','i','m','a'}}, 00572 {{Script_Vai_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00573 {0, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00574 MS_MAKE_TAG('v','a','i',' '), 00575 {'E','b','r','i','m','a'}}, 00576 {{Script_Cherokee, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00577 {0x5c, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00578 MS_MAKE_TAG('c','h','e','r'), 00579 {'P','l','a','n','t','a','g','e','n','e','t',' ','C','h','e','r','o','k','e','e'}}, 00580 {{Script_Canadian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00581 {0x5d, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00582 MS_MAKE_TAG('c','a','n','s'), 00583 {'E','u','p','h','e','m','i','a'}}, 00584 {{Script_Ogham, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00585 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00586 MS_MAKE_TAG('o','g','a','m'), 00587 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l'}}, 00588 {{Script_Runic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00589 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00590 MS_MAKE_TAG('r','u','n','r'), 00591 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l'}}, 00592 {{Script_Braille, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00593 {LANG_ENGLISH, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00594 MS_MAKE_TAG('b','r','a','i'), 00595 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l'}}, 00596 {{Script_Surrogates, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00597 {LANG_ENGLISH, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 00598 0x00000000, 00599 {0}}, 00600 {{Script_Private, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00601 {0, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 1, 0, 0, 0, 0, 1, 0, 0}, 00602 0x00000000, 00603 {0}}, 00604 {{Script_Deseret, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00605 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00606 MS_MAKE_TAG('d','s','r','t'), 00607 {'S','e','g','o','e',' ','U','I',' ','S','y','m','b','o','l'}}, 00608 {{Script_Osmanya, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00609 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00610 MS_MAKE_TAG('o','s','m','a'), 00611 {'E','b','r','i','m','a'}}, 00612 {{Script_Osmanya_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00613 {0, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00614 MS_MAKE_TAG('o','s','m','a'), 00615 {'E','b','r','i','m','a'}}, 00616 {{Script_MathAlpha, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00617 {0, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00618 MS_MAKE_TAG('m','a','t','h'), 00619 {'C','a','m','b','r','i','a',' ','M','a','t','h'}}, 00620 {{Script_Hebrew_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00621 {LANG_HEBREW, 0, 1, 0, 0, HEBREW_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00622 MS_MAKE_TAG('h','e','b','r'), 00623 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00624 {{Script_Vietnamese_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00625 {LANG_VIETNAMESE, 0, 0, 0, 0, VIETNAMESE_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00626 MS_MAKE_TAG('l','a','t','n'), 00627 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00628 {{Script_Thai_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, 00629 {LANG_THAI, 0, 1, 0, 0, THAI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 00630 MS_MAKE_TAG('t','h','a','i'), 00631 {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, 00632 }; 00633 00634 static const SCRIPT_PROPERTIES *script_props[] = 00635 { 00636 &scriptInformation[0].props, &scriptInformation[1].props, 00637 &scriptInformation[2].props, &scriptInformation[3].props, 00638 &scriptInformation[4].props, &scriptInformation[5].props, 00639 &scriptInformation[6].props, &scriptInformation[7].props, 00640 &scriptInformation[8].props, &scriptInformation[9].props, 00641 &scriptInformation[10].props, &scriptInformation[11].props, 00642 &scriptInformation[12].props, &scriptInformation[13].props, 00643 &scriptInformation[14].props, &scriptInformation[15].props, 00644 &scriptInformation[16].props, &scriptInformation[17].props, 00645 &scriptInformation[18].props, &scriptInformation[19].props, 00646 &scriptInformation[20].props, &scriptInformation[21].props, 00647 &scriptInformation[22].props, &scriptInformation[23].props, 00648 &scriptInformation[24].props, &scriptInformation[25].props, 00649 &scriptInformation[26].props, &scriptInformation[27].props, 00650 &scriptInformation[28].props, &scriptInformation[29].props, 00651 &scriptInformation[30].props, &scriptInformation[31].props, 00652 &scriptInformation[32].props, &scriptInformation[33].props, 00653 &scriptInformation[34].props, &scriptInformation[35].props, 00654 &scriptInformation[36].props, &scriptInformation[37].props, 00655 &scriptInformation[38].props, &scriptInformation[39].props, 00656 &scriptInformation[40].props, &scriptInformation[41].props, 00657 &scriptInformation[42].props, &scriptInformation[43].props, 00658 &scriptInformation[44].props, &scriptInformation[45].props, 00659 &scriptInformation[46].props, &scriptInformation[47].props, 00660 &scriptInformation[48].props, &scriptInformation[49].props, 00661 &scriptInformation[50].props, &scriptInformation[51].props, 00662 &scriptInformation[52].props, &scriptInformation[53].props, 00663 &scriptInformation[54].props, &scriptInformation[55].props, 00664 &scriptInformation[56].props, &scriptInformation[57].props, 00665 &scriptInformation[58].props, &scriptInformation[59].props, 00666 &scriptInformation[60].props, &scriptInformation[61].props, 00667 &scriptInformation[62].props, &scriptInformation[63].props, 00668 &scriptInformation[64].props, &scriptInformation[65].props, 00669 &scriptInformation[66].props, &scriptInformation[67].props, 00670 &scriptInformation[68].props, &scriptInformation[69].props, 00671 &scriptInformation[70].props, &scriptInformation[71].props, 00672 &scriptInformation[72].props, &scriptInformation[73].props, 00673 &scriptInformation[74].props, &scriptInformation[75].props, 00674 &scriptInformation[76].props, &scriptInformation[77].props, 00675 &scriptInformation[78].props, &scriptInformation[79].props, 00676 &scriptInformation[80].props, &scriptInformation[81].props 00677 }; 00678 00679 typedef struct { 00680 ScriptCache *sc; 00681 int numGlyphs; 00682 WORD* glyphs; 00683 WORD* pwLogClust; 00684 int* piAdvance; 00685 SCRIPT_VISATTR* psva; 00686 GOFFSET* pGoffset; 00687 ABC* abc; 00688 int iMaxPosX; 00689 HFONT fallbackFont; 00690 } StringGlyphs; 00691 00692 typedef struct { 00693 HDC hdc; 00694 DWORD dwFlags; 00695 BOOL invalid; 00696 int clip_len; 00697 int cItems; 00698 int cMaxGlyphs; 00699 SCRIPT_ITEM* pItem; 00700 int numItems; 00701 StringGlyphs* glyphs; 00702 SCRIPT_LOGATTR* logattrs; 00703 SIZE* sz; 00704 int* logical2visual; 00705 } StringAnalysis; 00706 00707 typedef struct { 00708 BOOL ascending; 00709 WORD target; 00710 } FindGlyph_struct; 00711 00712 static inline void *heap_alloc(SIZE_T size) 00713 { 00714 return HeapAlloc(GetProcessHeap(), 0, size); 00715 } 00716 00717 static inline void *heap_alloc_zero(SIZE_T size) 00718 { 00719 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 00720 } 00721 00722 static inline void *heap_realloc_zero(LPVOID mem, SIZE_T size) 00723 { 00724 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, size); 00725 } 00726 00727 static inline BOOL heap_free(LPVOID mem) 00728 { 00729 return HeapFree(GetProcessHeap(), 0, mem); 00730 } 00731 00732 static inline WCHAR get_cache_default_char(SCRIPT_CACHE *psc) 00733 { 00734 return ((ScriptCache *)*psc)->tm.tmDefaultChar; 00735 } 00736 00737 static inline LONG get_cache_height(SCRIPT_CACHE *psc) 00738 { 00739 return ((ScriptCache *)*psc)->tm.tmHeight; 00740 } 00741 00742 static inline BYTE get_cache_pitch_family(SCRIPT_CACHE *psc) 00743 { 00744 return ((ScriptCache *)*psc)->tm.tmPitchAndFamily; 00745 } 00746 00747 static inline WORD get_cache_glyph(SCRIPT_CACHE *psc, DWORD c) 00748 { 00749 WORD *block = ((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT]; 00750 00751 if (!block) return 0; 00752 return block[c & GLYPH_BLOCK_MASK]; 00753 } 00754 00755 static inline WORD set_cache_glyph(SCRIPT_CACHE *psc, WCHAR c, WORD glyph) 00756 { 00757 WORD **block = &((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT]; 00758 00759 if (!*block && !(*block = heap_alloc_zero(sizeof(WORD) * GLYPH_BLOCK_SIZE))) return 0; 00760 return ((*block)[c & GLYPH_BLOCK_MASK] = glyph); 00761 } 00762 00763 static inline BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc) 00764 { 00765 static const ABC nil; 00766 ABC *block = ((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT]; 00767 00768 if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(ABC))) return FALSE; 00769 memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC)); 00770 return TRUE; 00771 } 00772 00773 static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc) 00774 { 00775 ABC **block = &((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT]; 00776 00777 if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE))) return FALSE; 00778 memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC)); 00779 return TRUE; 00780 } 00781 00782 static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc) 00783 { 00784 ScriptCache *sc; 00785 00786 if (!psc) return E_INVALIDARG; 00787 if (*psc) return S_OK; 00788 if (!hdc) return E_PENDING; 00789 00790 if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY; 00791 if (!GetTextMetricsW(hdc, &sc->tm)) 00792 { 00793 heap_free(sc); 00794 return E_INVALIDARG; 00795 } 00796 if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf)) 00797 { 00798 heap_free(sc); 00799 return E_INVALIDARG; 00800 } 00801 sc->sfnt = (GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0)!=GDI_ERROR); 00802 *psc = sc; 00803 TRACE("<- %p\n", sc); 00804 return S_OK; 00805 } 00806 00807 static WCHAR mirror_char( WCHAR ch ) 00808 { 00809 extern const WCHAR wine_mirror_map[]; 00810 return ch + wine_mirror_map[wine_mirror_map[ch >> 8] + (ch & 0xff)]; 00811 } 00812 00813 static inline DWORD decode_surrogate_pair(LPCWSTR str, INT index, INT end) 00814 { 00815 if (index < end-1 && IS_SURROGATE_PAIR(str[index],str[index+1])) 00816 { 00817 DWORD ch = 0x10000 + ((str[index] - 0xd800) << 10) + (str[index+1] - 0xdc00); 00818 TRACE("Surrogate Pair %x %x => %x\n",str[index], str[index+1], ch); 00819 return ch; 00820 } 00821 return 0; 00822 } 00823 00824 static WORD get_char_script( LPCWSTR str, INT index, INT end, INT *consumed) 00825 { 00826 static const WCHAR latin_punc[] = {'#','$','&','\'',',',';','<','>','?','@','\\','^','_','`','{','|','}','~', 0x00a0, 0}; 00827 WORD type = 0; 00828 DWORD ch; 00829 int i; 00830 00831 *consumed = 1; 00832 00833 if (str[index] == 0xc || str[index] == 0x20 || str[index] == 0x202f) 00834 return Script_CR; 00835 00836 /* These punctuation are separated out as Latin punctuation */ 00837 if (strchrW(latin_punc,str[index])) 00838 return Script_Punctuation2; 00839 00840 /* These chars are itemized as Punctuation by Windows */ 00841 if (str[index] == 0x2212 || str[index] == 0x2044) 00842 return Script_Punctuation; 00843 00844 /* Currency Symboles by Unicode point */ 00845 switch (str[index]) 00846 { 00847 case 0x09f2: 00848 case 0x09f3: return Script_Bengali_Currency; 00849 case 0x0af1: return Script_Gujarati_Currency; 00850 case 0x0e3f: return Script_Thai_Currency; 00851 case 0x20aa: return Script_Hebrew_Currency; 00852 case 0x20ab: return Script_Vietnamese_Currency; 00853 case 0xfb29: return Script_Hebrew_Currency; 00854 } 00855 00856 GetStringTypeW(CT_CTYPE1, &str[index], 1, &type); 00857 00858 if (type == 0) 00859 return SCRIPT_UNDEFINED; 00860 00861 if (type & C1_CNTRL) 00862 return Script_Control; 00863 00864 ch = decode_surrogate_pair(str, index, end); 00865 if (ch) 00866 *consumed = 2; 00867 else 00868 ch = str[index]; 00869 00870 i = 0; 00871 do 00872 { 00873 if (ch < scriptRanges[i].rangeFirst || scriptRanges[i].script == SCRIPT_UNDEFINED) 00874 break; 00875 00876 if (ch >= scriptRanges[i].rangeFirst && ch <= scriptRanges[i].rangeLast) 00877 { 00878 if (scriptRanges[i].numericScript && type & C1_DIGIT) 00879 return scriptRanges[i].numericScript; 00880 if (scriptRanges[i].punctScript && type & C1_PUNCT) 00881 return scriptRanges[i].punctScript; 00882 return scriptRanges[i].script; 00883 } 00884 i++; 00885 } while (1); 00886 00887 return SCRIPT_UNDEFINED; 00888 } 00889 00890 static int compare_FindGlyph(const void *a, const void* b) 00891 { 00892 const FindGlyph_struct *find = (FindGlyph_struct*)a; 00893 const WORD *idx= (WORD*)b; 00894 int rc = 0; 00895 00896 if ( find->target > *idx) 00897 rc = 1; 00898 else if (find->target < *idx) 00899 rc = -1; 00900 00901 if (!find->ascending) 00902 rc *= -1; 00903 return rc; 00904 } 00905 00906 int USP10_FindGlyphInLogClust(const WORD* pwLogClust, int cChars, WORD target) 00907 { 00908 FindGlyph_struct fgs; 00909 WORD *ptr; 00910 INT k; 00911 00912 if (pwLogClust[0] < pwLogClust[cChars-1]) 00913 fgs.ascending = TRUE; 00914 else 00915 fgs.ascending = FALSE; 00916 00917 fgs.target = target; 00918 ptr = bsearch(&fgs, pwLogClust, cChars, sizeof(WORD), compare_FindGlyph); 00919 00920 if (!ptr) 00921 return -1; 00922 00923 for (k = (ptr - pwLogClust)-1; k >= 0 && pwLogClust[k] == target; k--) 00924 ; 00925 k++; 00926 00927 return k; 00928 } 00929 00930 /*********************************************************************** 00931 * DllMain 00932 * 00933 */ 00934 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 00935 { 00936 switch(fdwReason) 00937 { 00938 case DLL_PROCESS_ATTACH: 00939 DisableThreadLibraryCalls(hInstDLL); 00940 break; 00941 case DLL_PROCESS_DETACH: 00942 break; 00943 } 00944 return TRUE; 00945 } 00946 00947 /*********************************************************************** 00948 * ScriptFreeCache (USP10.@) 00949 * 00950 * Free a script cache. 00951 * 00952 * PARAMS 00953 * psc [I/O] Script cache. 00954 * 00955 * RETURNS 00956 * Success: S_OK 00957 * Failure: Non-zero HRESULT value. 00958 */ 00959 HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) 00960 { 00961 TRACE("%p\n", psc); 00962 00963 if (psc && *psc) 00964 { 00965 unsigned int i; 00966 for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++) 00967 { 00968 heap_free(((ScriptCache *)*psc)->glyphs[i]); 00969 heap_free(((ScriptCache *)*psc)->widths[i]); 00970 } 00971 heap_free(((ScriptCache *)*psc)->GSUB_Table); 00972 heap_free(((ScriptCache *)*psc)->GDEF_Table); 00973 heap_free(((ScriptCache *)*psc)->CMAP_Table); 00974 for (i = 0; i < ((ScriptCache *)*psc)->script_count; i++) 00975 { 00976 int j; 00977 for (j = 0; j < ((ScriptCache *)*psc)->scripts[i].language_count; j++) 00978 { 00979 int k; 00980 for (k = 0; k < ((ScriptCache *)*psc)->scripts[i].languages[j].feature_count; k++) 00981 heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features[k].lookups); 00982 heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features); 00983 } 00984 heap_free(((ScriptCache *)*psc)->scripts[i].languages); 00985 } 00986 heap_free(((ScriptCache *)*psc)->scripts); 00987 heap_free(*psc); 00988 *psc = NULL; 00989 } 00990 return S_OK; 00991 } 00992 00993 /*********************************************************************** 00994 * ScriptGetProperties (USP10.@) 00995 * 00996 * Retrieve a list of script properties. 00997 * 00998 * PARAMS 00999 * props [I] Pointer to an array of SCRIPT_PROPERTIES pointers. 01000 * num [I] Pointer to the number of scripts. 01001 * 01002 * RETURNS 01003 * Success: S_OK 01004 * Failure: Non-zero HRESULT value. 01005 * 01006 * NOTES 01007 * Behaviour matches WinXP. 01008 */ 01009 HRESULT WINAPI ScriptGetProperties(const SCRIPT_PROPERTIES ***props, int *num) 01010 { 01011 TRACE("(%p,%p)\n", props, num); 01012 01013 if (!props && !num) return E_INVALIDARG; 01014 01015 if (num) *num = sizeof(script_props)/sizeof(script_props[0]); 01016 if (props) *props = script_props; 01017 01018 return S_OK; 01019 } 01020 01021 /*********************************************************************** 01022 * ScriptGetFontProperties (USP10.@) 01023 * 01024 * Get information on special glyphs. 01025 * 01026 * PARAMS 01027 * hdc [I] Device context. 01028 * psc [I/O] Opaque pointer to a script cache. 01029 * sfp [O] Font properties structure. 01030 */ 01031 HRESULT WINAPI ScriptGetFontProperties(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_FONTPROPERTIES *sfp) 01032 { 01033 HRESULT hr; 01034 01035 TRACE("%p,%p,%p\n", hdc, psc, sfp); 01036 01037 if (!sfp) return E_INVALIDARG; 01038 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 01039 01040 if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES)) 01041 return E_INVALIDARG; 01042 01043 /* return something sensible? */ 01044 sfp->wgBlank = 0; 01045 sfp->wgDefault = get_cache_default_char(psc); 01046 sfp->wgInvalid = 0; 01047 sfp->wgKashida = 0xffff; 01048 sfp->iKashidaWidth = 0; 01049 01050 return S_OK; 01051 } 01052 01053 /*********************************************************************** 01054 * ScriptRecordDigitSubstitution (USP10.@) 01055 * 01056 * Record digit substitution settings for a given locale. 01057 * 01058 * PARAMS 01059 * locale [I] Locale identifier. 01060 * sds [I] Structure to record substitution settings. 01061 * 01062 * RETURNS 01063 * Success: S_OK 01064 * Failure: E_POINTER if sds is NULL, E_INVALIDARG otherwise. 01065 * 01066 * SEE ALSO 01067 * http://blogs.msdn.com/michkap/archive/2006/02/22/536877.aspx 01068 */ 01069 HRESULT WINAPI ScriptRecordDigitSubstitution(LCID locale, SCRIPT_DIGITSUBSTITUTE *sds) 01070 { 01071 DWORD plgid, sub; 01072 01073 TRACE("0x%x, %p\n", locale, sds); 01074 01075 /* This implementation appears to be correct for all languages, but it's 01076 * not clear if sds->DigitSubstitute is ever set to anything except 01077 * CONTEXT or NONE in reality */ 01078 01079 if (!sds) return E_POINTER; 01080 01081 locale = ConvertDefaultLocale(locale); 01082 01083 if (!IsValidLocale(locale, LCID_INSTALLED)) 01084 return E_INVALIDARG; 01085 01086 plgid = PRIMARYLANGID(LANGIDFROMLCID(locale)); 01087 sds->TraditionalDigitLanguage = plgid; 01088 01089 if (plgid == LANG_ARABIC || plgid == LANG_FARSI) 01090 sds->NationalDigitLanguage = plgid; 01091 else 01092 sds->NationalDigitLanguage = LANG_ENGLISH; 01093 01094 if (!GetLocaleInfoW(locale, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, 01095 (LPWSTR)&sub, sizeof(sub)/sizeof(WCHAR))) return E_INVALIDARG; 01096 01097 switch (sub) 01098 { 01099 case 0: 01100 if (plgid == LANG_ARABIC || plgid == LANG_FARSI) 01101 sds->DigitSubstitute = SCRIPT_DIGITSUBSTITUTE_CONTEXT; 01102 else 01103 sds->DigitSubstitute = SCRIPT_DIGITSUBSTITUTE_NONE; 01104 break; 01105 case 1: 01106 sds->DigitSubstitute = SCRIPT_DIGITSUBSTITUTE_NONE; 01107 break; 01108 case 2: 01109 sds->DigitSubstitute = SCRIPT_DIGITSUBSTITUTE_NATIONAL; 01110 break; 01111 default: 01112 sds->DigitSubstitute = SCRIPT_DIGITSUBSTITUTE_TRADITIONAL; 01113 break; 01114 } 01115 01116 sds->dwReserved = 0; 01117 return S_OK; 01118 } 01119 01120 /*********************************************************************** 01121 * ScriptApplyDigitSubstitution (USP10.@) 01122 * 01123 * Apply digit substitution settings. 01124 * 01125 * PARAMS 01126 * sds [I] Structure with recorded substitution settings. 01127 * sc [I] Script control structure. 01128 * ss [I] Script state structure. 01129 * 01130 * RETURNS 01131 * Success: S_OK 01132 * Failure: E_INVALIDARG if sds is invalid. Otherwise an HRESULT. 01133 */ 01134 HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds, 01135 SCRIPT_CONTROL *sc, SCRIPT_STATE *ss) 01136 { 01137 SCRIPT_DIGITSUBSTITUTE psds; 01138 01139 TRACE("%p, %p, %p\n", sds, sc, ss); 01140 01141 if (!sc || !ss) return E_POINTER; 01142 if (!sds) 01143 { 01144 sds = &psds; 01145 if (ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &psds) != S_OK) 01146 return E_INVALIDARG; 01147 } 01148 01149 sc->uDefaultLanguage = LANG_ENGLISH; 01150 sc->fContextDigits = 0; 01151 ss->fDigitSubstitute = 0; 01152 01153 switch (sds->DigitSubstitute) { 01154 case SCRIPT_DIGITSUBSTITUTE_CONTEXT: 01155 case SCRIPT_DIGITSUBSTITUTE_NATIONAL: 01156 case SCRIPT_DIGITSUBSTITUTE_NONE: 01157 case SCRIPT_DIGITSUBSTITUTE_TRADITIONAL: 01158 return S_OK; 01159 default: 01160 return E_INVALIDARG; 01161 } 01162 } 01163 01164 static inline BOOL is_indic(WORD script) 01165 { 01166 return (script >= Script_Devanagari && script <= Script_Malayalam_Numeric); 01167 } 01168 01169 static inline WORD base_indic(WORD script) 01170 { 01171 switch (script) 01172 { 01173 case Script_Devanagari: 01174 case Script_Devanagari_Numeric: return Script_Devanagari; 01175 case Script_Bengali: 01176 case Script_Bengali_Numeric: 01177 case Script_Bengali_Currency: return Script_Bengali; 01178 case Script_Gurmukhi: 01179 case Script_Gurmukhi_Numeric: return Script_Gurmukhi; 01180 case Script_Gujarati: 01181 case Script_Gujarati_Numeric: 01182 case Script_Gujarati_Currency: return Script_Gujarati; 01183 case Script_Oriya: 01184 case Script_Oriya_Numeric: return Script_Oriya; 01185 case Script_Tamil: 01186 case Script_Tamil_Numeric: return Script_Tamil; 01187 case Script_Telugu: 01188 case Script_Telugu_Numeric: return Script_Telugu; 01189 case Script_Kannada: 01190 case Script_Kannada_Numeric: return Script_Kannada; 01191 case Script_Malayalam: 01192 case Script_Malayalam_Numeric: return Script_Malayalam; 01193 default: 01194 return -1; 01195 }; 01196 } 01197 01198 /*********************************************************************** 01199 * ScriptItemizeOpenType (USP10.@) 01200 * 01201 * Split a Unicode string into shapeable parts. 01202 * 01203 * PARAMS 01204 * pwcInChars [I] String to split. 01205 * cInChars [I] Number of characters in pwcInChars. 01206 * cMaxItems [I] Maximum number of items to return. 01207 * psControl [I] Pointer to a SCRIPT_CONTROL structure. 01208 * psState [I] Pointer to a SCRIPT_STATE structure. 01209 * pItems [O] Buffer to receive SCRIPT_ITEM structures. 01210 * pScriptTags [O] Buffer to receive OPENTYPE_TAGs. 01211 * pcItems [O] Number of script items returned. 01212 * 01213 * RETURNS 01214 * Success: S_OK 01215 * Failure: Non-zero HRESULT value. 01216 */ 01217 HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems, 01218 const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, 01219 SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems) 01220 { 01221 01222 #define Numeric_space 0x0020 01223 #define ZWNJ 0x200C 01224 #define ZWJ 0x200D 01225 01226 int cnt = 0, index = 0, str = 0; 01227 int New_Script = -1; 01228 int i; 01229 WORD *levels = NULL; 01230 WORD *strength = NULL; 01231 WORD *scripts = NULL; 01232 WORD baselevel = 0; 01233 BOOL new_run; 01234 WORD last_indic = -1; 01235 WORD layoutRTL = 0; 01236 BOOL forceLevels = FALSE; 01237 INT consumed = 0; 01238 01239 TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, 01240 psControl, psState, pItems, pcItems); 01241 01242 if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2) 01243 return E_INVALIDARG; 01244 01245 scripts = heap_alloc(cInChars * sizeof(WORD)); 01246 if (!scripts) 01247 return E_OUTOFMEMORY; 01248 01249 for (i = 0; i < cInChars; i++) 01250 { 01251 if (consumed <= 0) 01252 { 01253 scripts[i] = get_char_script(pwcInChars,i,cInChars,&consumed); 01254 consumed --; 01255 } 01256 else 01257 { 01258 scripts[i] = scripts[i-1]; 01259 consumed --; 01260 } 01261 /* Devanagari danda (U+0964) and double danda (U+0965) are used for 01262 all Indic scripts */ 01263 if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic > 0) 01264 scripts[i] = last_indic; 01265 else if (is_indic(scripts[i])) 01266 last_indic = base_indic(scripts[i]); 01267 01268 /* Some unicode points (Zero Width Space U+200B - 01269 Right-to-Left Mark U+200F) will force us into bidi mode */ 01270 if (!forceLevels && pwcInChars[i] >= 0x200B && pwcInChars[i] <= 0x200F) 01271 forceLevels = TRUE; 01272 01273 /* Diacritical marks merge with other scripts */ 01274 if (scripts[i] == Script_Diacritical && i > 0) 01275 scripts[i] = scripts[i-1]; 01276 } 01277 01278 for (i = 0; i < cInChars; i++) 01279 { 01280 /* Joiners get merged preferencially right */ 01281 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ)) 01282 { 01283 int j; 01284 if (i+1 == cInChars) 01285 scripts[i] = scripts[i-1]; 01286 else 01287 { 01288 for (j = i+1; j < cInChars; j++) 01289 { 01290 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ && pwcInChars[j] != Numeric_space) 01291 { 01292 scripts[i] = scripts[j]; 01293 break; 01294 } 01295 } 01296 } 01297 } 01298 } 01299 01300 if (psState && psControl) 01301 { 01302 levels = heap_alloc_zero(cInChars * sizeof(WORD)); 01303 if (!levels) 01304 { 01305 heap_free(scripts); 01306 return E_OUTOFMEMORY; 01307 } 01308 01309 BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels); 01310 baselevel = levels[0]; 01311 for (i = 0; i < cInChars; i++) 01312 if (levels[i]!=levels[0]) 01313 break; 01314 if (i >= cInChars && !odd(baselevel) && !odd(psState->uBidiLevel) && !forceLevels) 01315 { 01316 heap_free(levels); 01317 levels = NULL; 01318 } 01319 else 01320 { 01321 BOOL inNumber = FALSE; 01322 static WCHAR math_punc[] = {'#','$','%','+',',','-','.','/',':',0x2212, 0x2044, 0x00a0,0}; 01323 01324 strength = heap_alloc_zero(cInChars * sizeof(WORD)); 01325 if (!strength) 01326 { 01327 heap_free(scripts); 01328 heap_free(levels); 01329 return E_OUTOFMEMORY; 01330 } 01331 BIDI_GetStrengths(pwcInChars, cInChars, psControl, strength); 01332 01333 /* We currently mis-level leading Diacriticals */ 01334 if (scripts[0] == Script_Diacritical) 01335 for (i = 0; i < cInChars && scripts[0] == Script_Diacritical; i++) 01336 { 01337 levels[i] = odd(levels[i])?levels[i]+1:levels[i]; 01338 strength[i] = BIDI_STRONG; 01339 } 01340 01341 for (i = 0; i < cInChars; i++) 01342 { 01343 /* Script_Numeric and select puncuation at level 0 get bumped to level 2 */ 01344 if ((levels[i] == 0 || (odd(psState->uBidiLevel) && levels[i] == psState->uBidiLevel+1)) && inNumber && strchrW(math_punc,pwcInChars[i])) 01345 { 01346 scripts[i] = Script_Numeric; 01347 levels[i] = 2; 01348 } 01349 else if ((levels[i] == 0 || (odd(psState->uBidiLevel) && levels[i] == psState->uBidiLevel+1)) && scripts[i] == Script_Numeric) 01350 { 01351 levels[i] = 2; 01352 inNumber = TRUE; 01353 } 01354 else 01355 inNumber = FALSE; 01356 01357 /* Joiners get merged preferencially right */ 01358 if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ)) 01359 { 01360 int j; 01361 if (i+1 == cInChars && levels[i-1] == levels[i]) 01362 strength[i] = strength[i-1]; 01363 else 01364 for (j = i+1; j < cInChars && levels[i] == levels[j]; j++) 01365 if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ && pwcInChars[j] != Numeric_space) 01366 { 01367 strength[i] = strength[j]; 01368 break; 01369 } 01370 } 01371 } 01372 if (psControl->fMergeNeutralItems) 01373 { 01374 /* Merge the neutrals */ 01375 for (i = 0; i < cInChars; i++) 01376 { 01377 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK) 01378 { 01379 int j; 01380 for (j = i; j > 0; j--) 01381 { 01382 if (levels[i] != levels[j]) 01383 break; 01384 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK)) 01385 { 01386 scripts[i] = scripts[j]; 01387 strength[i] = strength[j]; 01388 break; 01389 } 01390 } 01391 } 01392 /* Try going the other way */ 01393 if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK) 01394 { 01395 int j; 01396 for (j = i; j < cInChars; j++) 01397 { 01398 if (levels[i] != levels[j]) 01399 break; 01400 if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK)) 01401 { 01402 scripts[i] = scripts[j]; 01403 strength[i] = strength[j]; 01404 break; 01405 } 01406 } 01407 } 01408 } 01409 } 01410 } 01411 } 01412 01413 while ((!levels || (levels && levels[cnt+1] == levels[0])) && (pwcInChars[cnt] == Numeric_space) && cnt < cInChars) 01414 cnt++; 01415 01416 if (cnt == cInChars) /* All Spaces */ 01417 { 01418 cnt = 0; 01419 New_Script = scripts[cnt]; 01420 } 01421 01422 pItems[index].iCharPos = 0; 01423 pItems[index].a = scriptInformation[scripts[cnt]].a; 01424 pScriptTags[index] = scriptInformation[scripts[cnt]].scriptTag; 01425 01426 if (strength && strength[cnt] == BIDI_STRONG) 01427 str = strength[cnt]; 01428 else if (strength) 01429 str = strength[0]; 01430 01431 cnt = 0; 01432 01433 if (levels) 01434 { 01435 if (strength[cnt] == BIDI_STRONG) 01436 layoutRTL = (odd(levels[cnt]))?1:0; 01437 else 01438 layoutRTL = (psState->uBidiLevel || odd(levels[cnt]))?1:0; 01439 pItems[index].a.fRTL = odd(levels[cnt]); 01440 pItems[index].a.fLayoutRTL = layoutRTL; 01441 pItems[index].a.s.uBidiLevel = levels[cnt]; 01442 } 01443 else if (!pItems[index].a.s.uBidiLevel) 01444 { 01445 layoutRTL = (odd(baselevel))?1:0; 01446 pItems[index].a.s.uBidiLevel = baselevel; 01447 pItems[index].a.fLayoutRTL = odd(baselevel); 01448 pItems[index].a.fRTL = odd(baselevel); 01449 } 01450 01451 TRACE("New_Level=%i New_Strength=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n", 01452 levels?levels[cnt]:-1, str, New_Script, pItems[index].a.eScript, index, cnt, 01453 pItems[index].iCharPos); 01454 01455 for (cnt=1; cnt < cInChars; cnt++) 01456 { 01457 if(pwcInChars[cnt] != Numeric_space) 01458 New_Script = scripts[cnt]; 01459 else if (levels) 01460 { 01461 int j = 1; 01462 while (cnt + j < cInChars - 1 && pwcInChars[cnt+j] == Numeric_space && levels[cnt] == levels[cnt+j]) 01463 j++; 01464 if (cnt + j < cInChars && levels[cnt] == levels[cnt+j]) 01465 New_Script = scripts[cnt+j]; 01466 else 01467 New_Script = scripts[cnt]; 01468 } 01469 01470 new_run = FALSE; 01471 /* merge space strengths*/ 01472 if (strength && strength[cnt] == BIDI_STRONG && str != BIDI_STRONG && New_Script == pItems[index].a.eScript) 01473 str = BIDI_STRONG; 01474 01475 if (strength && strength[cnt] == BIDI_NEUTRAL && str == BIDI_STRONG && pwcInChars[cnt] != Numeric_space && New_Script == pItems[index].a.eScript) 01476 str = BIDI_NEUTRAL; 01477 01478 /* changes in level */ 01479 if (levels && (levels[cnt] != pItems[index].a.s.uBidiLevel)) 01480 { 01481 TRACE("Level break(%i/%i)\n",pItems[index].a.s.uBidiLevel,levels[cnt]); 01482 new_run = TRUE; 01483 } 01484 /* changes in strength */ 01485 else if (strength && pwcInChars[cnt] != Numeric_space && str != strength[cnt]) 01486 { 01487 TRACE("Strength break (%i/%i)\n",str,strength[cnt]); 01488 new_run = TRUE; 01489 } 01490 /* changes in script */ 01491 else if (((pwcInChars[cnt] != Numeric_space) && (New_Script != -1) && (New_Script != pItems[index].a.eScript)) || (New_Script == Script_Control)) 01492 { 01493 TRACE("Script break(%i/%i)\n",pItems[index].a.eScript,New_Script); 01494 new_run = TRUE; 01495 } 01496 01497 if (!new_run && strength && str == BIDI_STRONG) 01498 { 01499 layoutRTL = odd(levels[cnt])?1:0; 01500 pItems[index].a.fLayoutRTL = layoutRTL; 01501 } 01502 01503 if (new_run) 01504 { 01505 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); 01506 01507 index++; 01508 if (index+1 > cMaxItems) 01509 return E_OUTOFMEMORY; 01510 01511 if (strength) 01512 str = strength[cnt]; 01513 01514 pItems[index].iCharPos = cnt; 01515 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); 01516 01517 pItems[index].a = scriptInformation[New_Script].a; 01518 pScriptTags[index] = scriptInformation[New_Script].scriptTag; 01519 if (levels) 01520 { 01521 if (levels[cnt] == 0) 01522 layoutRTL = 0; 01523 else 01524 layoutRTL = (layoutRTL || odd(levels[cnt]))?1:0; 01525 pItems[index].a.fRTL = odd(levels[cnt]); 01526 pItems[index].a.fLayoutRTL = layoutRTL; 01527 pItems[index].a.s.uBidiLevel = levels[cnt]; 01528 } 01529 else if (!pItems[index].a.s.uBidiLevel) 01530 { 01531 pItems[index].a.s.uBidiLevel = baselevel; 01532 pItems[index].a.fLayoutRTL = layoutRTL; 01533 pItems[index].a.fRTL = odd(baselevel); 01534 } 01535 01536 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); 01537 } 01538 } 01539 01540 /* While not strictly necessary according to the spec, make sure the n+1 01541 * item is set up to prevent random behaviour if the caller erroneously 01542 * checks the n+1 structure */ 01543 index++; 01544 memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); 01545 01546 TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); 01547 01548 /* Set one SCRIPT_STATE item being returned */ 01549 if (index + 1 > cMaxItems) return E_OUTOFMEMORY; 01550 if (pcItems) *pcItems = index; 01551 01552 /* Set SCRIPT_ITEM */ 01553 pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */ 01554 heap_free(levels); 01555 heap_free(strength); 01556 heap_free(scripts); 01557 return S_OK; 01558 } 01559 01560 /*********************************************************************** 01561 * ScriptItemize (USP10.@) 01562 * 01563 * Split a Unicode string into shapeable parts. 01564 * 01565 * PARAMS 01566 * pwcInChars [I] String to split. 01567 * cInChars [I] Number of characters in pwcInChars. 01568 * cMaxItems [I] Maximum number of items to return. 01569 * psControl [I] Pointer to a SCRIPT_CONTROL structure. 01570 * psState [I] Pointer to a SCRIPT_STATE structure. 01571 * pItems [O] Buffer to receive SCRIPT_ITEM structures. 01572 * pcItems [O] Number of script items returned. 01573 * 01574 * RETURNS 01575 * Success: S_OK 01576 * Failure: Non-zero HRESULT value. 01577 */ 01578 HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, 01579 const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, 01580 SCRIPT_ITEM *pItems, int *pcItems) 01581 { 01582 OPENTYPE_TAG *discarded_tags; 01583 HRESULT res; 01584 01585 discarded_tags = heap_alloc(cMaxItems * sizeof(OPENTYPE_TAG)); 01586 if (!discarded_tags) 01587 return E_OUTOFMEMORY; 01588 res = ScriptItemizeOpenType(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, discarded_tags, pcItems); 01589 heap_free(discarded_tags); 01590 return res; 01591 } 01592 01593 static inline int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x) 01594 { 01595 int defWidth; 01596 int cTabStops=0; 01597 INT *lpTabPos = NULL; 01598 INT nTabOrg = 0; 01599 INT x = 0; 01600 01601 if (pTabdef) 01602 lpTabPos = pTabdef->pTabStops; 01603 01604 if (pTabdef && pTabdef->iTabOrigin) 01605 { 01606 if (pTabdef->iScale) 01607 nTabOrg = (pTabdef->iTabOrigin * pTabdef->iScale)/4; 01608 else 01609 nTabOrg = pTabdef->iTabOrigin * psc->tm.tmAveCharWidth; 01610 } 01611 01612 if (pTabdef) 01613 cTabStops = pTabdef->cTabStops; 01614 01615 if (cTabStops == 1) 01616 { 01617 if (pTabdef->iScale) 01618 defWidth = ((pTabdef->pTabStops[0])*pTabdef->iScale) / 4; 01619 else 01620 defWidth = (pTabdef->pTabStops[0])*psc->tm.tmAveCharWidth; 01621 cTabStops = 0; 01622 } 01623 else 01624 defWidth = 8 * psc->tm.tmAveCharWidth; 01625 01626 for (; cTabStops>0 ; lpTabPos++, cTabStops--) 01627 { 01628 int position = *lpTabPos; 01629 if (position < 0) 01630 position = -1 * position; 01631 if (pTabdef->iScale) 01632 position = (position * pTabdef->iScale) / 4; 01633 else 01634 position = position * psc->tm.tmAveCharWidth; 01635 01636 if( nTabOrg + position > current_x) 01637 { 01638 if( *lpTabPos >= 0) 01639 { 01640 /* a left aligned tab */ 01641 x = (nTabOrg + *lpTabPos) - current_x; 01642 break; 01643 } 01644 else 01645 { 01646 FIXME("Negative tabstop\n"); 01647 break; 01648 } 01649 } 01650 } 01651 if ((!cTabStops) && (defWidth > 0)) 01652 x =((((current_x - nTabOrg) / defWidth)+1) * defWidth) - current_x; 01653 else if ((!cTabStops) && (defWidth < 0)) 01654 FIXME("TODO: Negative defWidth\n"); 01655 01656 return x; 01657 } 01658 01659 /*********************************************************************** 01660 * Helper function for ScriptStringAnalyse 01661 */ 01662 static BOOL requires_fallback(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, 01663 const WCHAR *pwcInChars, int cChars ) 01664 { 01665 /* FIXME: When to properly fallback is still a bit of a mystery */ 01666 WORD *glyphs; 01667 01668 if (psa->fNoGlyphIndex) 01669 return FALSE; 01670 01671 if (init_script_cache(hdc, psc) != S_OK) 01672 return FALSE; 01673 01674 if (SHAPE_CheckFontForRequiredFeatures(hdc, (ScriptCache *)*psc, psa) != S_OK) 01675 return TRUE; 01676 01677 glyphs = heap_alloc(sizeof(WORD) * cChars); 01678 if (!glyphs) 01679 return FALSE; 01680 if (ScriptGetCMap(hdc, psc, pwcInChars, cChars, 0, glyphs) != S_OK) 01681 { 01682 heap_free(glyphs); 01683 return TRUE; 01684 } 01685 heap_free(glyphs); 01686 01687 return FALSE; 01688 } 01689 01690 static void find_fallback_font(DWORD scriptid, LPWSTR FaceName) 01691 { 01692 HKEY hkey; 01693 01694 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Uniscribe\\Fallback", &hkey)) 01695 { 01696 static const WCHAR szFmt[] = {'%','x',0}; 01697 WCHAR value[10]; 01698 DWORD count = LF_FACESIZE * sizeof(WCHAR); 01699 DWORD type; 01700 01701 sprintfW(value, szFmt, scriptInformation[scriptid].scriptTag); 01702 if (RegQueryValueExW(hkey, value, 0, &type, (LPBYTE)FaceName, &count)) 01703 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont); 01704 RegCloseKey(hkey); 01705 } 01706 else 01707 lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont); 01708 } 01709 01710 /*********************************************************************** 01711 * ScriptStringAnalyse (USP10.@) 01712 * 01713 */ 01714 HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, 01715 int cGlyphs, int iCharset, DWORD dwFlags, 01716 int iReqWidth, SCRIPT_CONTROL *psControl, 01717 SCRIPT_STATE *psState, const int *piDx, 01718 SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass, 01719 SCRIPT_STRING_ANALYSIS *pssa) 01720 { 01721 HRESULT hr = E_OUTOFMEMORY; 01722 StringAnalysis *analysis = NULL; 01723 SCRIPT_CONTROL sControl; 01724 SCRIPT_STATE sState; 01725 int i, num_items = 255; 01726 BYTE *BidiLevel; 01727 WCHAR *iString = NULL; 01728 01729 TRACE("(%p,%p,%d,%d,%d,0x%x,%d,%p,%p,%p,%p,%p,%p)\n", 01730 hdc, pString, cString, cGlyphs, iCharset, dwFlags, iReqWidth, 01731 psControl, psState, piDx, pTabdef, pbInClass, pssa); 01732 01733 if (iCharset != -1) 01734 { 01735 FIXME("Only Unicode strings are supported\n"); 01736 return E_INVALIDARG; 01737 } 01738 if (cString < 1 || !pString) return E_INVALIDARG; 01739 if ((dwFlags & SSA_GLYPHS) && !hdc) return E_PENDING; 01740 01741 if (!(analysis = heap_alloc_zero(sizeof(StringAnalysis)))) return E_OUTOFMEMORY; 01742 if (!(analysis->pItem = heap_alloc_zero(num_items * sizeof(SCRIPT_ITEM) + 1))) goto error; 01743 01744 /* FIXME: handle clipping */ 01745 analysis->clip_len = cString; 01746 analysis->hdc = hdc; 01747 analysis->dwFlags = dwFlags; 01748 01749 if (psState) 01750 sState = *psState; 01751 else 01752 memset(&sState, 0, sizeof(SCRIPT_STATE)); 01753 01754 if (psControl) 01755 sControl = *psControl; 01756 else 01757 memset(&sControl, 0, sizeof(SCRIPT_CONTROL)); 01758 01759 if (dwFlags & SSA_PASSWORD) 01760 { 01761 iString = heap_alloc(sizeof(WCHAR)*cString); 01762 if (!iString) 01763 { 01764 hr = E_OUTOFMEMORY; 01765 goto error; 01766 } 01767 for (i = 0; i < cString; i++) 01768 iString[i] = *((const WCHAR *)pString); 01769 pString = iString; 01770 } 01771 01772 hr = ScriptItemize(pString, cString, num_items, &sControl, &sState, analysis->pItem, 01773 &analysis->numItems); 01774 01775 if FAILED(hr) 01776 { 01777 if (hr == E_OUTOFMEMORY) 01778 hr = E_INVALIDARG; 01779 goto error; 01780 } 01781 01782 /* set back to out of memory for default goto error behaviour */ 01783 hr = E_OUTOFMEMORY; 01784 01785 if (dwFlags & SSA_BREAK) 01786 { 01787 if ((analysis->logattrs = heap_alloc(sizeof(SCRIPT_LOGATTR) * cString))) 01788 { 01789 for (i = 0; i < analysis->numItems; i++) 01790 ScriptBreak(&((LPWSTR)pString)[analysis->pItem[i].iCharPos], analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos, &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]); 01791 } 01792 else 01793 goto error; 01794 } 01795 01796 if (!(analysis->logical2visual = heap_alloc_zero(sizeof(int) * analysis->numItems))) 01797 goto error; 01798 if (!(BidiLevel = heap_alloc_zero(analysis->numItems))) 01799 goto error; 01800 01801 if (dwFlags & SSA_GLYPHS) 01802 { 01803 int tab_x = 0; 01804 if (!(analysis->glyphs = heap_alloc_zero(sizeof(StringGlyphs) * analysis->numItems))) 01805 { 01806 heap_free(BidiLevel); 01807 goto error; 01808 } 01809 01810 for (i = 0; i < analysis->numItems; i++) 01811 { 01812 SCRIPT_CACHE *sc = (SCRIPT_CACHE*)&analysis->glyphs[i].sc; 01813 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; 01814 int numGlyphs = 1.5 * cChar + 16; 01815 WORD *glyphs = heap_alloc_zero(sizeof(WORD) * numGlyphs); 01816 WORD *pwLogClust = heap_alloc_zero(sizeof(WORD) * cChar); 01817 int *piAdvance = heap_alloc_zero(sizeof(int) * numGlyphs); 01818 SCRIPT_VISATTR *psva = heap_alloc_zero(sizeof(SCRIPT_VISATTR) * numGlyphs); 01819 GOFFSET *pGoffset = heap_alloc_zero(sizeof(GOFFSET) * numGlyphs); 01820 ABC *abc = heap_alloc_zero(sizeof(ABC)); 01821 int numGlyphsReturned; 01822 HFONT originalFont = 0x0; 01823 01824 /* FIXME: non unicode strings */ 01825 const WCHAR* pStr = (const WCHAR*)pString; 01826 analysis->glyphs[i].fallbackFont = NULL; 01827 01828 if (!glyphs || !pwLogClust || !piAdvance || !psva || !pGoffset || !abc) 01829 { 01830 heap_free (BidiLevel); 01831 heap_free (glyphs); 01832 heap_free (pwLogClust); 01833 heap_free (piAdvance); 01834 heap_free (psva); 01835 heap_free (pGoffset); 01836 heap_free (abc); 01837 hr = E_OUTOFMEMORY; 01838 goto error; 01839 } 01840 01841 if ((dwFlags & SSA_FALLBACK) && requires_fallback(hdc, sc, &analysis->pItem[i].a, &pStr[analysis->pItem[i].iCharPos], cChar)) 01842 { 01843 LOGFONTW lf; 01844 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), & lf); 01845 lf.lfCharSet = scriptInformation[analysis->pItem[i].a.eScript].props.bCharSet; 01846 lf.lfFaceName[0] = 0; 01847 find_fallback_font(analysis->pItem[i].a.eScript, lf.lfFaceName); 01848 if (lf.lfFaceName[0]) 01849 { 01850 analysis->glyphs[i].fallbackFont = CreateFontIndirectW(&lf); 01851 if (analysis->glyphs[i].fallbackFont) 01852 { 01853 ScriptFreeCache(sc); 01854 originalFont = SelectObject(hdc, analysis->glyphs[i].fallbackFont); 01855 } 01856 } 01857 } 01858 01859 /* FIXME: When we properly shape Hangul remove this check */ 01860 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && analysis->pItem[i].a.eScript == Script_Hangul) 01861 analysis->pItem[i].a.fNoGlyphIndex = TRUE; 01862 01863 if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex) 01864 analysis->pItem[i].a.fNoGlyphIndex = TRUE; 01865 01866 hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], 01867 cChar, numGlyphs, &analysis->pItem[i].a, 01868 glyphs, pwLogClust, psva, &numGlyphsReturned); 01869 hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, 01870 piAdvance, pGoffset, abc); 01871 if (originalFont) 01872 SelectObject(hdc,originalFont); 01873 01874 if (dwFlags & SSA_TAB) 01875 { 01876 int tabi = 0; 01877 for (tabi = 0; tabi < cChar; tabi++) 01878 { 01879 if (pStr[analysis->pItem[i].iCharPos+tabi] == 0x0009) 01880 piAdvance[tabi] = getGivenTabWidth(analysis->glyphs[i].sc, pTabdef, analysis->pItem[i].iCharPos+tabi, tab_x); 01881 tab_x+=piAdvance[tabi]; 01882 } 01883 } 01884 01885 analysis->glyphs[i].numGlyphs = numGlyphsReturned; 01886 analysis->glyphs[i].glyphs = glyphs; 01887 analysis->glyphs[i].pwLogClust = pwLogClust; 01888 analysis->glyphs[i].piAdvance = piAdvance; 01889 analysis->glyphs[i].psva = psva; 01890 analysis->glyphs[i].pGoffset = pGoffset; 01891 analysis->glyphs[i].abc = abc; 01892 analysis->glyphs[i].iMaxPosX= -1; 01893 01894 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel; 01895 } 01896 } 01897 else 01898 { 01899 for (i = 0; i < analysis->numItems; i++) 01900 BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel; 01901 } 01902 01903 ScriptLayout(analysis->numItems, BidiLevel, NULL, analysis->logical2visual); 01904 heap_free(BidiLevel); 01905 01906 *pssa = analysis; 01907 heap_free(iString); 01908 return S_OK; 01909 01910 error: 01911 heap_free(iString); 01912 heap_free(analysis->glyphs); 01913 heap_free(analysis->logattrs); 01914 heap_free(analysis->pItem); 01915 heap_free(analysis->logical2visual); 01916 heap_free(analysis); 01917 return hr; 01918 } 01919 01920 static inline BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction) 01921 { 01922 if (pva[glyph].fClusterStart) 01923 return TRUE; 01924 if (USP10_FindGlyphInLogClust(pwLogClust, cChars, glyph) >= 0) 01925 return TRUE; 01926 01927 return FALSE; 01928 } 01929 01930 01931 static HRESULT SS_ItemOut( SCRIPT_STRING_ANALYSIS ssa, 01932 int iX, 01933 int iY, 01934 int iItem, 01935 int cStart, 01936 int cEnd, 01937 UINT uOptions, 01938 const RECT *prc, 01939 BOOL fSelected, 01940 BOOL fDisabled) 01941 { 01942 StringAnalysis *analysis; 01943 int off_x = 0; 01944 HRESULT hr; 01945 COLORREF BkColor = 0x0; 01946 COLORREF TextColor = 0x0; 01947 INT BkMode = 0; 01948 INT runStart, runEnd; 01949 INT iGlyph, cGlyphs; 01950 HFONT oldFont = 0x0; 01951 RECT crc; 01952 int i; 01953 01954 TRACE("(%p,%d,%d,%d,%d,%d, 0x%1x, %d, %d)\n", 01955 ssa, iX, iY, iItem, cStart, cEnd, uOptions, fSelected, fDisabled); 01956 01957 if (!(analysis = ssa)) return E_INVALIDARG; 01958 01959 if ((cStart >= 0 && analysis->pItem[iItem+1].iCharPos <= cStart) || 01960 (cEnd >= 0 && analysis->pItem[iItem].iCharPos >= cEnd)) 01961 return S_OK; 01962 01963 CopyRect(&crc,prc); 01964 if (fSelected) 01965 { 01966 BkMode = GetBkMode(analysis->hdc); 01967 SetBkMode( analysis->hdc, OPAQUE); 01968 BkColor = GetBkColor(analysis->hdc); 01969 SetBkColor(analysis->hdc, GetSysColor(COLOR_HIGHLIGHT)); 01970 if (!fDisabled) 01971 { 01972 TextColor = GetTextColor(analysis->hdc); 01973 SetTextColor(analysis->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); 01974 } 01975 } 01976 if (analysis->glyphs[iItem].fallbackFont) 01977 oldFont = SelectObject(analysis->hdc, analysis->glyphs[iItem].fallbackFont); 01978 01979 if (cStart >= 0 && analysis->pItem[iItem+1].iCharPos > cStart && analysis->pItem[iItem].iCharPos <= cStart) 01980 runStart = cStart - analysis->pItem[iItem].iCharPos; 01981 else 01982 runStart = 0; 01983 if (cEnd >= 0 && analysis->pItem[iItem+1].iCharPos > cEnd && analysis->pItem[iItem].iCharPos <= cEnd) 01984 runEnd = (cEnd-1) - analysis->pItem[iItem].iCharPos; 01985 else 01986 runEnd = (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos) - 1; 01987 01988 if (analysis->pItem[iItem].a.fRTL) 01989 { 01990 if (cEnd >= 0 && cEnd < analysis->pItem[iItem+1].iCharPos) 01991 ScriptStringCPtoX(ssa, cEnd, FALSE, &off_x); 01992 else 01993 ScriptStringCPtoX(ssa, analysis->pItem[iItem+1].iCharPos-1, TRUE, &off_x); 01994 crc.left = iX + off_x; 01995 } 01996 else 01997 { 01998 if (cStart >=0 && runStart) 01999 ScriptStringCPtoX(ssa, cStart, FALSE, &off_x); 02000 else 02001 ScriptStringCPtoX(ssa, analysis->pItem[iItem].iCharPos, FALSE, &off_x); 02002 crc.left = iX + off_x; 02003 } 02004 02005 if (analysis->pItem[iItem].a.fRTL) 02006 iGlyph = analysis->glyphs[iItem].pwLogClust[runEnd]; 02007 else 02008 iGlyph = analysis->glyphs[iItem].pwLogClust[runStart]; 02009 02010 if (analysis->pItem[iItem].a.fRTL) 02011 cGlyphs = analysis->glyphs[iItem].pwLogClust[runStart] - iGlyph; 02012 else 02013 cGlyphs = analysis->glyphs[iItem].pwLogClust[runEnd] - iGlyph; 02014 02015 cGlyphs++; 02016 02017 /* adjust for cluster glyphs when starting */ 02018 if (analysis->pItem[iItem].a.fRTL) 02019 i = analysis->pItem[iItem+1].iCharPos - 1; 02020 else 02021 i = analysis->pItem[iItem].iCharPos; 02022 02023 for (; i >=analysis->pItem[iItem].iCharPos && i < analysis->pItem[iItem+1].iCharPos; (analysis->pItem[iItem].a.fRTL)?i--:i++) 02024 { 02025 if (analysis->glyphs[iItem].pwLogClust[i - analysis->pItem[iItem].iCharPos] == iGlyph) 02026 { 02027 if (analysis->pItem[iItem].a.fRTL) 02028 ScriptStringCPtoX(ssa, i, TRUE, &off_x); 02029 else 02030 ScriptStringCPtoX(ssa, i, FALSE, &off_x); 02031 break; 02032 } 02033 } 02034 02035 if (cEnd < 0 || scriptInformation[analysis->pItem[iItem].a.eScript].props.fNeedsCaretInfo) 02036 { 02037 INT direction; 02038 INT clust_glyph; 02039 02040 clust_glyph = iGlyph + cGlyphs; 02041 if (analysis->pItem[iItem].a.fRTL) 02042 direction = -1; 02043 else 02044 direction = 1; 02045 02046 while(clust_glyph < analysis->glyphs[iItem].numGlyphs && 02047 !does_glyph_start_cluster(analysis->glyphs[iItem].psva, analysis->glyphs[iItem].pwLogClust, (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos), clust_glyph, direction)) 02048 { 02049 cGlyphs++; 02050 clust_glyph++; 02051 } 02052 } 02053 02054 hr = ScriptTextOut(analysis->hdc, 02055 (SCRIPT_CACHE *)&analysis->glyphs[iItem].sc, iX + off_x, 02056 iY, uOptions, &crc, &analysis->pItem[iItem].a, NULL, 0, 02057 &analysis->glyphs[iItem].glyphs[iGlyph], cGlyphs, 02058 &analysis->glyphs[iItem].piAdvance[iGlyph], NULL, 02059 &analysis->glyphs[iItem].pGoffset[iGlyph]); 02060 02061 TRACE("ScriptTextOut hr=%08x\n", hr); 02062 02063 if (fSelected) 02064 { 02065 SetBkColor(analysis->hdc, BkColor); 02066 SetBkMode( analysis->hdc, BkMode); 02067 if (!fDisabled) 02068 SetTextColor(analysis->hdc, TextColor); 02069 } 02070 if (analysis->glyphs[iItem].fallbackFont) 02071 SelectObject(analysis->hdc, oldFont); 02072 02073 return hr; 02074 } 02075 02076 /*********************************************************************** 02077 * ScriptStringOut (USP10.@) 02078 * 02079 * This function takes the output of ScriptStringAnalyse and joins the segments 02080 * of glyphs and passes the resulting string to ScriptTextOut. ScriptStringOut 02081 * only processes glyphs. 02082 * 02083 * Parameters: 02084 * ssa [I] buffer to hold the analysed string components 02085 * iX [I] X axis displacement for output 02086 * iY [I] Y axis displacement for output 02087 * uOptions [I] flags controling output processing 02088 * prc [I] rectangle coordinates 02089 * iMinSel [I] starting pos for substringing output string 02090 * iMaxSel [I] ending pos for substringing output string 02091 * fDisabled [I] controls text highlighting 02092 * 02093 * RETURNS 02094 * Success: S_OK 02095 * Failure: is the value returned by ScriptTextOut 02096 */ 02097 HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, 02098 int iX, 02099 int iY, 02100 UINT uOptions, 02101 const RECT *prc, 02102 int iMinSel, 02103 int iMaxSel, 02104 BOOL fDisabled) 02105 { 02106 StringAnalysis *analysis; 02107 int item; 02108 HRESULT hr; 02109 02110 TRACE("(%p,%d,%d,0x%1x,%p,%d,%d,%d)\n", 02111 ssa, iX, iY, uOptions, prc, iMinSel, iMaxSel, fDisabled); 02112 02113 if (!(analysis = ssa)) return E_INVALIDARG; 02114 if (!(analysis->dwFlags & SSA_GLYPHS)) return E_INVALIDARG; 02115 02116 for (item = 0; item < analysis->numItems; item++) 02117 { 02118 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], -1, -1, uOptions, prc, FALSE, fDisabled); 02119 if (FAILED(hr)) 02120 return hr; 02121 } 02122 02123 if (iMinSel < iMaxSel && (iMinSel > 0 || iMaxSel > 0)) 02124 { 02125 if (iMaxSel > 0 && iMinSel < 0) 02126 iMinSel = 0; 02127 for (item = 0; item < analysis->numItems; item++) 02128 { 02129 hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], iMinSel, iMaxSel, uOptions, prc, TRUE, fDisabled); 02130 if (FAILED(hr)) 02131 return hr; 02132 } 02133 } 02134 02135 return S_OK; 02136 } 02137 02138 /*********************************************************************** 02139 * ScriptStringCPtoX (USP10.@) 02140 * 02141 */ 02142 HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int* pX) 02143 { 02144 int item; 02145 int runningX = 0; 02146 StringAnalysis* analysis = ssa; 02147 02148 TRACE("(%p), %d, %d, (%p)\n", ssa, icp, fTrailing, pX); 02149 02150 if (!ssa || !pX) return S_FALSE; 02151 if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; 02152 02153 /* icp out of range */ 02154 if(icp < 0) 02155 { 02156 analysis->invalid = TRUE; 02157 return E_INVALIDARG; 02158 } 02159 02160 for(item=0; item<analysis->numItems; item++) 02161 { 02162 int CP, i; 02163 int offset; 02164 02165 i = analysis->logical2visual[item]; 02166 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; 02167 /* initialize max extents for uninitialized runs */ 02168 if (analysis->glyphs[i].iMaxPosX == -1) 02169 { 02170 if (analysis->pItem[i].a.fRTL) 02171 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02172 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02173 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); 02174 else 02175 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02176 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02177 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); 02178 } 02179 02180 if (icp >= analysis->pItem[i+1].iCharPos || icp < analysis->pItem[i].iCharPos) 02181 { 02182 runningX += analysis->glyphs[i].iMaxPosX; 02183 continue; 02184 } 02185 02186 icp -= analysis->pItem[i].iCharPos; 02187 ScriptCPtoX(icp, fTrailing, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02188 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02189 &analysis->pItem[i].a, &offset); 02190 runningX += offset; 02191 02192 *pX = runningX; 02193 return S_OK; 02194 } 02195 02196 /* icp out of range */ 02197 analysis->invalid = TRUE; 02198 return E_INVALIDARG; 02199 } 02200 02201 /*********************************************************************** 02202 * ScriptStringXtoCP (USP10.@) 02203 * 02204 */ 02205 HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing) 02206 { 02207 StringAnalysis* analysis = ssa; 02208 int item; 02209 02210 TRACE("(%p), %d, (%p), (%p)\n", ssa, iX, piCh, piTrailing); 02211 02212 if (!ssa || !piCh || !piTrailing) return S_FALSE; 02213 if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; 02214 02215 /* out of range */ 02216 if(iX < 0) 02217 { 02218 if (analysis->pItem[0].a.fRTL) 02219 { 02220 *piCh = 1; 02221 *piTrailing = FALSE; 02222 } 02223 else 02224 { 02225 *piCh = -1; 02226 *piTrailing = TRUE; 02227 } 02228 return S_OK; 02229 } 02230 02231 for(item=0; item<analysis->numItems; item++) 02232 { 02233 int i; 02234 int CP; 02235 02236 for (i = 0; i < analysis->numItems && analysis->logical2visual[i] != item; i++) 02237 /* nothing */; 02238 02239 CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; 02240 /* initialize max extents for uninitialized runs */ 02241 if (analysis->glyphs[i].iMaxPosX == -1) 02242 { 02243 if (analysis->pItem[i].a.fRTL) 02244 ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02245 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02246 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); 02247 else 02248 ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02249 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02250 &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); 02251 } 02252 02253 if (iX > analysis->glyphs[i].iMaxPosX) 02254 { 02255 iX -= analysis->glyphs[i].iMaxPosX; 02256 continue; 02257 } 02258 02259 ScriptXtoCP(iX, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, 02260 analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, 02261 &analysis->pItem[i].a, piCh, piTrailing); 02262 *piCh += analysis->pItem[i].iCharPos; 02263 02264 return S_OK; 02265 } 02266 02267 /* out of range */ 02268 *piCh = analysis->pItem[analysis->numItems].iCharPos; 02269 *piTrailing = FALSE; 02270 02271 return S_OK; 02272 } 02273 02274 02275 /*********************************************************************** 02276 * ScriptStringFree (USP10.@) 02277 * 02278 * Free a string analysis. 02279 * 02280 * PARAMS 02281 * pssa [I] string analysis. 02282 * 02283 * RETURNS 02284 * Success: S_OK 02285 * Failure: Non-zero HRESULT value. 02286 */ 02287 HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa) 02288 { 02289 StringAnalysis* analysis; 02290 BOOL invalid; 02291 int i; 02292 02293 TRACE("(%p)\n", pssa); 02294 02295 if (!pssa || !(analysis = *pssa)) return E_INVALIDARG; 02296 02297 invalid = analysis->invalid; 02298 02299 if (analysis->glyphs) 02300 { 02301 for (i = 0; i < analysis->numItems; i++) 02302 { 02303 heap_free(analysis->glyphs[i].glyphs); 02304 heap_free(analysis->glyphs[i].pwLogClust); 02305 heap_free(analysis->glyphs[i].piAdvance); 02306 heap_free(analysis->glyphs[i].psva); 02307 heap_free(analysis->glyphs[i].pGoffset); 02308 heap_free(analysis->glyphs[i].abc); 02309 if (analysis->glyphs[i].fallbackFont) 02310 DeleteObject(analysis->glyphs[i].fallbackFont); 02311 ScriptFreeCache((SCRIPT_CACHE *)&analysis->glyphs[i].sc); 02312 heap_free(analysis->glyphs[i].sc); 02313 } 02314 heap_free(analysis->glyphs); 02315 } 02316 02317 heap_free(analysis->pItem); 02318 heap_free(analysis->logattrs); 02319 heap_free(analysis->sz); 02320 heap_free(analysis->logical2visual); 02321 heap_free(analysis); 02322 02323 if (invalid) return E_INVALIDARG; 02324 return S_OK; 02325 } 02326 02327 static inline int get_cluster_size(const WORD *pwLogClust, int cChars, int item, 02328 int direction, int* iCluster, int *check_out) 02329 { 02330 int clust_size = 1; 02331 int check; 02332 WORD clust = pwLogClust[item]; 02333 02334 for (check = item+direction; check < cChars && check >= 0; check+=direction) 02335 { 02336 if (pwLogClust[check] == clust) 02337 { 02338 clust_size ++; 02339 if (iCluster && *iCluster == -1) 02340 *iCluster = item; 02341 } 02342 else break; 02343 } 02344 02345 if (check_out) 02346 *check_out = check; 02347 02348 return clust_size; 02349 } 02350 02351 static inline int get_glyph_cluster_advance(const int* piAdvance, const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cGlyphs, int cChars, int glyph, int direction) 02352 { 02353 int advance; 02354 int log_clust_max; 02355 02356 advance = piAdvance[glyph]; 02357 02358 if (pwLogClust[0] > pwLogClust[cChars-1]) 02359 log_clust_max = pwLogClust[0]; 02360 else 02361 log_clust_max = pwLogClust[cChars-1]; 02362 02363 if (glyph > log_clust_max) 02364 return advance; 02365 02366 for (glyph+=direction; glyph < cGlyphs && glyph >= 0; glyph +=direction) 02367 { 02368 02369 if (does_glyph_start_cluster(pva, pwLogClust, cChars, glyph, direction)) 02370 break; 02371 if (glyph > log_clust_max) 02372 break; 02373 advance += piAdvance[glyph]; 02374 } 02375 02376 return advance; 02377 } 02378 02379 /*********************************************************************** 02380 * ScriptCPtoX (USP10.@) 02381 * 02382 */ 02383 HRESULT WINAPI ScriptCPtoX(int iCP, 02384 BOOL fTrailing, 02385 int cChars, 02386 int cGlyphs, 02387 const WORD *pwLogClust, 02388 const SCRIPT_VISATTR *psva, 02389 const int *piAdvance, 02390 const SCRIPT_ANALYSIS *psa, 02391 int *piX) 02392 { 02393 int item; 02394 float iPosX; 02395 int iSpecial = -1; 02396 int iCluster = -1; 02397 int clust_size = 1; 02398 float special_size = 0.0; 02399 int iMaxPos = 0; 02400 int advance = 0; 02401 BOOL rtl = FALSE; 02402 02403 TRACE("(%d,%d,%d,%d,%p,%p,%p,%p,%p)\n", 02404 iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, 02405 psa, piX); 02406 02407 if (psa->fRTL && ! psa->fLogicalOrder) 02408 rtl = TRUE; 02409 02410 if (fTrailing) 02411 iCP++; 02412 02413 if (rtl) 02414 { 02415 int max_clust = pwLogClust[0]; 02416 02417 for (item=0; item < cGlyphs; item++) 02418 if (pwLogClust[item] > max_clust) 02419 { 02420 ERR("We do not handle non reversed clusters properly\n"); 02421 break; 02422 } 02423 02424 iMaxPos = 0; 02425 for (item = max_clust; item >=0; item --) 02426 iMaxPos += piAdvance[item]; 02427 } 02428 02429 iPosX = 0.0; 02430 for (item=0; item < iCP && item < cChars; item++) 02431 { 02432 if (iSpecial == -1 && (iCluster == -1 || (iCluster != -1 && iCluster+clust_size <= item))) 02433 { 02434 int check; 02435 int clust = pwLogClust[item]; 02436 02437 iCluster = -1; 02438 clust_size = get_cluster_size(pwLogClust, cChars, item, 1, &iCluster, 02439 &check); 02440 02441 advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, 1); 02442 02443 if (check >= cChars && !iMaxPos) 02444 { 02445 for (check = clust; check < cChars; check++) 02446 special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, 1); 02447 iSpecial = item; 02448 special_size /= (cChars - item); 02449 iPosX += special_size; 02450 } 02451 else 02452 { 02453 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) 02454 { 02455 clust_size --; 02456 if (clust_size == 0) 02457 iPosX += advance; 02458 } 02459 else 02460 iPosX += advance / (float)clust_size; 02461 } 02462 } 02463 else if (iSpecial != -1) 02464 iPosX += special_size; 02465 else /* (iCluster != -1) */ 02466 { 02467 int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], 1); 02468 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) 02469 { 02470 clust_size --; 02471 if (clust_size == 0) 02472 iPosX += adv; 02473 } 02474 else 02475 iPosX += adv / (float)clust_size; 02476 } 02477 } 02478 02479 if (iMaxPos > 0) 02480 { 02481 iPosX = iMaxPos - iPosX; 02482 if (iPosX < 0) 02483 iPosX = 0; 02484 } 02485 02486 *piX = iPosX; 02487 TRACE("*piX=%d\n", *piX); 02488 return S_OK; 02489 } 02490 02491 /*********************************************************************** 02492 * ScriptXtoCP (USP10.@) 02493 * 02494 */ 02495 HRESULT WINAPI ScriptXtoCP(int iX, 02496 int cChars, 02497 int cGlyphs, 02498 const WORD *pwLogClust, 02499 const SCRIPT_VISATTR *psva, 02500 const int *piAdvance, 02501 const SCRIPT_ANALYSIS *psa, 02502 int *piCP, 02503 int *piTrailing) 02504 { 02505 int item; 02506 float iPosX; 02507 float iLastPosX; 02508 int iSpecial = -1; 02509 int iCluster = -1; 02510 int clust_size = 1; 02511 int cjump = 0; 02512 int advance; 02513 float special_size = 0.0; 02514 int direction = 1; 02515 02516 TRACE("(%d,%d,%d,%p,%p,%p,%p,%p,%p)\n", 02517 iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, 02518 psa, piCP, piTrailing); 02519 02520 if (psa->fRTL && ! psa->fLogicalOrder) 02521 direction = -1; 02522 02523 if (direction<0) 02524 { 02525 int max_clust = pwLogClust[0]; 02526 02527 if (iX < 0) 02528 { 02529 *piCP = cChars; 02530 *piTrailing = 0; 02531 return S_OK; 02532 } 02533 02534 for (item=0; item < cChars; item++) 02535 if (pwLogClust[item] > max_clust) 02536 { 02537 ERR("We do not handle non reversed clusters properly\n"); 02538 break; 02539 } 02540 } 02541 02542 if (iX < 0) 02543 { 02544 *piCP = -1; 02545 *piTrailing = 1; 02546 return S_OK; 02547 } 02548 02549 iPosX = iLastPosX = 0; 02550 if (direction > 0) 02551 item = 0; 02552 else 02553 item = cChars - 1; 02554 for (; iPosX <= iX && item < cChars && item >= 0; item+=direction) 02555 { 02556 iLastPosX = iPosX; 02557 if (iSpecial == -1 && 02558 (iCluster == -1 || 02559 (iCluster != -1 && 02560 ((direction > 0 && iCluster+clust_size <= item) || 02561 (direction < 0 && iCluster-clust_size >= item)) 02562 ) 02563 ) 02564 ) 02565 { 02566 int check; 02567 int clust = pwLogClust[item]; 02568 02569 iCluster = -1; 02570 cjump = 0; 02571 clust_size = get_cluster_size(pwLogClust, cChars, item, direction, 02572 &iCluster, &check); 02573 advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, direction); 02574 02575 if (check >= cChars && direction > 0) 02576 { 02577 for (check = clust; check < cChars; check++) 02578 special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, direction); 02579 iSpecial = item; 02580 special_size /= (cChars - item); 02581 iPosX += special_size; 02582 } 02583 else 02584 { 02585 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) 02586 { 02587 if (!cjump) 02588 iPosX += advance; 02589 cjump++; 02590 } 02591 else 02592 iPosX += advance / (float)clust_size; 02593 } 02594 } 02595 else if (iSpecial != -1) 02596 iPosX += special_size; 02597 else /* (iCluster != -1) */ 02598 { 02599 int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], direction); 02600 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) 02601 { 02602 if (!cjump) 02603 iPosX += adv; 02604 cjump++; 02605 } 02606 else 02607 iPosX += adv / (float)clust_size; 02608 } 02609 } 02610 02611 if (direction > 0) 02612 { 02613 if (iPosX > iX) 02614 item--; 02615 if (item < cChars && ((iPosX - iLastPosX) / 2.0) + iX >= iPosX) 02616 { 02617 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo && clust_size > 1) 02618 item+=(clust_size-1); 02619 *piTrailing = 1; 02620 } 02621 else 02622 *piTrailing = 0; 02623 } 02624 else 02625 { 02626 if (iX == iLastPosX) 02627 item++; 02628 if (iX >= iLastPosX && iX <= iPosX) 02629 item++; 02630 02631 if (iLastPosX == iX) 02632 *piTrailing = 0; 02633 else if (item < 0 || ((iLastPosX - iPosX) / 2.0) + iX <= iLastPosX) 02634 { 02635 if (scriptInformation[psa->eScript].props.fNeedsCaretInfo && clust_size > 1) 02636 item-=(clust_size-1); 02637 *piTrailing = 1; 02638 } 02639 else 02640 *piTrailing = 0; 02641 } 02642 02643 *piCP = item; 02644 02645 TRACE("*piCP=%d\n", *piCP); 02646 TRACE("*piTrailing=%d\n", *piTrailing); 02647 return S_OK; 02648 } 02649 02650 /*********************************************************************** 02651 * ScriptBreak (USP10.@) 02652 * 02653 * Retrieve line break information. 02654 * 02655 * PARAMS 02656 * chars [I] Array of characters. 02657 * sa [I] String analysis. 02658 * la [I] Array of logical attribute structures. 02659 * 02660 * RETURNS 02661 * Success: S_OK 02662 * Failure: S_FALSE 02663 */ 02664 HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) 02665 { 02666 TRACE("(%s, %d, %p, %p)\n", debugstr_wn(chars, count), count, sa, la); 02667 02668 if (count < 0 || !la) return E_INVALIDARG; 02669 if (count == 0) return E_FAIL; 02670 02671 BREAK_line(chars, count, sa, la); 02672 02673 return S_OK; 02674 } 02675 02676 /*********************************************************************** 02677 * ScriptIsComplex (USP10.@) 02678 * 02679 * Determine if a string is complex. 02680 * 02681 * PARAMS 02682 * chars [I] Array of characters to test. 02683 * len [I] Length in characters. 02684 * flag [I] Flag. 02685 * 02686 * RETURNS 02687 * Success: S_OK 02688 * Failure: S_FALSE 02689 * 02690 */ 02691 HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag) 02692 { 02693 int i; 02694 INT consumed = 0; 02695 02696 TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag); 02697 02698 for (i = 0; i < len; i+=consumed) 02699 { 02700 int script; 02701 if (i >= len) 02702 break; 02703 02704 if ((flag & SIC_ASCIIDIGIT) && chars[i] >= 0x30 && chars[i] <= 0x39) 02705 return S_OK; 02706 02707 script = get_char_script(chars,i,len, &consumed); 02708 if ((scriptInformation[script].props.fComplex && (flag & SIC_COMPLEX))|| 02709 (!scriptInformation[script].props.fComplex && (flag & SIC_NEUTRAL))) 02710 return S_OK; 02711 } 02712 return S_FALSE; 02713 } 02714 02715 /*********************************************************************** 02716 * ScriptShapeOpenType (USP10.@) 02717 * 02718 * Produce glyphs and visual attributes for a run. 02719 * 02720 * PARAMS 02721 * hdc [I] Device context. 02722 * psc [I/O] Opaque pointer to a script cache. 02723 * psa [I/O] Script analysis. 02724 * tagScript [I] The OpenType tag for the Script 02725 * tagLangSys [I] The OpenType tag for the Language 02726 * rcRangeChars[I] Array of Character counts in each range 02727 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures 02728 * cRanges [I] Count of ranges 02729 * pwcChars [I] Array of characters specifying the run. 02730 * cChars [I] Number of characters in pwcChars. 02731 * cMaxGlyphs [I] Length of pwOutGlyphs. 02732 * pwLogClust [O] Array of logical cluster info. 02733 * pCharProps [O] Array of character property values 02734 * pwOutGlyphs [O] Array of glyphs. 02735 * pOutGlyphProps [O] Array of attributes for the retrieved glyphs 02736 * pcGlyphs [O] Number of glyphs returned. 02737 * 02738 * RETURNS 02739 * Success: S_OK 02740 * Failure: Non-zero HRESULT value. 02741 */ 02742 HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc, 02743 SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, 02744 OPENTYPE_TAG tagLangSys, int *rcRangeChars, 02745 TEXTRANGE_PROPERTIES **rpRangeProperties, 02746 int cRanges, const WCHAR *pwcChars, int cChars, 02747 int cMaxGlyphs, WORD *pwLogClust, 02748 SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs, 02749 SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs) 02750 { 02751 HRESULT hr; 02752 unsigned int i,g; 02753 BOOL rtl; 02754 int cluster; 02755 02756 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %d, %d, %p, %p, %p, %p, %p )\n", 02757 hdc, psc, psa, 02758 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4), 02759 rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars), 02760 cChars, cMaxGlyphs, pwLogClust, pCharProps, pwOutGlyphs, pOutGlyphProps, pcGlyphs); 02761 02762 if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL, 02763 psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder, psa->fNoGlyphIndex); 02764 02765 if (!pOutGlyphProps || !pcGlyphs || !pCharProps) return E_INVALIDARG; 02766 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY; 02767 02768 if (cRanges) 02769 FIXME("Ranges not supported yet\n"); 02770 02771 rtl = (psa && !psa->fLogicalOrder && psa->fRTL); 02772 02773 *pcGlyphs = cChars; 02774 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 02775 if (!pwLogClust) return E_FAIL; 02776 02777 ((ScriptCache *)*psc)->userScript = tagScript; 02778 ((ScriptCache *)*psc)->userLang = tagLangSys; 02779 02780 /* set fNoGlyphIndex non truetype/opentype fonts */ 02781 if (psa && !psa->fNoGlyphIndex && !((ScriptCache *)*psc)->sfnt) 02782 psa->fNoGlyphIndex = TRUE; 02783 02784 /* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */ 02785 for (i = 0; i < cChars; i++) 02786 { 02787 int idx = i; 02788 if (rtl) idx = cChars - 1 - i; 02789 /* FIXME: set to better values */ 02790 pOutGlyphProps[i].sva.uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; 02791 pOutGlyphProps[i].sva.fClusterStart = 1; 02792 pOutGlyphProps[i].sva.fDiacritic = 0; 02793 pOutGlyphProps[i].sva.fZeroWidth = 0; 02794 pOutGlyphProps[i].sva.fReserved = 0; 02795 pOutGlyphProps[i].sva.fShapeReserved = 0; 02796 02797 /* FIXME: have the shaping engine set this */ 02798 pCharProps[i].fCanGlyphAlone = 0; 02799 02800 pwLogClust[i] = idx; 02801 } 02802 02803 if (psa && !psa->fNoGlyphIndex) 02804 { 02805 WCHAR *rChars; 02806 if ((hr = SHAPE_CheckFontForRequiredFeatures(hdc, (ScriptCache *)*psc, psa)) != S_OK) return hr; 02807 02808 rChars = heap_alloc(sizeof(WCHAR) * cChars); 02809 if (!rChars) return E_OUTOFMEMORY; 02810 for (i = 0, g = 0, cluster = 0; i < cChars; i++) 02811 { 02812 int idx = i; 02813 DWORD chInput; 02814 02815 if (rtl) idx = cChars - 1 - i; 02816 if (!cluster) 02817 { 02818 chInput = decode_surrogate_pair(pwcChars, idx, cChars); 02819 if (!chInput) 02820 { 02821 if (psa->fRTL) 02822 chInput = mirror_char(pwcChars[idx]); 02823 else 02824 chInput = pwcChars[idx]; 02825 /* special case for tabs */ 02826 if (chInput == 0x0009) 02827 chInput = 0x0020; 02828 rChars[i] = chInput; 02829 } 02830 else 02831 { 02832 rChars[i] = pwcChars[idx]; 02833 rChars[i+1] = pwcChars[(rtl)?idx-1:idx+1]; 02834 cluster = 1; 02835 } 02836 if (!(pwOutGlyphs[g] = get_cache_glyph(psc, chInput))) 02837 { 02838 WORD glyph; 02839 if (!hdc) 02840 { 02841 heap_free(rChars); 02842 return E_PENDING; 02843 } 02844 if (OpenType_CMAP_GetGlyphIndex(hdc, (ScriptCache *)*psc, chInput, &glyph, 0) == GDI_ERROR) 02845 { 02846 heap_free(rChars); 02847 return S_FALSE; 02848 } 02849 pwOutGlyphs[g] = set_cache_glyph(psc, chInput, glyph); 02850 } 02851 g++; 02852 } 02853 else 02854 { 02855 int k; 02856 cluster--; 02857 pwLogClust[idx] = (rtl)?pwLogClust[idx+1]:pwLogClust[idx-1]; 02858 for (k = (rtl)?idx-1:idx+1; k >= 0 && k < cChars; (rtl)?k--:k++) 02859 pwLogClust[k]--; 02860 } 02861 } 02862 *pcGlyphs = g; 02863 02864 SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); 02865 SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); 02866 SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs, *pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps); 02867 heap_free(rChars); 02868 } 02869 else 02870 { 02871 TRACE("no glyph translation\n"); 02872 for (i = 0; i < cChars; i++) 02873 { 02874 int idx = i; 02875 /* No mirroring done here */ 02876 if (rtl) idx = cChars - 1 - i; 02877 pwOutGlyphs[i] = pwcChars[idx]; 02878 } 02879 } 02880 02881 return S_OK; 02882 } 02883 02884 02885 /*********************************************************************** 02886 * ScriptShape (USP10.@) 02887 * 02888 * Produce glyphs and visual attributes for a run. 02889 * 02890 * PARAMS 02891 * hdc [I] Device context. 02892 * psc [I/O] Opaque pointer to a script cache. 02893 * pwcChars [I] Array of characters specifying the run. 02894 * cChars [I] Number of characters in pwcChars. 02895 * cMaxGlyphs [I] Length of pwOutGlyphs. 02896 * psa [I/O] Script analysis. 02897 * pwOutGlyphs [O] Array of glyphs. 02898 * pwLogClust [O] Array of logical cluster info. 02899 * psva [O] Array of visual attributes. 02900 * pcGlyphs [O] Number of glyphs returned. 02901 * 02902 * RETURNS 02903 * Success: S_OK 02904 * Failure: Non-zero HRESULT value. 02905 */ 02906 HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, 02907 int cChars, int cMaxGlyphs, 02908 SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, 02909 SCRIPT_VISATTR *psva, int *pcGlyphs) 02910 { 02911 HRESULT hr; 02912 int i; 02913 SCRIPT_CHARPROP *charProps; 02914 SCRIPT_GLYPHPROP *glyphProps; 02915 02916 if (!psva || !pcGlyphs) return E_INVALIDARG; 02917 if (cChars > cMaxGlyphs) return E_OUTOFMEMORY; 02918 02919 charProps = heap_alloc_zero(sizeof(SCRIPT_CHARPROP)*cChars); 02920 if (!charProps) return E_OUTOFMEMORY; 02921 glyphProps = heap_alloc_zero(sizeof(SCRIPT_GLYPHPROP)*cMaxGlyphs); 02922 if (!glyphProps) 02923 { 02924 heap_free(charProps); 02925 return E_OUTOFMEMORY; 02926 } 02927 02928 hr = ScriptShapeOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, pwcChars, cChars, cMaxGlyphs, pwLogClust, charProps, pwOutGlyphs, glyphProps, pcGlyphs); 02929 02930 if (SUCCEEDED(hr)) 02931 { 02932 for (i = 0; i < *pcGlyphs; i++) 02933 psva[i] = glyphProps[i].sva; 02934 } 02935 02936 heap_free(charProps); 02937 heap_free(glyphProps); 02938 02939 return hr; 02940 } 02941 02942 /*********************************************************************** 02943 * ScriptPlaceOpenType (USP10.@) 02944 * 02945 * Produce advance widths for a run. 02946 * 02947 * PARAMS 02948 * hdc [I] Device context. 02949 * psc [I/O] Opaque pointer to a script cache. 02950 * psa [I/O] String analysis. 02951 * tagScript [I] The OpenType tag for the Script 02952 * tagLangSys [I] The OpenType tag for the Language 02953 * rcRangeChars[I] Array of Character counts in each range 02954 * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures 02955 * cRanges [I] Count of ranges 02956 * pwcChars [I] Array of characters specifying the run. 02957 * pwLogClust [I] Array of logical cluster info 02958 * pCharProps [I] Array of character property values 02959 * cChars [I] Number of characters in pwcChars. 02960 * pwGlyphs [I] Array of glyphs. 02961 * pGlyphProps [I] Array of attributes for the retrieved glyphs 02962 * cGlyphs [I] Count of Glyphs 02963 * piAdvance [O] Array of advance widths. 02964 * pGoffset [O] Glyph offsets. 02965 * pABC [O] Combined ABC width. 02966 * 02967 * RETURNS 02968 * Success: S_OK 02969 * Failure: Non-zero HRESULT value. 02970 */ 02971 02972 HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, 02973 OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, 02974 int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, 02975 int cRanges, const WCHAR *pwcChars, WORD *pwLogClust, 02976 SCRIPT_CHARPROP *pCharProps, int cChars, 02977 const WORD *pwGlyphs, const SCRIPT_GLYPHPROP *pGlyphProps, 02978 int cGlyphs, int *piAdvance, 02979 GOFFSET *pGoffset, ABC *pABC 02980 ) 02981 { 02982 HRESULT hr; 02983 int i; 02984 02985 TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %p, %p, %d, %p, %p, %d, %p %p %p)\n", 02986 hdc, psc, psa, 02987 debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4), 02988 rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars), 02989 pwLogClust, pCharProps, cChars, pwGlyphs, pGlyphProps, cGlyphs, piAdvance, 02990 pGoffset, pABC); 02991 02992 if (!pGlyphProps) return E_INVALIDARG; 02993 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 02994 if (!pGoffset) return E_FAIL; 02995 02996 if (cRanges) 02997 FIXME("Ranges not supported yet\n"); 02998 02999 ((ScriptCache *)*psc)->userScript = tagScript; 03000 ((ScriptCache *)*psc)->userLang = tagLangSys; 03001 03002 if (pABC) memset(pABC, 0, sizeof(ABC)); 03003 for (i = 0; i < cGlyphs; i++) 03004 { 03005 ABC abc; 03006 if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc)) 03007 { 03008 if (!hdc) return E_PENDING; 03009 if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) 03010 { 03011 if (!GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc)) return S_FALSE; 03012 } 03013 else 03014 { 03015 INT width; 03016 if (!GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return S_FALSE; 03017 abc.abcB = width; 03018 abc.abcA = abc.abcC = 0; 03019 } 03020 set_cache_glyph_widths(psc, pwGlyphs[i], &abc); 03021 } 03022 if (pABC) 03023 { 03024 pABC->abcA += abc.abcA; 03025 pABC->abcB += abc.abcB; 03026 pABC->abcC += abc.abcC; 03027 } 03028 /* FIXME: set to more reasonable values */ 03029 pGoffset[i].du = pGoffset[i].dv = 0; 03030 if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC; 03031 } 03032 03033 if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n", pABC->abcA, pABC->abcB, pABC->abcC); 03034 return S_OK; 03035 } 03036 03037 /*********************************************************************** 03038 * ScriptPlace (USP10.@) 03039 * 03040 * Produce advance widths for a run. 03041 * 03042 * PARAMS 03043 * hdc [I] Device context. 03044 * psc [I/O] Opaque pointer to a script cache. 03045 * pwGlyphs [I] Array of glyphs. 03046 * cGlyphs [I] Number of glyphs in pwGlyphs. 03047 * psva [I] Array of visual attributes. 03048 * psa [I/O] String analysis. 03049 * piAdvance [O] Array of advance widths. 03050 * pGoffset [O] Glyph offsets. 03051 * pABC [O] Combined ABC width. 03052 * 03053 * RETURNS 03054 * Success: S_OK 03055 * Failure: Non-zero HRESULT value. 03056 */ 03057 HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, 03058 int cGlyphs, const SCRIPT_VISATTR *psva, 03059 SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC ) 03060 { 03061 HRESULT hr; 03062 SCRIPT_GLYPHPROP *glyphProps; 03063 int i; 03064 03065 TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs, cGlyphs, psva, psa, 03066 piAdvance, pGoffset, pABC); 03067 03068 if (!psva) return E_INVALIDARG; 03069 if (!pGoffset) return E_FAIL; 03070 03071 glyphProps = heap_alloc(sizeof(SCRIPT_GLYPHPROP)*cGlyphs); 03072 if (!glyphProps) return E_OUTOFMEMORY; 03073 03074 for (i = 0; i < cGlyphs; i++) 03075 glyphProps[i].sva = psva[i]; 03076 03077 hr = ScriptPlaceOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, NULL, NULL, NULL, 0, pwGlyphs, glyphProps, cGlyphs, piAdvance, pGoffset, pABC); 03078 03079 heap_free(glyphProps); 03080 03081 return hr; 03082 } 03083 03084 /*********************************************************************** 03085 * ScriptGetCMap (USP10.@) 03086 * 03087 * Retrieve glyph indices. 03088 * 03089 * PARAMS 03090 * hdc [I] Device context. 03091 * psc [I/O] Opaque pointer to a script cache. 03092 * pwcInChars [I] Array of Unicode characters. 03093 * cChars [I] Number of characters in pwcInChars. 03094 * dwFlags [I] Flags. 03095 * pwOutGlyphs [O] Buffer to receive the array of glyph indices. 03096 * 03097 * RETURNS 03098 * Success: S_OK 03099 * Failure: Non-zero HRESULT value. 03100 */ 03101 HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars, 03102 int cChars, DWORD dwFlags, WORD *pwOutGlyphs) 03103 { 03104 HRESULT hr; 03105 int i; 03106 03107 TRACE("(%p,%p,%s,%d,0x%x,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars), 03108 cChars, dwFlags, pwOutGlyphs); 03109 03110 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03111 03112 hr = S_OK; 03113 03114 if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE)) 03115 { 03116 for (i = 0; i < cChars; i++) 03117 { 03118 WCHAR inChar; 03119 if (dwFlags == SGCM_RTL) 03120 inChar = mirror_char(pwcInChars[i]); 03121 else 03122 inChar = pwcInChars[i]; 03123 if (!(pwOutGlyphs[i] = get_cache_glyph(psc, inChar))) 03124 { 03125 WORD glyph; 03126 if (!hdc) return E_PENDING; 03127 if (GetGlyphIndicesW(hdc, &inChar, 1, &glyph, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE; 03128 if (glyph == 0xffff) 03129 { 03130 hr = S_FALSE; 03131 glyph = 0x0; 03132 } 03133 pwOutGlyphs[i] = set_cache_glyph(psc, inChar, glyph); 03134 } 03135 } 03136 } 03137 else 03138 { 03139 TRACE("no glyph translation\n"); 03140 for (i = 0; i < cChars; i++) 03141 { 03142 WCHAR inChar; 03143 if (dwFlags == SGCM_RTL) 03144 inChar = mirror_char(pwcInChars[i]); 03145 else 03146 inChar = pwcInChars[i]; 03147 pwOutGlyphs[i] = inChar; 03148 } 03149 } 03150 return hr; 03151 } 03152 03153 /*********************************************************************** 03154 * ScriptTextOut (USP10.@) 03155 * 03156 */ 03157 HRESULT WINAPI ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions, 03158 const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved, 03159 int iReserved, const WORD *pwGlyphs, int cGlyphs, const int *piAdvance, 03160 const int *piJustify, const GOFFSET *pGoffset) 03161 { 03162 HRESULT hr = S_OK; 03163 03164 TRACE("(%p, %p, %d, %d, %04x, %p, %p, %p, %d, %p, %d, %p, %p, %p)\n", 03165 hdc, psc, x, y, fuOptions, lprc, psa, pwcReserved, iReserved, pwGlyphs, cGlyphs, 03166 piAdvance, piJustify, pGoffset); 03167 03168 if (!hdc || !psc) return E_INVALIDARG; 03169 if (!piAdvance || !psa || !pwGlyphs) return E_INVALIDARG; 03170 03171 fuOptions &= ETO_CLIPPED + ETO_OPAQUE; 03172 fuOptions |= ETO_IGNORELANGUAGE; 03173 if (!psa->fNoGlyphIndex) /* Have Glyphs? */ 03174 fuOptions |= ETO_GLYPH_INDEX; /* Say don't do translation to glyph */ 03175 03176 if (psa->fRTL && psa->fLogicalOrder) 03177 { 03178 int i; 03179 WORD *rtlGlyphs; 03180 03181 rtlGlyphs = heap_alloc(cGlyphs * sizeof(WORD)); 03182 if (!rtlGlyphs) 03183 return E_OUTOFMEMORY; 03184 03185 for (i = 0; i < cGlyphs; i++) 03186 rtlGlyphs[i] = pwGlyphs[cGlyphs-1-i]; 03187 03188 if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, rtlGlyphs, cGlyphs, NULL)) 03189 hr = S_FALSE; 03190 heap_free(rtlGlyphs); 03191 } 03192 else 03193 if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, pwGlyphs, cGlyphs, NULL)) 03194 hr = S_FALSE; 03195 03196 return hr; 03197 } 03198 03199 /*********************************************************************** 03200 * ScriptCacheGetHeight (USP10.@) 03201 * 03202 * Retrieve the height of the font in the cache. 03203 * 03204 * PARAMS 03205 * hdc [I] Device context. 03206 * psc [I/O] Opaque pointer to a script cache. 03207 * height [O] Receives font height. 03208 * 03209 * RETURNS 03210 * Success: S_OK 03211 * Failure: Non-zero HRESULT value. 03212 */ 03213 HRESULT WINAPI ScriptCacheGetHeight(HDC hdc, SCRIPT_CACHE *psc, LONG *height) 03214 { 03215 HRESULT hr; 03216 03217 TRACE("(%p, %p, %p)\n", hdc, psc, height); 03218 03219 if (!height) return E_INVALIDARG; 03220 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03221 03222 *height = get_cache_height(psc); 03223 return S_OK; 03224 } 03225 03226 /*********************************************************************** 03227 * ScriptGetGlyphABCWidth (USP10.@) 03228 * 03229 * Retrieve the width of a glyph. 03230 * 03231 * PARAMS 03232 * hdc [I] Device context. 03233 * psc [I/O] Opaque pointer to a script cache. 03234 * glyph [I] Glyph to retrieve the width for. 03235 * abc [O] ABC widths of the glyph. 03236 * 03237 * RETURNS 03238 * Success: S_OK 03239 * Failure: Non-zero HRESULT value. 03240 */ 03241 HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, ABC *abc) 03242 { 03243 HRESULT hr; 03244 03245 TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc); 03246 03247 if (!abc) return E_INVALIDARG; 03248 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03249 03250 if (!get_cache_glyph_widths(psc, glyph, abc)) 03251 { 03252 if (!hdc) return E_PENDING; 03253 if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE)) 03254 { 03255 if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE; 03256 } 03257 else 03258 { 03259 INT width; 03260 if (!GetCharWidth32W(hdc, glyph, glyph, &width)) return S_FALSE; 03261 abc->abcB = width; 03262 abc->abcA = abc->abcC = 0; 03263 } 03264 set_cache_glyph_widths(psc, glyph, abc); 03265 } 03266 return S_OK; 03267 } 03268 03269 /*********************************************************************** 03270 * ScriptLayout (USP10.@) 03271 * 03272 * Map embedding levels to visual and/or logical order. 03273 * 03274 * PARAMS 03275 * runs [I] Size of level array. 03276 * level [I] Array of embedding levels. 03277 * vistolog [O] Map of embedding levels from visual to logical order. 03278 * logtovis [O] Map of embedding levels from logical to visual order. 03279 * 03280 * RETURNS 03281 * Success: S_OK 03282 * Failure: Non-zero HRESULT value. 03283 * 03284 * BUGS 03285 * This stub works correctly for any sequence of a single 03286 * embedding level but not for sequences of different 03287 * embedding levels, i.e. mixtures of RTL and LTR scripts. 03288 */ 03289 HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis) 03290 { 03291 int* indexs; 03292 int ich; 03293 03294 TRACE("(%d, %p, %p, %p)\n", runs, level, vistolog, logtovis); 03295 03296 if (!level || (!vistolog && !logtovis)) 03297 return E_INVALIDARG; 03298 03299 indexs = heap_alloc(sizeof(int) * runs); 03300 if (!indexs) 03301 return E_OUTOFMEMORY; 03302 03303 03304 if (vistolog) 03305 { 03306 for( ich = 0; ich < runs; ich++) 03307 indexs[ich] = ich; 03308 03309 ich = 0; 03310 while (ich < runs) 03311 ich += BIDI_ReorderV2lLevel(0, indexs+ich, level+ich, runs - ich, FALSE); 03312 for (ich = 0; ich < runs; ich++) 03313 vistolog[ich] = indexs[ich]; 03314 } 03315 03316 03317 if (logtovis) 03318 { 03319 for( ich = 0; ich < runs; ich++) 03320 indexs[ich] = ich; 03321 03322 ich = 0; 03323 while (ich < runs) 03324 ich += BIDI_ReorderL2vLevel(0, indexs+ich, level+ich, runs - ich, FALSE); 03325 for (ich = 0; ich < runs; ich++) 03326 logtovis[ich] = indexs[ich]; 03327 } 03328 heap_free(indexs); 03329 03330 return S_OK; 03331 } 03332 03333 /*********************************************************************** 03334 * ScriptStringGetLogicalWidths (USP10.@) 03335 * 03336 * Returns logical widths from a string analysis. 03337 * 03338 * PARAMS 03339 * ssa [I] string analysis. 03340 * piDx [O] logical widths returned. 03341 * 03342 * RETURNS 03343 * Success: S_OK 03344 * Failure: a non-zero HRESULT. 03345 */ 03346 HRESULT WINAPI ScriptStringGetLogicalWidths(SCRIPT_STRING_ANALYSIS ssa, int *piDx) 03347 { 03348 int i, j, next = 0; 03349 StringAnalysis *analysis = ssa; 03350 03351 TRACE("%p, %p\n", ssa, piDx); 03352 03353 if (!analysis) return S_FALSE; 03354 if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; 03355 03356 for (i = 0; i < analysis->numItems; i++) 03357 { 03358 int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; 03359 int direction = 1; 03360 03361 if (analysis->pItem[i].a.fRTL && ! analysis->pItem[i].a.fLogicalOrder) 03362 direction = -1; 03363 03364 for (j = 0; j < cChar; j++) 03365 { 03366 int k; 03367 int glyph = analysis->glyphs[i].pwLogClust[j]; 03368 int clust_size = get_cluster_size(analysis->glyphs[i].pwLogClust, 03369 cChar, j, direction, NULL, NULL); 03370 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); 03371 03372 for (k = 0; k < clust_size; k++) 03373 { 03374 piDx[next] = advance / clust_size; 03375 next++; 03376 if (k) j++; 03377 } 03378 } 03379 } 03380 return S_OK; 03381 } 03382 03383 /*********************************************************************** 03384 * ScriptStringValidate (USP10.@) 03385 * 03386 * Validate a string analysis. 03387 * 03388 * PARAMS 03389 * ssa [I] string analysis. 03390 * 03391 * RETURNS 03392 * Success: S_OK 03393 * Failure: S_FALSE if invalid sequences are found 03394 * or a non-zero HRESULT if it fails. 03395 */ 03396 HRESULT WINAPI ScriptStringValidate(SCRIPT_STRING_ANALYSIS ssa) 03397 { 03398 StringAnalysis *analysis = ssa; 03399 03400 TRACE("(%p)\n", ssa); 03401 03402 if (!analysis) return E_INVALIDARG; 03403 return (analysis->invalid) ? S_FALSE : S_OK; 03404 } 03405 03406 /*********************************************************************** 03407 * ScriptString_pSize (USP10.@) 03408 * 03409 * Retrieve width and height of an analysed string. 03410 * 03411 * PARAMS 03412 * ssa [I] string analysis. 03413 * 03414 * RETURNS 03415 * Success: Pointer to a SIZE structure. 03416 * Failure: NULL 03417 */ 03418 const SIZE * WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa) 03419 { 03420 int i, j; 03421 StringAnalysis *analysis = ssa; 03422 03423 TRACE("(%p)\n", ssa); 03424 03425 if (!analysis) return NULL; 03426 if (!(analysis->dwFlags & SSA_GLYPHS)) return NULL; 03427 03428 if (!analysis->sz) 03429 { 03430 if (!(analysis->sz = heap_alloc(sizeof(SIZE)))) return NULL; 03431 analysis->sz->cy = analysis->glyphs[0].sc->tm.tmHeight; 03432 03433 analysis->sz->cx = 0; 03434 for (i = 0; i < analysis->numItems; i++) 03435 { 03436 if (analysis->glyphs[i].sc->tm.tmHeight > analysis->sz->cy) 03437 analysis->sz->cy = analysis->glyphs[i].sc->tm.tmHeight; 03438 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++) 03439 analysis->sz->cx += analysis->glyphs[i].piAdvance[j]; 03440 } 03441 } 03442 return analysis->sz; 03443 } 03444 03445 /*********************************************************************** 03446 * ScriptString_pLogAttr (USP10.@) 03447 * 03448 * Retrieve logical attributes of an analysed string. 03449 * 03450 * PARAMS 03451 * ssa [I] string analysis. 03452 * 03453 * RETURNS 03454 * Success: Pointer to an array of SCRIPT_LOGATTR structures. 03455 * Failure: NULL 03456 */ 03457 const SCRIPT_LOGATTR * WINAPI ScriptString_pLogAttr(SCRIPT_STRING_ANALYSIS ssa) 03458 { 03459 StringAnalysis *analysis = ssa; 03460 03461 TRACE("(%p)\n", ssa); 03462 03463 if (!analysis) return NULL; 03464 if (!(analysis->dwFlags & SSA_BREAK)) return NULL; 03465 return analysis->logattrs; 03466 } 03467 03468 /*********************************************************************** 03469 * ScriptString_pcOutChars (USP10.@) 03470 * 03471 * Retrieve the length of a string after clipping. 03472 * 03473 * PARAMS 03474 * ssa [I] String analysis. 03475 * 03476 * RETURNS 03477 * Success: Pointer to the length. 03478 * Failure: NULL 03479 */ 03480 const int * WINAPI ScriptString_pcOutChars(SCRIPT_STRING_ANALYSIS ssa) 03481 { 03482 StringAnalysis *analysis = ssa; 03483 03484 TRACE("(%p)\n", ssa); 03485 03486 if (!analysis) return NULL; 03487 return &analysis->clip_len; 03488 } 03489 03490 /*********************************************************************** 03491 * ScriptStringGetOrder (USP10.@) 03492 * 03493 * Retrieve a glyph order map. 03494 * 03495 * PARAMS 03496 * ssa [I] String analysis. 03497 * order [I/O] Array of glyph positions. 03498 * 03499 * RETURNS 03500 * Success: S_OK 03501 * Failure: a non-zero HRESULT. 03502 */ 03503 HRESULT WINAPI ScriptStringGetOrder(SCRIPT_STRING_ANALYSIS ssa, UINT *order) 03504 { 03505 int i, j; 03506 unsigned int k; 03507 StringAnalysis *analysis = ssa; 03508 03509 TRACE("(%p)\n", ssa); 03510 03511 if (!analysis) return S_FALSE; 03512 if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; 03513 03514 /* FIXME: handle RTL scripts */ 03515 for (i = 0, k = 0; i < analysis->numItems; i++) 03516 for (j = 0; j < analysis->glyphs[i].numGlyphs; j++, k++) 03517 order[k] = k; 03518 03519 return S_OK; 03520 } 03521 03522 /*********************************************************************** 03523 * ScriptGetLogicalWidths (USP10.@) 03524 * 03525 * Convert advance widths to logical widths. 03526 * 03527 * PARAMS 03528 * sa [I] Script analysis. 03529 * nbchars [I] Number of characters. 03530 * nbglyphs [I] Number of glyphs. 03531 * glyph_width [I] Array of glyph widths. 03532 * log_clust [I] Array of logical clusters. 03533 * sva [I] Visual attributes. 03534 * widths [O] Array of logical widths. 03535 * 03536 * RETURNS 03537 * Success: S_OK 03538 * Failure: a non-zero HRESULT. 03539 */ 03540 HRESULT WINAPI ScriptGetLogicalWidths(const SCRIPT_ANALYSIS *sa, int nbchars, int nbglyphs, 03541 const int *glyph_width, const WORD *log_clust, 03542 const SCRIPT_VISATTR *sva, int *widths) 03543 { 03544 int i; 03545 03546 TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", 03547 sa, nbchars, nbglyphs, glyph_width, log_clust, sva, widths); 03548 03549 /* FIXME */ 03550 for (i = 0; i < nbchars; i++) widths[i] = glyph_width[i]; 03551 return S_OK; 03552 } 03553 03554 /*********************************************************************** 03555 * ScriptApplyLogicalWidth (USP10.@) 03556 * 03557 * Generate glyph advance widths. 03558 * 03559 * PARAMS 03560 * dx [I] Array of logical advance widths. 03561 * num_chars [I] Number of characters. 03562 * num_glyphs [I] Number of glyphs. 03563 * log_clust [I] Array of logical clusters. 03564 * sva [I] Visual attributes. 03565 * advance [I] Array of glyph advance widths. 03566 * sa [I] Script analysis. 03567 * abc [I/O] Summed ABC widths. 03568 * justify [O] Array of glyph advance widths. 03569 * 03570 * RETURNS 03571 * Success: S_OK 03572 * Failure: a non-zero HRESULT. 03573 */ 03574 HRESULT WINAPI ScriptApplyLogicalWidth(const int *dx, int num_chars, int num_glyphs, 03575 const WORD *log_clust, const SCRIPT_VISATTR *sva, 03576 const int *advance, const SCRIPT_ANALYSIS *sa, 03577 ABC *abc, int *justify) 03578 { 03579 int i; 03580 03581 FIXME("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", 03582 dx, num_chars, num_glyphs, log_clust, sva, advance, sa, abc, justify); 03583 03584 for (i = 0; i < num_chars; i++) justify[i] = advance[i]; 03585 return S_OK; 03586 } 03587 03588 HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance, 03589 int num_glyphs, int dx, int min_kashida, int *justify) 03590 { 03591 int i; 03592 03593 FIXME("(%p, %p, %d, %d, %d, %p)\n", sva, advance, num_glyphs, dx, min_kashida, justify); 03594 03595 for (i = 0; i < num_glyphs; i++) justify[i] = advance[i]; 03596 return S_OK; 03597 } 03598 03599 HRESULT WINAPI ScriptGetFontScriptTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags) 03600 { 03601 HRESULT hr; 03602 if (!pScriptTags || !pcTags || cMaxTags == 0) return E_INVALIDARG; 03603 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03604 03605 return SHAPE_GetFontScriptTags(hdc, (ScriptCache *)*psc, psa, cMaxTags, pScriptTags, pcTags); 03606 } 03607 03608 HRESULT WINAPI ScriptGetFontLanguageTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags) 03609 { 03610 HRESULT hr; 03611 if (!pLangSysTags || !pcTags || cMaxTags == 0) return E_INVALIDARG; 03612 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03613 03614 return SHAPE_GetFontLanguageTags(hdc, (ScriptCache *)*psc, psa, tagScript, cMaxTags, pLangSysTags, pcTags); 03615 } 03616 03617 HRESULT WINAPI ScriptGetFontFeatureTags( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags) 03618 { 03619 HRESULT hr; 03620 if (!pFeatureTags || !pcTags || cMaxTags == 0) return E_INVALIDARG; 03621 if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; 03622 03623 return SHAPE_GetFontFeatureTags(hdc, (ScriptCache *)*psc, psa, tagScript, tagLangSys, cMaxTags, pFeatureTags, pcTags); 03624 } 03625 03626 BOOL gbLpkPresent = FALSE; 03627 VOID WINAPI LpkPresent() 03628 { 03629 gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */ 03630 } Generated on Wed May 23 2012 04:24:39 for ReactOS by
1.7.6.1
|