/****************************************************************************
** $Id: qtextengine_pm.cpp 8 2005-11-16 19:36:46Z dmik $
**
** ???
**
** Copyright (C) 2003 Trolltech AS.  All rights reserved.
** Copyright (C) 2004 Norman ASA.  Initial OS/2 Port.
** Copyright (C) 2005 netlabs.org.  Further OS/2 Development.
**
** This file is part of the kernel module of the Qt GUI Toolkit.
**
** This file may be distributed under the terms of the Q Public License
** as defined by Trolltech AS of Norway and appearing in the file
** LICENSE.QPL included in the packaging of this file.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
** licenses may use this file in accordance with the Qt Commercial License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about Qt Commercial License Agreements.
** See http://www.trolltech.com/qpl/ for QPL licensing information.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

#ifdef QT_THREAD_SUPPORT
#  include <private/qmutexpool_p.h>
#endif // QT_THREAD_SUPPORT
#include "qlibrary.h"


//@@TODO (dmik): remove?
//// these defines are from usp10.h
//typedef void *SCRIPT_CACHE;
//typedef struct tag_SCRIPT_CONTROL {
//    DWORD   uDefaultLanguage    :16;
//    DWORD   fContextDigits      :1;
//    DWORD   fInvertPreBoundDir  :1;
//    DWORD   fInvertPostBoundDir :1;
//    DWORD   fLinkStringBefore   :1;
//    DWORD   fLinkStringAfter    :1;
//    DWORD   fNeutralOverride    :1;
//    DWORD   fNumericOverride    :1;
//    DWORD   fLegacyBidiClass    :1;
//    DWORD   fReserved           :8;
//} SCRIPT_CONTROL;
//
//typedef struct tag_SCRIPT_STATE {
//    WORD    uBidiLevel         :5;
//    WORD    fOverrideDirection :1;
//    WORD    fInhibitSymSwap    :1;
//    WORD    fCharShape         :1;
//    WORD    fDigitSubstitute   :1;
//    WORD    fInhibitLigate     :1;
//    WORD    fDisplayZWG        :1;
//    WORD    fArabicNumContext  :1;
//    WORD    fGcpClusters       :1;
//    WORD    fReserved          :1;
//    WORD    fEngineReserved    :2;
//} SCRIPT_STATE;
//
//typedef struct tag_SCRIPT_ITEM {
//    int              iCharPos;
//    QScriptAnalysis  a;
//} SCRIPT_ITEM;
//
//typedef GlyphAttributes SCRIPT_VISATTR;
//typedef qoffset_t GOFFSET;
//
//#define USP_E_SCRIPT_NOT_IN_FONT   \
//        MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,0x200)    // Script doesn't exist in font
//
//typedef struct {
//  DWORD   langid              :16;
//  DWORD   fNumeric            :1;
//  DWORD   fComplex            :1;
//  DWORD   fNeedsWordBreaking  :1;
//  DWORD   fNeedsCaretInfo     :1;
//  DWORD   bCharSet            :8;
//  DWORD   fControl            :1;
//  DWORD   fPrivateUseArea     :1;
//  DWORD   fNeedsCharacterJustify :1;
//  DWORD   fInvalidGlyph       :1;
//  DWORD   fInvalidLogAttr     :1;
//  DWORD   fCDM                :1;
//  DWORD   fAmbiguousCharSet   :1;
//  DWORD   fClusterSizeVaries  :1;
//  DWORD   fRejectInvalid      :1;
//} SCRIPT_PROPERTIES;
//
//#if defined(Q_OS_TEMP) && UNDER_CE < 400
//typedef struct _ABC {
//  int     abcA;
//  UINT    abcB;
//  int     abcC;
//} ABC;
//#endif
//
//typedef HRESULT (WINAPI *fScriptFreeCache)( SCRIPT_CACHE *);
//typedef HRESULT (WINAPI *fScriptItemize)( const WCHAR *, int, int, const SCRIPT_CONTROL *,
//					  const SCRIPT_STATE *, SCRIPT_ITEM *, int *);
//typedef HRESULT (WINAPI *fScriptShape)( HDC hdc, SCRIPT_CACHE *, const WCHAR *, int, int,
//				        QScriptAnalysis *, WORD *, WORD *, SCRIPT_VISATTR *, int *);
//typedef HRESULT (WINAPI *fScriptPlace)( HDC, SCRIPT_CACHE *, const WORD *, int, const SCRIPT_VISATTR *, QScriptAnalysis *, int *,
//					GOFFSET *, ABC * );
//typedef HRESULT (WINAPI *fScriptTextOut)( const HDC, SCRIPT_CACHE *, int, int, UINT, const RECT *, const QScriptAnalysis *,
//					 const WCHAR *, int, const WORD *, int, const int *, const int *, const GOFFSET *);
//typedef HRESULT (WINAPI *fScriptBreak)( const WCHAR *, int, const QScriptAnalysis *, QCharAttributes * );
////typedef HRESULT (WINAPI *fScriptGetFontProperties)( HDC, SCRIPT_CACHE *, SCRIPT_FONTPROPERTIES * );
//typedef HRESULT (WINAPI *fScriptGetProperties)( const SCRIPT_PROPERTIES ***, int *);
//
//fScriptFreeCache ScriptFreeCache = 0;
//static fScriptItemize ScriptItemize = 0;
//static fScriptShape ScriptShape = 0;
//static fScriptPlace ScriptPlace = 0;
//fScriptTextOut ScriptTextOut = 0;
//static fScriptBreak ScriptBreak = 0;
////static fScriptGetFontProperties ScriptGetFontProperties = 0;
//static fScriptGetProperties ScriptGetProperties = 0;
//
//static bool resolvedUsp10 = FALSE;
//bool hasUsp10 = FALSE;
//
//const SCRIPT_PROPERTIES **script_properties = 0;
//int num_scripts = 0;
//int usp_latin_script = 0;
//
//
//const QFont::Script japanese_tryScripts[] = {
//    QFont::Latin,
//    QFont::Han_Japanese,
//    QFont::Hangul,
//    QFont::Han_SimplifiedChinese,
//    QFont::Han_TraditionalChinese
//};
//
//const QFont::Script korean_tryScripts[] = {
//    QFont::Latin,
//    QFont::Hangul,
//    QFont::Han_Japanese,
//    QFont::Han_SimplifiedChinese,
//    QFont::Han_TraditionalChinese
//};
//
//const QFont::Script simplifiedChinese_tryScripts[] = {
//    QFont::Latin,
//    QFont::Han_SimplifiedChinese,
//    QFont::Han_TraditionalChinese,
//    QFont::Han_Japanese,
//    QFont::Hangul
//};
//
//const QFont::Script traditionalChinese_tryScripts[] = {
//    QFont::Latin,
//    QFont::Han_TraditionalChinese,
//    QFont::Han_SimplifiedChinese,
//    QFont::Han_Japanese,
//    QFont::Hangul
//};
//
//const QFont::Script *tryScripts = japanese_tryScripts;
//
//static void uspAppendItems(QTextEngine *engine, int &start, int &stop, BidiControl &control, QChar::Direction dir);
//
//static void resolveUsp10()
//{
//#ifndef QT_NO_COMPONENT
//    if ( !resolvedUsp10 ) {
//	// need to resolve the security info functions
//
//#ifdef QT_THREAD_SUPPORT
//	// protect initialization
//	QMutexLocker locker( qt_global_mutexpool ?
//			     qt_global_mutexpool->get( (void*)&resolveUsp10 ) : 0 );
//	// check triedResolve again, since another thread may have already
//	// done the initialization
//	if ( resolvedUsp10 ) {
//	    // another thread did initialize the security function pointers,
//	    // so we shouldn't do it again.
//	    return;
//	}
//#endif
//
//	resolvedUsp10 = TRUE;
//	QLibrary lib("usp10");
//	lib.setAutoUnload( FALSE );
//
//	ScriptFreeCache = (fScriptFreeCache) lib.resolve( "ScriptFreeCache" );
//	ScriptItemize = (fScriptItemize) lib.resolve( "ScriptItemize" );
//	ScriptShape = (fScriptShape) lib.resolve( "ScriptShape" );
//	ScriptPlace = (fScriptPlace) lib.resolve( "ScriptPlace" );
//	ScriptTextOut = (fScriptTextOut) lib.resolve( "ScriptTextOut" );
//	ScriptBreak = (fScriptBreak) lib.resolve( "ScriptBreak" );
//	ScriptGetProperties = (fScriptGetProperties) lib.resolve( "ScriptGetProperties" );
//
//	if ( !ScriptFreeCache )
//	    return;
//
//	hasUsp10 = TRUE;
//	ScriptGetProperties( &script_properties, &num_scripts );
//
//	// get the usp script for western
//	for( int i = 0; i < num_scripts; i++ ) {
//	    if (script_properties[i]->langid == LANG_ENGLISH &&
//		!script_properties[i]->fAmbiguousCharSet ) {
//		usp_latin_script = i;
//		break;
//	    }
//	}
//
//	// initialize tryScripts according to locale
//	LANGID lid = GetUserDefaultLangID();
//	switch( lid&0xff ) {
//	case LANG_CHINESE: // Chinese (Taiwan)
//	    if ( lid == 0x0804 ) // Taiwan
//		tryScripts = traditionalChinese_tryScripts;
//	    else
//	    	tryScripts = simplifiedChinese_tryScripts;
//	    break;
//	case LANG_JAPANESE:
//	    // japanese is already the default
//	    break;
//	case LANG_KOREAN:
//		tryScripts = korean_tryScripts;
//		break;
//	default:
//	    break;
//	}
//
//	appendItems = uspAppendItems;
//    }
//#endif
//}
//
//static unsigned char script_for_win_language[ 0x80 ] = {
//    //0x00 LANG_NEUTRAL Neutral
//    QFont::Latin,
//    //0x01 LANG_ARABIC Arabic
//    QFont::Arabic,
//    //0x02 LANG_BULGARIAN Bulgarian
//    QFont::NScripts,
//    //0x03 LANG_CATALAN Catalan
//    QFont::NScripts,
//    //0x04 LANG_CHINESE Chinese
//    QFont::Han,
//    //0x05 LANG_CZECH Czech
//    QFont::NScripts,
//    //0x06 LANG_DANISH Danish
//    QFont::NScripts,
//    //0x07 LANG_GERMAN German
//    QFont::NScripts,
//    //0x08 LANG_GREEK Greek
//    QFont::Greek,
//    //0x09 LANG_ENGLISH English
//    QFont::Latin,
//    //0x0a LANG_SPANISH Spanish
//    QFont::NScripts,
//    //0x0b LANG_FINNISH Finnish
//    QFont::NScripts,
//    //0x0c LANG_FRENCH French
//    QFont::NScripts,
//    //0x0d LANG_HEBREW Hebrew
//    QFont::Hebrew,
//    //0x0e LANG_HUNGARIAN Hungarian
//    QFont::NScripts,
//    //0x0f LANG_ICELANDIC Icelandic
//    QFont::NScripts,
//
//    //0x10 LANG_ITALIAN Italian
//    QFont::NScripts,
//    //0x11 LANG_JAPANESE Japanese
//    QFont::Hiragana,
//    //0x12 LANG_KOREAN Korean
//    QFont::Hangul,
//    //0x13 LANG_DUTCH Dutch
//    QFont::NScripts,
//    //0x14 LANG_NORWEGIAN Norwegian
//    QFont::NScripts,
//    //0x15 LANG_POLISH Polish
//    QFont::NScripts,
//    //0x16 LANG_PORTUGUESE Portuguese
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x18 LANG_ROMANIAN Romanian
//    QFont::NScripts,
//    //0x19 LANG_RUSSIAN Russian
//    QFont::Cyrillic,
//    //0x1a LANG_CROATIAN Croatian
//    //0x1a LANG_SERBIAN Serbian
//    QFont::NScripts,
//    //0x1b LANG_SLOVAK Slovak
//    QFont::NScripts,
//    //0x1c LANG_ALBANIAN Albanian
//    QFont::NScripts,
//    //0x1d LANG_SWEDISH Swedish
//    QFont::NScripts,
//    //0x1e LANG_THAI Thai
//    QFont::Thai,
//    //0x1f LANG_TURKISH Turkish
//    QFont::NScripts,
//
//    //0x20 LANG_URDU Urdu
//    QFont::NScripts,
//    //0x21 LANG_INDONESIAN Indonesian
//    QFont::NScripts,
//    //0x22 LANG_UKRAINIAN Ukrainian
//    QFont::NScripts,
//    //0x23 LANG_BELARUSIAN Belarusian
//    QFont::NScripts,
//    //0x24 LANG_SLOVENIAN Slovenian
//    QFont::NScripts,
//    //0x25 LANG_ESTONIAN Estonian
//    QFont::NScripts,
//    //0x26 LANG_LATVIAN Latvian
//    QFont::NScripts,
//    //0x27 LANG_LITHUANIAN Lithuanian
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x29 LANG_FARSI Farsi
//    QFont::NScripts,
//    //0x2a LANG_VIETNAMESE Vietnamese
//    QFont::Latin, // ##### maybe use QFont::CombiningMarks instead?
//    //0x2b LANG_ARMENIAN Armenian
//    QFont::Armenian,
//    //0x2c LANG_AZERI Azeri
//    QFont::NScripts,
//    //0x2d LANG_BASQUE Basque
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x2f LANG_MACEDONIAN FYRO Macedonian
//    QFont::NScripts,
//
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x36 LANG_AFRIKAANS Afrikaans
//    QFont::NScripts,
//    //0x37 LANG_GEORGIAN Georgian
//    QFont::NScripts,
//    //0x38 LANG_FAEROESE Faeroese
//    QFont::NScripts,
//    //0x39 LANG_HINDI Hindi
//    QFont::Devanagari,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x3e LANG_MALAY Malay
//    QFont::NScripts,
//    //0x3f LANG_KAZAK Kazak
//    QFont::NScripts,
//
//    //0x40 LANG_KYRGYZ Kyrgyz
//    QFont::NScripts,
//    //0x41 LANG_SWAHILI Swahili
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x43 LANG_UZBEK Uzbek
//    QFont::NScripts,
//    //0x44 LANG_TATAR Tatar
//    QFont::NScripts,
//    //0x45 LANG_BENGALI Not supported.
//    QFont::Bengali,
//    //0x46 LANG_PUNJABI Punjabi
//    QFont::Gurmukhi,
//    //0x47 LANG_GUJARATI Gujarati
//    QFont::Gujarati,
//    //0x48 LANG_ORIYA Not supported.
//    QFont::Oriya,
//    //0x49 LANG_TAMIL Tamil
//    QFont::Tamil,
//    //0x4a LANG_TELUGU Telugu
//    QFont::Telugu,
//    //0x4b LANG_KANNADA Kannada
//    QFont::Kannada,
//    //0x4c LANG_MALAYALAM Not supported.
//    QFont::Malayalam,
//    //0x4d LANG_ASSAMESE Not supported.
//    QFont::NScripts,
//    //0x4e LANG_MARATHI Marathi
//    QFont::NScripts,
//    //0x4f LANG_SANSKRIT Sanskrit
//    QFont::Devanagari,
//
//    //0x50 LANG_MONGOLIAN Mongolian
//    QFont::Mongolian,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x56 LANG_GALICIAN Galician
//    QFont::NScripts,
//    //0x57 LANG_KONKANI Konkani
//    QFont::NScripts,
//    //0x58 LANG_MANIPURI Not supported.
//    QFont::NScripts,
//    //0x59 LANG_SINDHI Not supported.
//    QFont::NScripts,
//    //0x5a LANG_SYRIAC Syriac
//    QFont::Syriac,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//
//    //0x60 LANG_KASHMIRI Not supported.
//    QFont::NScripts,
//    //0x61 LANG_NEPALI Not supported.
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x65 LANG_DIVEHI Divehi
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    QFont::NScripts,
//    //0x7f LANG_INVARIANT
//    QFont::NScripts,
//};
//
//static inline QFont::Script scriptForWinLanguage( DWORD langid )
//{
//    QFont::Script script = (QFont::Script)script_for_win_language[langid];
//    if ( script == QFont::NScripts )
//	qWarning( "Qt Uniscribe support: Encountered unhandled language id %x", (unsigned int)langid );
//    return script;
//}
//
//static inline bool isAsian( unsigned short ch )
//{
//    return (ch > 0x2dff && ch < 0xfb00) || ((ch & 0xff00) == 0x1100);
//}
//
//
//// we're not using Uniscribe's BiDi algorithm, since it is (a) not 100% Unicode compliant and
//// (b) seems to work wrongly when trying to use it with a base level != 0.
////
//// This function does uses Uniscribe to do the script analysis and creates items from this.
//static void uspAppendItems(QTextEngine *engine, int &start, int &stop, BidiControl &control, QChar::Direction dir)
//{
//    QScriptItemArray &items = engine->items;
//    const QChar *text = engine->string.unicode();
//
//    if ( start > stop ) {
//	// #### the algorithm is currently not really safe against this. Still needs fixing.
//// 	qWarning( "Bidi: appendItems() internal error" );
//	return;
//    }
//
//    int level = control.level();
//
//    if(dir != QChar::DirON) {
//	// add level of run (cases I1 & I2)
//	if( level % 2 ) {
//	    if(dir == QChar::DirL || dir == QChar::DirAN || dir == QChar::DirEN )
//		level++;
//	} else {
//	    if( dir == QChar::DirR )
//		level++;
//	    else if( dir == QChar::DirAN || dir == QChar::DirEN )
//		level += 2;
//	}
//    }
//
//    SCRIPT_ITEM s_items[256];
//    SCRIPT_ITEM *usp_items = s_items;
//
//    int numItems;
//    HRESULT res = ScriptItemize( (WCHAR *)(text+start), stop-start+1, 255, 0, 0, usp_items, &numItems );
//
//    if ( res == E_OUTOFMEMORY ) {
//	int alloc = 256;
//	usp_items = 0;
//	while( res == E_OUTOFMEMORY ) {
//	    alloc *= 2;
//	    usp_items = (SCRIPT_ITEM *)realloc( usp_items, alloc * sizeof( SCRIPT_ITEM ) );
//	    res = ScriptItemize( (WCHAR *)(text+start), stop-start+1, alloc-1, 0, 0, usp_items, &numItems );
//	}
//    }
//    items.resize( items.size() + numItems );
//    int i;
//    for( i = 0; i < numItems; i++ ) {
//	QScriptItem item;
//	item.analysis = usp_items[i].a;
//	item.position = usp_items[i].iCharPos+start;
//	item.analysis.bidiLevel = level;
//	item.analysis.override = control.override();
//
//	int rstart = usp_items[i].iCharPos;
//	int rstop = usp_items[i+1].iCharPos-1;
//	bool b = TRUE;
//	for ( int j = rstart; j <= rstop; j++ ) {
//
//	    unsigned short uc = text[j+start].unicode();
//	    QChar::Category category = ::category( uc );
//	    if ( uc == 0xfffcU || uc == 0x2028U ) {
//		item.analysis.script = usp_latin_script;
//		item.isObject = TRUE;
//		b = TRUE;
//	    } else if ((uc >= 9 && uc <=13) ||
//		       (category >= QChar::Separator_Space && category <= QChar::Separator_Paragraph)) {
//		item.analysis.script = usp_latin_script;
//		item.isSpace = TRUE;
//		item.isTab = (uc == '\t');
//		if (item.isTab)
//		    item.analysis.bidiLevel = control.baseLevel();
//		b = TRUE;
//	    } else if (b) {
//		b = FALSE;
//	    } else {
//		continue;
//	    }
//
//	    item.position = j+start;
//	    items.append( item );
//	    item.analysis = usp_items[i].a;
//	    item.analysis.bidiLevel = level;
//	    item.analysis.override = control.override();
//	    item.isSpace = item.isTab = item.isObject = FALSE;
//	}
//    }
//
//    if ( usp_items != s_items )
//	free( usp_items );
//
//    ++stop;
//    start = stop;
//}


// -----------------------------------------------------------------------------------------------------
//
// Text engine classes
//
// -----------------------------------------------------------------------------------------------------


QScriptItemArray::~QScriptItemArray()
{
    clear();
    free( d );
}

void QScriptItemArray::clear()
{
    if ( d ) {
	for ( unsigned int i = 0; i < d->size; i++ ) {
	    QScriptItem &si = d->items[i];
	    if ( si.fontEngine )
		si.fontEngine->deref();
	}
	d->size = 0;
    }
}

void QScriptItemArray::resize( int s )
{
    int alloc = ((s + 8) >> 3) << 3;
    d = (QScriptItemArrayPrivate *)realloc( d, sizeof( QScriptItemArrayPrivate ) +
		 sizeof( QScriptItem ) * alloc );
    d->alloc = alloc;
}


void QTextEngine::shape( int item ) const
{
    QScriptItem &si = items[item];

    if ( si.num_glyphs )
	return;

    QFont::Script script = (QFont::Script)si.analysis.script;
    int from = si.position;
    int len = length( item );

    Q_ASSERT( len > 0 );

    si.glyph_data_offset = used;

    if ( !si.fontEngine ) {
//@@TODO (dmik): remove?
//	if ( hasUsp10 ) {
//	    const SCRIPT_PROPERTIES *script_prop = script_properties[si.analysis.script];
//	    script = scriptForWinLanguage( script_prop->langid );
//	    if ( script == QFont::Latin && script_prop->fAmbiguousCharSet ) {
//		// either some asian language or something Uniscribe doesn't recognise
//		// we look at the first character to find out what it is
//		bool asian = false;
//		int l = length(item);
//		for(int i = 0; i < l; ++i) {
//		    if(isAsian(string.unicode()[si.position+i].unicode())) {
//			asian = true;
//			break;
//		    }
//		}
//		if (asian) {
//		    // some asian language
//		    int i;
//		    for( i = 0; i < 5; i++ ) {
//			QFontEngine *fe = fnt->engineForScript( tryScripts[i] );
//			if ( fe->type() == QFontEngine::Box )
//			    continue;
//
//			if ( fe->canRender( string.unicode()+from, len ) ) {
//			    script = tryScripts[i];
//    			    break;
//			}
//		    }
//		}
//	    }
//	}
	si.fontEngine = fnt->engineForScript( script );
//@@TODO (dmik): remove?
//	if ( si.fontEngine->type() == QFontEngine::Box )
//	    si.fontEngine = fnt->engineForScript( QFont::NoScript );
	si.fontEngine->ref();
    }

//@@TODO (dmik): remove?
//    if ( hasUsp10 && si.fontEngine->ttf ) {
//	int l = len;
//	si.analysis.logicalOrder = TRUE;
//	HRESULT res = E_OUTOFMEMORY;
//	HDC hdc = 0;
//
//	do {
//	    ensureSpace( l );
//
//	    res = ScriptShape( hdc, &si.fontEngine->script_cache, (WCHAR *)string.unicode() + from, len,
//			       l, &si.analysis, glyphs( &si ), logClusters( &si ), glyphAttributes( &si ),
//			       &si.num_glyphs );
//	    if ( res == E_PENDING ) {
//		hdc = si.fontEngine->dc();
//		SelectObject( hdc, si.fontEngine->hfont );
//	    } else if ( res == USP_E_SCRIPT_NOT_IN_FONT ) {
//		si.analysis.script = 0;
//		hdc = 0;
//	    } else if (res == E_OUTOFMEMORY) {
//		l += 32;
//	    } else if ( res != S_OK ) {
//		Q_ASSERT( FALSE );
//	    }
//	} while( res != S_OK );
//
//
//	ABC abc;
//	res = ScriptPlace( hdc, &si.fontEngine->script_cache, glyphs( &si ), si.num_glyphs,
//		           glyphAttributes( &si ), &si.analysis, advances( &si ), offsets( &si ), &abc );
//	if ( res == E_PENDING ) {
//	    hdc = si.fontEngine->dc();
//	    SelectObject( hdc, si.fontEngine->hfont );
//	    ScriptPlace( hdc, &si.fontEngine->script_cache, glyphs( &si ), si.num_glyphs,
//		         glyphAttributes( &si ), &si.analysis, advances( &si ), offsets( &si ), &abc );
//	}
//	si.width = abc.abcA + abc.abcB + abc.abcC;
//    } else {
	Q_ASSERT( script < QFont::NScripts );
	scriptEngines[script].shape( script, string, from, len, (QTextEngine*)this, &si );
	si.width = 0;
	advance_t *advances = this->advances( &si );
	for ( int i = 0; i < si.num_glyphs; i++ )
	    si.width += advances[i];
//@@TODO (dmik): remove?
//    }
    si.ascent = si.fontEngine->ascent();
    si.descent = si.fontEngine->descent();

    ((QTextEngine *)this)->used += si.num_glyphs;
}

