[8] | 1 | /****************************************************************************
|
---|
| 2 | ** $Id: qtextengine_pm.cpp 20 2005-11-17 18:00:27Z dmik $
|
---|
| 3 | **
|
---|
| 4 | ** ???
|
---|
| 5 | **
|
---|
| 6 | ** Copyright (C) 2003 Trolltech AS. All rights reserved.
|
---|
| 7 | ** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
|
---|
| 8 | ** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
|
---|
| 9 | **
|
---|
| 10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
---|
| 11 | **
|
---|
| 12 | ** This file may be distributed under the terms of the Q Public License
|
---|
| 13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
---|
| 14 | ** LICENSE.QPL included in the packaging of this file.
|
---|
| 15 | **
|
---|
| 16 | ** This file may be distributed and/or modified under the terms of the
|
---|
| 17 | ** GNU General Public License version 2 as published by the Free Software
|
---|
| 18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 19 | ** packaging of this file.
|
---|
| 20 | **
|
---|
| 21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
---|
| 22 | ** licenses may use this file in accordance with the Qt Commercial License
|
---|
| 23 | ** Agreement provided with the Software.
|
---|
| 24 | **
|
---|
| 25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
| 26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
| 27 | **
|
---|
| 28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
| 29 | ** information about Qt Commercial License Agreements.
|
---|
| 30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
| 31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
| 32 | **
|
---|
| 33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
| 34 | ** not clear to you.
|
---|
| 35 | **
|
---|
| 36 | **********************************************************************/
|
---|
| 37 |
|
---|
| 38 | #ifdef QT_THREAD_SUPPORT
|
---|
| 39 | # include <private/qmutexpool_p.h>
|
---|
| 40 | #endif // QT_THREAD_SUPPORT
|
---|
| 41 | #include "qlibrary.h"
|
---|
| 42 |
|
---|
| 43 |
|
---|
[20] | 44 | /// @todo (dmik) remove?
|
---|
| 45 | #if 0
|
---|
| 46 | // these defines are from usp10.h
|
---|
| 47 | typedef void *SCRIPT_CACHE;
|
---|
| 48 | typedef struct tag_SCRIPT_CONTROL {
|
---|
| 49 | DWORD uDefaultLanguage :16;
|
---|
| 50 | DWORD fContextDigits :1;
|
---|
| 51 | DWORD fInvertPreBoundDir :1;
|
---|
| 52 | DWORD fInvertPostBoundDir :1;
|
---|
| 53 | DWORD fLinkStringBefore :1;
|
---|
| 54 | DWORD fLinkStringAfter :1;
|
---|
| 55 | DWORD fNeutralOverride :1;
|
---|
| 56 | DWORD fNumericOverride :1;
|
---|
| 57 | DWORD fLegacyBidiClass :1;
|
---|
| 58 | DWORD fReserved :8;
|
---|
| 59 | } SCRIPT_CONTROL;
|
---|
| 60 |
|
---|
| 61 | typedef struct tag_SCRIPT_STATE {
|
---|
| 62 | WORD uBidiLevel :5;
|
---|
| 63 | WORD fOverrideDirection :1;
|
---|
| 64 | WORD fInhibitSymSwap :1;
|
---|
| 65 | WORD fCharShape :1;
|
---|
| 66 | WORD fDigitSubstitute :1;
|
---|
| 67 | WORD fInhibitLigate :1;
|
---|
| 68 | WORD fDisplayZWG :1;
|
---|
| 69 | WORD fArabicNumContext :1;
|
---|
| 70 | WORD fGcpClusters :1;
|
---|
| 71 | WORD fReserved :1;
|
---|
| 72 | WORD fEngineReserved :2;
|
---|
| 73 | } SCRIPT_STATE;
|
---|
| 74 |
|
---|
| 75 | typedef struct tag_SCRIPT_ITEM {
|
---|
| 76 | int iCharPos;
|
---|
| 77 | QScriptAnalysis a;
|
---|
| 78 | } SCRIPT_ITEM;
|
---|
| 79 |
|
---|
| 80 | typedef GlyphAttributes SCRIPT_VISATTR;
|
---|
| 81 | typedef qoffset_t GOFFSET;
|
---|
| 82 |
|
---|
| 83 | #define USP_E_SCRIPT_NOT_IN_FONT \
|
---|
| 84 | MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,0x200) // Script doesn't exist in font
|
---|
| 85 |
|
---|
| 86 | typedef struct {
|
---|
| 87 | DWORD langid :16;
|
---|
| 88 | DWORD fNumeric :1;
|
---|
| 89 | DWORD fComplex :1;
|
---|
| 90 | DWORD fNeedsWordBreaking :1;
|
---|
| 91 | DWORD fNeedsCaretInfo :1;
|
---|
| 92 | DWORD bCharSet :8;
|
---|
| 93 | DWORD fControl :1;
|
---|
| 94 | DWORD fPrivateUseArea :1;
|
---|
| 95 | DWORD fNeedsCharacterJustify :1;
|
---|
| 96 | DWORD fInvalidGlyph :1;
|
---|
| 97 | DWORD fInvalidLogAttr :1;
|
---|
| 98 | DWORD fCDM :1;
|
---|
| 99 | DWORD fAmbiguousCharSet :1;
|
---|
| 100 | DWORD fClusterSizeVaries :1;
|
---|
| 101 | DWORD fRejectInvalid :1;
|
---|
| 102 | } SCRIPT_PROPERTIES;
|
---|
| 103 |
|
---|
| 104 | #if defined(Q_OS_TEMP) && UNDER_CE < 400
|
---|
| 105 | typedef struct _ABC {
|
---|
| 106 | int abcA;
|
---|
| 107 | UINT abcB;
|
---|
| 108 | int abcC;
|
---|
| 109 | } ABC;
|
---|
| 110 | #endif
|
---|
| 111 |
|
---|
| 112 | typedef HRESULT (WINAPI *fScriptFreeCache)( SCRIPT_CACHE *);
|
---|
| 113 | typedef HRESULT (WINAPI *fScriptItemize)( const WCHAR *, int, int, const SCRIPT_CONTROL *,
|
---|
| 114 | const SCRIPT_STATE *, SCRIPT_ITEM *, int *);
|
---|
| 115 | typedef HRESULT (WINAPI *fScriptShape)( HDC hdc, SCRIPT_CACHE *, const WCHAR *, int, int,
|
---|
| 116 | QScriptAnalysis *, WORD *, WORD *, SCRIPT_VISATTR *, int *);
|
---|
| 117 | typedef HRESULT (WINAPI *fScriptPlace)( HDC, SCRIPT_CACHE *, const WORD *, int, const SCRIPT_VISATTR *, QScriptAnalysis *, int *,
|
---|
| 118 | GOFFSET *, ABC * );
|
---|
| 119 | typedef HRESULT (WINAPI *fScriptTextOut)( const HDC, SCRIPT_CACHE *, int, int, UINT, const RECT *, const QScriptAnalysis *,
|
---|
| 120 | const WCHAR *, int, const WORD *, int, const int *, const int *, const GOFFSET *);
|
---|
| 121 | typedef HRESULT (WINAPI *fScriptBreak)( const WCHAR *, int, const QScriptAnalysis *, QCharAttributes * );
|
---|
| 122 | //typedef HRESULT (WINAPI *fScriptGetFontProperties)( HDC, SCRIPT_CACHE *, SCRIPT_FONTPROPERTIES * );
|
---|
| 123 | typedef HRESULT (WINAPI *fScriptGetProperties)( const SCRIPT_PROPERTIES ***, int *);
|
---|
| 124 |
|
---|
| 125 | fScriptFreeCache ScriptFreeCache = 0;
|
---|
| 126 | static fScriptItemize ScriptItemize = 0;
|
---|
| 127 | static fScriptShape ScriptShape = 0;
|
---|
| 128 | static fScriptPlace ScriptPlace = 0;
|
---|
| 129 | fScriptTextOut ScriptTextOut = 0;
|
---|
| 130 | static fScriptBreak ScriptBreak = 0;
|
---|
| 131 | //static fScriptGetFontProperties ScriptGetFontProperties = 0;
|
---|
| 132 | static fScriptGetProperties ScriptGetProperties = 0;
|
---|
| 133 |
|
---|
| 134 | static bool resolvedUsp10 = FALSE;
|
---|
| 135 | bool hasUsp10 = FALSE;
|
---|
| 136 |
|
---|
| 137 | const SCRIPT_PROPERTIES **script_properties = 0;
|
---|
| 138 | int num_scripts = 0;
|
---|
| 139 | int usp_latin_script = 0;
|
---|
| 140 |
|
---|
| 141 |
|
---|
| 142 | const QFont::Script japanese_tryScripts[] = {
|
---|
| 143 | QFont::Latin,
|
---|
| 144 | QFont::Han_Japanese,
|
---|
| 145 | QFont::Hangul,
|
---|
| 146 | QFont::Han_SimplifiedChinese,
|
---|
| 147 | QFont::Han_TraditionalChinese
|
---|
| 148 | };
|
---|
| 149 |
|
---|
| 150 | const QFont::Script korean_tryScripts[] = {
|
---|
| 151 | QFont::Latin,
|
---|
| 152 | QFont::Hangul,
|
---|
| 153 | QFont::Han_Japanese,
|
---|
| 154 | QFont::Han_SimplifiedChinese,
|
---|
| 155 | QFont::Han_TraditionalChinese
|
---|
| 156 | };
|
---|
| 157 |
|
---|
| 158 | const QFont::Script simplifiedChinese_tryScripts[] = {
|
---|
| 159 | QFont::Latin,
|
---|
| 160 | QFont::Han_SimplifiedChinese,
|
---|
| 161 | QFont::Han_TraditionalChinese,
|
---|
| 162 | QFont::Han_Japanese,
|
---|
| 163 | QFont::Hangul
|
---|
| 164 | };
|
---|
| 165 |
|
---|
| 166 | const QFont::Script traditionalChinese_tryScripts[] = {
|
---|
| 167 | QFont::Latin,
|
---|
| 168 | QFont::Han_TraditionalChinese,
|
---|
| 169 | QFont::Han_SimplifiedChinese,
|
---|
| 170 | QFont::Han_Japanese,
|
---|
| 171 | QFont::Hangul
|
---|
| 172 | };
|
---|
| 173 |
|
---|
| 174 | const QFont::Script *tryScripts = japanese_tryScripts;
|
---|
| 175 |
|
---|
| 176 | static void uspAppendItems(QTextEngine *engine, int &start, int &stop, BidiControl &control, QChar::Direction dir);
|
---|
| 177 |
|
---|
| 178 | static void resolveUsp10()
|
---|
| 179 | {
|
---|
| 180 | #ifndef QT_NO_COMPONENT
|
---|
| 181 | if ( !resolvedUsp10 ) {
|
---|
| 182 | // need to resolve the security info functions
|
---|
| 183 |
|
---|
| 184 | #ifdef QT_THREAD_SUPPORT
|
---|
| 185 | // protect initialization
|
---|
| 186 | QMutexLocker locker( qt_global_mutexpool ?
|
---|
| 187 | qt_global_mutexpool->get( (void*)&resolveUsp10 ) : 0 );
|
---|
| 188 | // check triedResolve again, since another thread may have already
|
---|
| 189 | // done the initialization
|
---|
| 190 | if ( resolvedUsp10 ) {
|
---|
| 191 | // another thread did initialize the security function pointers,
|
---|
| 192 | // so we shouldn't do it again.
|
---|
| 193 | return;
|
---|
| 194 | }
|
---|
| 195 | #endif
|
---|
| 196 |
|
---|
| 197 | resolvedUsp10 = TRUE;
|
---|
| 198 | QLibrary lib("usp10");
|
---|
| 199 | lib.setAutoUnload( FALSE );
|
---|
| 200 |
|
---|
| 201 | ScriptFreeCache = (fScriptFreeCache) lib.resolve( "ScriptFreeCache" );
|
---|
| 202 | ScriptItemize = (fScriptItemize) lib.resolve( "ScriptItemize" );
|
---|
| 203 | ScriptShape = (fScriptShape) lib.resolve( "ScriptShape" );
|
---|
| 204 | ScriptPlace = (fScriptPlace) lib.resolve( "ScriptPlace" );
|
---|
| 205 | ScriptTextOut = (fScriptTextOut) lib.resolve( "ScriptTextOut" );
|
---|
| 206 | ScriptBreak = (fScriptBreak) lib.resolve( "ScriptBreak" );
|
---|
| 207 | ScriptGetProperties = (fScriptGetProperties) lib.resolve( "ScriptGetProperties" );
|
---|
| 208 |
|
---|
| 209 | if ( !ScriptFreeCache )
|
---|
| 210 | return;
|
---|
| 211 |
|
---|
| 212 | hasUsp10 = TRUE;
|
---|
| 213 | ScriptGetProperties( &script_properties, &num_scripts );
|
---|
| 214 |
|
---|
| 215 | // get the usp script for western
|
---|
| 216 | for( int i = 0; i < num_scripts; i++ ) {
|
---|
| 217 | if (script_properties[i]->langid == LANG_ENGLISH &&
|
---|
| 218 | !script_properties[i]->fAmbiguousCharSet ) {
|
---|
| 219 | usp_latin_script = i;
|
---|
| 220 | break;
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 | // initialize tryScripts according to locale
|
---|
| 225 | LANGID lid = GetUserDefaultLangID();
|
---|
| 226 | switch( lid&0xff ) {
|
---|
| 227 | case LANG_CHINESE: // Chinese (Taiwan)
|
---|
| 228 | if ( lid == 0x0804 ) // Taiwan
|
---|
| 229 | tryScripts = traditionalChinese_tryScripts;
|
---|
| 230 | else
|
---|
| 231 | tryScripts = simplifiedChinese_tryScripts;
|
---|
| 232 | break;
|
---|
| 233 | case LANG_JAPANESE:
|
---|
| 234 | // japanese is already the default
|
---|
| 235 | break;
|
---|
| 236 | case LANG_KOREAN:
|
---|
| 237 | tryScripts = korean_tryScripts;
|
---|
| 238 | break;
|
---|
| 239 | default:
|
---|
| 240 | break;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | appendItems = uspAppendItems;
|
---|
| 244 | }
|
---|
| 245 | #endif
|
---|
| 246 | }
|
---|
| 247 |
|
---|
| 248 | static unsigned char script_for_win_language[ 0x80 ] = {
|
---|
| 249 | //0x00 LANG_NEUTRAL Neutral
|
---|
| 250 | QFont::Latin,
|
---|
| 251 | //0x01 LANG_ARABIC Arabic
|
---|
| 252 | QFont::Arabic,
|
---|
| 253 | //0x02 LANG_BULGARIAN Bulgarian
|
---|
| 254 | QFont::NScripts,
|
---|
| 255 | //0x03 LANG_CATALAN Catalan
|
---|
| 256 | QFont::NScripts,
|
---|
| 257 | //0x04 LANG_CHINESE Chinese
|
---|
| 258 | QFont::Han,
|
---|
| 259 | //0x05 LANG_CZECH Czech
|
---|
| 260 | QFont::NScripts,
|
---|
| 261 | //0x06 LANG_DANISH Danish
|
---|
| 262 | QFont::NScripts,
|
---|
| 263 | //0x07 LANG_GERMAN German
|
---|
| 264 | QFont::NScripts,
|
---|
| 265 | //0x08 LANG_GREEK Greek
|
---|
| 266 | QFont::Greek,
|
---|
| 267 | //0x09 LANG_ENGLISH English
|
---|
| 268 | QFont::Latin,
|
---|
| 269 | //0x0a LANG_SPANISH Spanish
|
---|
| 270 | QFont::NScripts,
|
---|
| 271 | //0x0b LANG_FINNISH Finnish
|
---|
| 272 | QFont::NScripts,
|
---|
| 273 | //0x0c LANG_FRENCH French
|
---|
| 274 | QFont::NScripts,
|
---|
| 275 | //0x0d LANG_HEBREW Hebrew
|
---|
| 276 | QFont::Hebrew,
|
---|
| 277 | //0x0e LANG_HUNGARIAN Hungarian
|
---|
| 278 | QFont::NScripts,
|
---|
| 279 | //0x0f LANG_ICELANDIC Icelandic
|
---|
| 280 | QFont::NScripts,
|
---|
| 281 |
|
---|
| 282 | //0x10 LANG_ITALIAN Italian
|
---|
| 283 | QFont::NScripts,
|
---|
| 284 | //0x11 LANG_JAPANESE Japanese
|
---|
| 285 | QFont::Hiragana,
|
---|
| 286 | //0x12 LANG_KOREAN Korean
|
---|
| 287 | QFont::Hangul,
|
---|
| 288 | //0x13 LANG_DUTCH Dutch
|
---|
| 289 | QFont::NScripts,
|
---|
| 290 | //0x14 LANG_NORWEGIAN Norwegian
|
---|
| 291 | QFont::NScripts,
|
---|
| 292 | //0x15 LANG_POLISH Polish
|
---|
| 293 | QFont::NScripts,
|
---|
| 294 | //0x16 LANG_PORTUGUESE Portuguese
|
---|
| 295 | QFont::NScripts,
|
---|
| 296 | QFont::NScripts,
|
---|
| 297 | //0x18 LANG_ROMANIAN Romanian
|
---|
| 298 | QFont::NScripts,
|
---|
| 299 | //0x19 LANG_RUSSIAN Russian
|
---|
| 300 | QFont::Cyrillic,
|
---|
| 301 | //0x1a LANG_CROATIAN Croatian
|
---|
| 302 | //0x1a LANG_SERBIAN Serbian
|
---|
| 303 | QFont::NScripts,
|
---|
| 304 | //0x1b LANG_SLOVAK Slovak
|
---|
| 305 | QFont::NScripts,
|
---|
| 306 | //0x1c LANG_ALBANIAN Albanian
|
---|
| 307 | QFont::NScripts,
|
---|
| 308 | //0x1d LANG_SWEDISH Swedish
|
---|
| 309 | QFont::NScripts,
|
---|
| 310 | //0x1e LANG_THAI Thai
|
---|
| 311 | QFont::Thai,
|
---|
| 312 | //0x1f LANG_TURKISH Turkish
|
---|
| 313 | QFont::NScripts,
|
---|
| 314 |
|
---|
| 315 | //0x20 LANG_URDU Urdu
|
---|
| 316 | QFont::NScripts,
|
---|
| 317 | //0x21 LANG_INDONESIAN Indonesian
|
---|
| 318 | QFont::NScripts,
|
---|
| 319 | //0x22 LANG_UKRAINIAN Ukrainian
|
---|
| 320 | QFont::NScripts,
|
---|
| 321 | //0x23 LANG_BELARUSIAN Belarusian
|
---|
| 322 | QFont::NScripts,
|
---|
| 323 | //0x24 LANG_SLOVENIAN Slovenian
|
---|
| 324 | QFont::NScripts,
|
---|
| 325 | //0x25 LANG_ESTONIAN Estonian
|
---|
| 326 | QFont::NScripts,
|
---|
| 327 | //0x26 LANG_LATVIAN Latvian
|
---|
| 328 | QFont::NScripts,
|
---|
| 329 | //0x27 LANG_LITHUANIAN Lithuanian
|
---|
| 330 | QFont::NScripts,
|
---|
| 331 | QFont::NScripts,
|
---|
| 332 | //0x29 LANG_FARSI Farsi
|
---|
| 333 | QFont::NScripts,
|
---|
| 334 | //0x2a LANG_VIETNAMESE Vietnamese
|
---|
| 335 | QFont::Latin, // ##### maybe use QFont::CombiningMarks instead?
|
---|
| 336 | //0x2b LANG_ARMENIAN Armenian
|
---|
| 337 | QFont::Armenian,
|
---|
| 338 | //0x2c LANG_AZERI Azeri
|
---|
| 339 | QFont::NScripts,
|
---|
| 340 | //0x2d LANG_BASQUE Basque
|
---|
| 341 | QFont::NScripts,
|
---|
| 342 | QFont::NScripts,
|
---|
| 343 | //0x2f LANG_MACEDONIAN FYRO Macedonian
|
---|
| 344 | QFont::NScripts,
|
---|
| 345 |
|
---|
| 346 | QFont::NScripts,
|
---|
| 347 | QFont::NScripts,
|
---|
| 348 | QFont::NScripts,
|
---|
| 349 | QFont::NScripts,
|
---|
| 350 | QFont::NScripts,
|
---|
| 351 | QFont::NScripts,
|
---|
| 352 | //0x36 LANG_AFRIKAANS Afrikaans
|
---|
| 353 | QFont::NScripts,
|
---|
| 354 | //0x37 LANG_GEORGIAN Georgian
|
---|
| 355 | QFont::NScripts,
|
---|
| 356 | //0x38 LANG_FAEROESE Faeroese
|
---|
| 357 | QFont::NScripts,
|
---|
| 358 | //0x39 LANG_HINDI Hindi
|
---|
| 359 | QFont::Devanagari,
|
---|
| 360 | QFont::NScripts,
|
---|
| 361 | QFont::NScripts,
|
---|
| 362 | QFont::NScripts,
|
---|
| 363 | QFont::NScripts,
|
---|
| 364 | //0x3e LANG_MALAY Malay
|
---|
| 365 | QFont::NScripts,
|
---|
| 366 | //0x3f LANG_KAZAK Kazak
|
---|
| 367 | QFont::NScripts,
|
---|
| 368 |
|
---|
| 369 | //0x40 LANG_KYRGYZ Kyrgyz
|
---|
| 370 | QFont::NScripts,
|
---|
| 371 | //0x41 LANG_SWAHILI Swahili
|
---|
| 372 | QFont::NScripts,
|
---|
| 373 | QFont::NScripts,
|
---|
| 374 | //0x43 LANG_UZBEK Uzbek
|
---|
| 375 | QFont::NScripts,
|
---|
| 376 | //0x44 LANG_TATAR Tatar
|
---|
| 377 | QFont::NScripts,
|
---|
| 378 | //0x45 LANG_BENGALI Not supported.
|
---|
| 379 | QFont::Bengali,
|
---|
| 380 | //0x46 LANG_PUNJABI Punjabi
|
---|
| 381 | QFont::Gurmukhi,
|
---|
| 382 | //0x47 LANG_GUJARATI Gujarati
|
---|
| 383 | QFont::Gujarati,
|
---|
| 384 | //0x48 LANG_ORIYA Not supported.
|
---|
| 385 | QFont::Oriya,
|
---|
| 386 | //0x49 LANG_TAMIL Tamil
|
---|
| 387 | QFont::Tamil,
|
---|
| 388 | //0x4a LANG_TELUGU Telugu
|
---|
| 389 | QFont::Telugu,
|
---|
| 390 | //0x4b LANG_KANNADA Kannada
|
---|
| 391 | QFont::Kannada,
|
---|
| 392 | //0x4c LANG_MALAYALAM Not supported.
|
---|
| 393 | QFont::Malayalam,
|
---|
| 394 | //0x4d LANG_ASSAMESE Not supported.
|
---|
| 395 | QFont::NScripts,
|
---|
| 396 | //0x4e LANG_MARATHI Marathi
|
---|
| 397 | QFont::NScripts,
|
---|
| 398 | //0x4f LANG_SANSKRIT Sanskrit
|
---|
| 399 | QFont::Devanagari,
|
---|
| 400 |
|
---|
| 401 | //0x50 LANG_MONGOLIAN Mongolian
|
---|
| 402 | QFont::Mongolian,
|
---|
| 403 | QFont::NScripts,
|
---|
| 404 | QFont::NScripts,
|
---|
| 405 | QFont::NScripts,
|
---|
| 406 | QFont::NScripts,
|
---|
| 407 | QFont::NScripts,
|
---|
| 408 | //0x56 LANG_GALICIAN Galician
|
---|
| 409 | QFont::NScripts,
|
---|
| 410 | //0x57 LANG_KONKANI Konkani
|
---|
| 411 | QFont::NScripts,
|
---|
| 412 | //0x58 LANG_MANIPURI Not supported.
|
---|
| 413 | QFont::NScripts,
|
---|
| 414 | //0x59 LANG_SINDHI Not supported.
|
---|
| 415 | QFont::NScripts,
|
---|
| 416 | //0x5a LANG_SYRIAC Syriac
|
---|
| 417 | QFont::Syriac,
|
---|
| 418 | QFont::NScripts,
|
---|
| 419 | QFont::NScripts,
|
---|
| 420 | QFont::NScripts,
|
---|
| 421 | QFont::NScripts,
|
---|
| 422 | QFont::NScripts,
|
---|
| 423 |
|
---|
| 424 | //0x60 LANG_KASHMIRI Not supported.
|
---|
| 425 | QFont::NScripts,
|
---|
| 426 | //0x61 LANG_NEPALI Not supported.
|
---|
| 427 | QFont::NScripts,
|
---|
| 428 | QFont::NScripts,
|
---|
| 429 | QFont::NScripts,
|
---|
| 430 | QFont::NScripts,
|
---|
| 431 | //0x65 LANG_DIVEHI Divehi
|
---|
| 432 | QFont::NScripts,
|
---|
| 433 | QFont::NScripts,
|
---|
| 434 | QFont::NScripts,
|
---|
| 435 | QFont::NScripts,
|
---|
| 436 | QFont::NScripts,
|
---|
| 437 | QFont::NScripts,
|
---|
| 438 | QFont::NScripts,
|
---|
| 439 | QFont::NScripts,
|
---|
| 440 | QFont::NScripts,
|
---|
| 441 | QFont::NScripts,
|
---|
| 442 | QFont::NScripts,
|
---|
| 443 |
|
---|
| 444 | QFont::NScripts,
|
---|
| 445 | QFont::NScripts,
|
---|
| 446 | QFont::NScripts,
|
---|
| 447 | QFont::NScripts,
|
---|
| 448 | QFont::NScripts,
|
---|
| 449 | QFont::NScripts,
|
---|
| 450 | QFont::NScripts,
|
---|
| 451 | QFont::NScripts,
|
---|
| 452 | QFont::NScripts,
|
---|
| 453 | QFont::NScripts,
|
---|
| 454 | QFont::NScripts,
|
---|
| 455 | QFont::NScripts,
|
---|
| 456 | QFont::NScripts,
|
---|
| 457 | QFont::NScripts,
|
---|
| 458 | QFont::NScripts,
|
---|
| 459 | //0x7f LANG_INVARIANT
|
---|
| 460 | QFont::NScripts,
|
---|
| 461 | };
|
---|
| 462 |
|
---|
| 463 | static inline QFont::Script scriptForWinLanguage( DWORD langid )
|
---|
| 464 | {
|
---|
| 465 | QFont::Script script = (QFont::Script)script_for_win_language[langid];
|
---|
| 466 | if ( script == QFont::NScripts )
|
---|
| 467 | qWarning( "Qt Uniscribe support: Encountered unhandled language id %x", (unsigned int)langid );
|
---|
| 468 | return script;
|
---|
| 469 | }
|
---|
| 470 |
|
---|
| 471 | static inline bool isAsian( unsigned short ch )
|
---|
| 472 | {
|
---|
| 473 | return (ch > 0x2dff && ch < 0xfb00) || ((ch & 0xff00) == 0x1100);
|
---|
| 474 | }
|
---|
| 475 |
|
---|
| 476 |
|
---|
| 477 | // we're not using Uniscribe's BiDi algorithm, since it is (a) not 100% Unicode compliant and
|
---|
| 478 | // (b) seems to work wrongly when trying to use it with a base level != 0.
|
---|
[8] | 479 | //
|
---|
[20] | 480 | // This function does uses Uniscribe to do the script analysis and creates items from this.
|
---|
| 481 | static void uspAppendItems(QTextEngine *engine, int &start, int &stop, BidiControl &control, QChar::Direction dir)
|
---|
| 482 | {
|
---|
| 483 | QScriptItemArray &items = engine->items;
|
---|
| 484 | const QChar *text = engine->string.unicode();
|
---|
[8] | 485 |
|
---|
[20] | 486 | if ( start > stop ) {
|
---|
| 487 | // #### the algorithm is currently not really safe against this. Still needs fixing.
|
---|
| 488 | // qWarning( "Bidi: appendItems() internal error" );
|
---|
| 489 | return;
|
---|
| 490 | }
|
---|
[8] | 491 |
|
---|
[20] | 492 | int level = control.level();
|
---|
| 493 |
|
---|
| 494 | if(dir != QChar::DirON) {
|
---|
| 495 | // add level of run (cases I1 & I2)
|
---|
| 496 | if( level % 2 ) {
|
---|
| 497 | if(dir == QChar::DirL || dir == QChar::DirAN || dir == QChar::DirEN )
|
---|
| 498 | level++;
|
---|
| 499 | } else {
|
---|
| 500 | if( dir == QChar::DirR )
|
---|
| 501 | level++;
|
---|
| 502 | else if( dir == QChar::DirAN || dir == QChar::DirEN )
|
---|
| 503 | level += 2;
|
---|
| 504 | }
|
---|
| 505 | }
|
---|
| 506 |
|
---|
| 507 | SCRIPT_ITEM s_items[256];
|
---|
| 508 | SCRIPT_ITEM *usp_items = s_items;
|
---|
| 509 |
|
---|
| 510 | int numItems;
|
---|
| 511 | HRESULT res = ScriptItemize( (WCHAR *)(text+start), stop-start+1, 255, 0, 0, usp_items, &numItems );
|
---|
| 512 |
|
---|
| 513 | if ( res == E_OUTOFMEMORY ) {
|
---|
| 514 | int alloc = 256;
|
---|
| 515 | usp_items = 0;
|
---|
| 516 | while( res == E_OUTOFMEMORY ) {
|
---|
| 517 | alloc *= 2;
|
---|
| 518 | usp_items = (SCRIPT_ITEM *)realloc( usp_items, alloc * sizeof( SCRIPT_ITEM ) );
|
---|
| 519 | res = ScriptItemize( (WCHAR *)(text+start), stop-start+1, alloc-1, 0, 0, usp_items, &numItems );
|
---|
| 520 | }
|
---|
| 521 | }
|
---|
| 522 | items.resize( items.size() + numItems );
|
---|
| 523 | int i;
|
---|
| 524 | for( i = 0; i < numItems; i++ ) {
|
---|
| 525 | QScriptItem item;
|
---|
| 526 | item.analysis = usp_items[i].a;
|
---|
| 527 | item.position = usp_items[i].iCharPos+start;
|
---|
| 528 | item.analysis.bidiLevel = level;
|
---|
| 529 | item.analysis.override = control.override();
|
---|
| 530 |
|
---|
| 531 | int rstart = usp_items[i].iCharPos;
|
---|
| 532 | int rstop = usp_items[i+1].iCharPos-1;
|
---|
| 533 | bool b = TRUE;
|
---|
| 534 | for ( int j = rstart; j <= rstop; j++ ) {
|
---|
| 535 |
|
---|
| 536 | unsigned short uc = text[j+start].unicode();
|
---|
| 537 | QChar::Category category = ::category( uc );
|
---|
| 538 | if ( uc == 0xfffcU || uc == 0x2028U ) {
|
---|
| 539 | item.analysis.script = usp_latin_script;
|
---|
| 540 | item.isObject = TRUE;
|
---|
| 541 | b = TRUE;
|
---|
| 542 | } else if ((uc >= 9 && uc <=13) ||
|
---|
| 543 | (category >= QChar::Separator_Space && category <= QChar::Separator_Paragraph)) {
|
---|
| 544 | item.analysis.script = usp_latin_script;
|
---|
| 545 | item.isSpace = TRUE;
|
---|
| 546 | item.isTab = (uc == '\t');
|
---|
| 547 | if (item.isTab)
|
---|
| 548 | item.analysis.bidiLevel = control.baseLevel();
|
---|
| 549 | b = TRUE;
|
---|
| 550 | } else if (b) {
|
---|
| 551 | b = FALSE;
|
---|
| 552 | } else {
|
---|
| 553 | continue;
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | item.position = j+start;
|
---|
| 557 | items.append( item );
|
---|
| 558 | item.analysis = usp_items[i].a;
|
---|
| 559 | item.analysis.bidiLevel = level;
|
---|
| 560 | item.analysis.override = control.override();
|
---|
| 561 | item.isSpace = item.isTab = item.isObject = FALSE;
|
---|
| 562 | }
|
---|
| 563 | }
|
---|
| 564 |
|
---|
| 565 | if ( usp_items != s_items )
|
---|
| 566 | free( usp_items );
|
---|
| 567 |
|
---|
| 568 | ++stop;
|
---|
| 569 | start = stop;
|
---|
| 570 | }
|
---|
| 571 | #endif // if 0
|
---|
| 572 |
|
---|
[8] | 573 | // -----------------------------------------------------------------------------------------------------
|
---|
| 574 | //
|
---|
| 575 | // Text engine classes
|
---|
| 576 | //
|
---|
| 577 | // -----------------------------------------------------------------------------------------------------
|
---|
| 578 |
|
---|
| 579 |
|
---|
| 580 | QScriptItemArray::~QScriptItemArray()
|
---|
| 581 | {
|
---|
| 582 | clear();
|
---|
| 583 | free( d );
|
---|
| 584 | }
|
---|
| 585 |
|
---|
| 586 | void QScriptItemArray::clear()
|
---|
| 587 | {
|
---|
| 588 | if ( d ) {
|
---|
| 589 | for ( unsigned int i = 0; i < d->size; i++ ) {
|
---|
| 590 | QScriptItem &si = d->items[i];
|
---|
| 591 | if ( si.fontEngine )
|
---|
| 592 | si.fontEngine->deref();
|
---|
| 593 | }
|
---|
| 594 | d->size = 0;
|
---|
| 595 | }
|
---|
| 596 | }
|
---|
| 597 |
|
---|
| 598 | void QScriptItemArray::resize( int s )
|
---|
| 599 | {
|
---|
| 600 | int alloc = ((s + 8) >> 3) << 3;
|
---|
| 601 | d = (QScriptItemArrayPrivate *)realloc( d, sizeof( QScriptItemArrayPrivate ) +
|
---|
| 602 | sizeof( QScriptItem ) * alloc );
|
---|
| 603 | d->alloc = alloc;
|
---|
| 604 | }
|
---|
| 605 |
|
---|
| 606 |
|
---|
| 607 | void QTextEngine::shape( int item ) const
|
---|
| 608 | {
|
---|
| 609 | QScriptItem &si = items[item];
|
---|
| 610 |
|
---|
| 611 | if ( si.num_glyphs )
|
---|
| 612 | return;
|
---|
| 613 |
|
---|
| 614 | QFont::Script script = (QFont::Script)si.analysis.script;
|
---|
| 615 | int from = si.position;
|
---|
| 616 | int len = length( item );
|
---|
| 617 |
|
---|
| 618 | Q_ASSERT( len > 0 );
|
---|
| 619 |
|
---|
| 620 | si.glyph_data_offset = used;
|
---|
| 621 |
|
---|
| 622 | if ( !si.fontEngine ) {
|
---|
| 623 | //@@TODO (dmik): remove?
|
---|
| 624 | // if ( hasUsp10 ) {
|
---|
| 625 | // const SCRIPT_PROPERTIES *script_prop = script_properties[si.analysis.script];
|
---|
| 626 | // script = scriptForWinLanguage( script_prop->langid );
|
---|
| 627 | // if ( script == QFont::Latin && script_prop->fAmbiguousCharSet ) {
|
---|
| 628 | // // either some asian language or something Uniscribe doesn't recognise
|
---|
| 629 | // // we look at the first character to find out what it is
|
---|
| 630 | // bool asian = false;
|
---|
| 631 | // int l = length(item);
|
---|
| 632 | // for(int i = 0; i < l; ++i) {
|
---|
| 633 | // if(isAsian(string.unicode()[si.position+i].unicode())) {
|
---|
| 634 | // asian = true;
|
---|
| 635 | // break;
|
---|
| 636 | // }
|
---|
| 637 | // }
|
---|
| 638 | // if (asian) {
|
---|
| 639 | // // some asian language
|
---|
| 640 | // int i;
|
---|
| 641 | // for( i = 0; i < 5; i++ ) {
|
---|
| 642 | // QFontEngine *fe = fnt->engineForScript( tryScripts[i] );
|
---|
| 643 | // if ( fe->type() == QFontEngine::Box )
|
---|
| 644 | // continue;
|
---|
| 645 | //
|
---|
| 646 | // if ( fe->canRender( string.unicode()+from, len ) ) {
|
---|
| 647 | // script = tryScripts[i];
|
---|
| 648 | // break;
|
---|
| 649 | // }
|
---|
| 650 | // }
|
---|
| 651 | // }
|
---|
| 652 | // }
|
---|
| 653 | // }
|
---|
| 654 | si.fontEngine = fnt->engineForScript( script );
|
---|
| 655 | //@@TODO (dmik): remove?
|
---|
| 656 | // if ( si.fontEngine->type() == QFontEngine::Box )
|
---|
| 657 | // si.fontEngine = fnt->engineForScript( QFont::NoScript );
|
---|
| 658 | si.fontEngine->ref();
|
---|
| 659 | }
|
---|
| 660 |
|
---|
| 661 | //@@TODO (dmik): remove?
|
---|
| 662 | // if ( hasUsp10 && si.fontEngine->ttf ) {
|
---|
| 663 | // int l = len;
|
---|
| 664 | // si.analysis.logicalOrder = TRUE;
|
---|
| 665 | // HRESULT res = E_OUTOFMEMORY;
|
---|
| 666 | // HDC hdc = 0;
|
---|
| 667 | //
|
---|
| 668 | // do {
|
---|
| 669 | // ensureSpace( l );
|
---|
| 670 | //
|
---|
| 671 | // res = ScriptShape( hdc, &si.fontEngine->script_cache, (WCHAR *)string.unicode() + from, len,
|
---|
| 672 | // l, &si.analysis, glyphs( &si ), logClusters( &si ), glyphAttributes( &si ),
|
---|
| 673 | // &si.num_glyphs );
|
---|
| 674 | // if ( res == E_PENDING ) {
|
---|
| 675 | // hdc = si.fontEngine->dc();
|
---|
| 676 | // SelectObject( hdc, si.fontEngine->hfont );
|
---|
| 677 | // } else if ( res == USP_E_SCRIPT_NOT_IN_FONT ) {
|
---|
| 678 | // si.analysis.script = 0;
|
---|
| 679 | // hdc = 0;
|
---|
| 680 | // } else if (res == E_OUTOFMEMORY) {
|
---|
| 681 | // l += 32;
|
---|
| 682 | // } else if ( res != S_OK ) {
|
---|
| 683 | // Q_ASSERT( FALSE );
|
---|
| 684 | // }
|
---|
| 685 | // } while( res != S_OK );
|
---|
| 686 | //
|
---|
| 687 | //
|
---|
| 688 | // ABC abc;
|
---|
| 689 | // res = ScriptPlace( hdc, &si.fontEngine->script_cache, glyphs( &si ), si.num_glyphs,
|
---|
| 690 | // glyphAttributes( &si ), &si.analysis, advances( &si ), offsets( &si ), &abc );
|
---|
| 691 | // if ( res == E_PENDING ) {
|
---|
| 692 | // hdc = si.fontEngine->dc();
|
---|
| 693 | // SelectObject( hdc, si.fontEngine->hfont );
|
---|
| 694 | // ScriptPlace( hdc, &si.fontEngine->script_cache, glyphs( &si ), si.num_glyphs,
|
---|
| 695 | // glyphAttributes( &si ), &si.analysis, advances( &si ), offsets( &si ), &abc );
|
---|
| 696 | // }
|
---|
| 697 | // si.width = abc.abcA + abc.abcB + abc.abcC;
|
---|
| 698 | // } else {
|
---|
| 699 | Q_ASSERT( script < QFont::NScripts );
|
---|
| 700 | scriptEngines[script].shape( script, string, from, len, (QTextEngine*)this, &si );
|
---|
| 701 | si.width = 0;
|
---|
| 702 | advance_t *advances = this->advances( &si );
|
---|
| 703 | for ( int i = 0; i < si.num_glyphs; i++ )
|
---|
| 704 | si.width += advances[i];
|
---|
| 705 | //@@TODO (dmik): remove?
|
---|
| 706 | // }
|
---|
| 707 | si.ascent = si.fontEngine->ascent();
|
---|
| 708 | si.descent = si.fontEngine->descent();
|
---|
| 709 |
|
---|
| 710 | ((QTextEngine *)this)->used += si.num_glyphs;
|
---|
| 711 | }
|
---|
| 712 |
|
---|