/****************************************************************************
** $Id: qfontdatabase.cpp 8 2005-11-16 19:36:46Z dmik $
**
** Implementation of font database class.
**
** Created : 990603
**
** Copyright (C) 1999-2000 Trolltech AS.  All rights reserved.
**
** 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.
**
**********************************************************************/

#include "qfontdatabase.h"

#ifndef QT_NO_FONTDATABASE

#include <qtl.h>
#include <qapplication.h>

#include <private/qunicodetables_p.h>
#include "qfontengine_p.h"

#include <qcleanuphandler.h>

#ifdef Q_WS_X11
#include <locale.h>
#endif
#include <stdlib.h>

// #define QFONTDATABASE_DEBUG
#ifdef QFONTDATABASE_DEBUG
#  define FD_DEBUG qDebug
#else
#  define FD_DEBUG if (FALSE) qDebug
#endif

// #define FONT_MATCH_DEBUG
#ifdef FONT_MATCH_DEBUG
#  define FM_DEBUG qDebug
#else
#  define FM_DEBUG if (FALSE) qDebug
#endif

#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
#  define for if(0){}else for
#endif

#define SMOOTH_SCALABLE 0xffff

static int ucstricmp( const QString &as, const QString &bs )
{
    const QChar *a = as.unicode();
    const QChar *b = bs.unicode();
    if ( a == b )
	return 0;
    if ( a == 0 )
	return 1;
    if ( b == 0 )
	return -1;
    int l=QMIN(as.length(),bs.length());
    while ( l-- && ::lower( *a ) == ::lower( *b ) )
	a++,b++;
    if ( l==-1 )
	return ( as.length()-bs.length() );
    return ::lower( *a ).unicode() - ::lower( *b ).unicode();
}

static int getFontWeight( const QString &weightString )
{
    QString s = weightString.lower();

    // Test in decreasing order of commonness
    if (s == "medium" ||
	s == "normal")
	return QFont::Normal;
    if (s == "bold")
	return QFont::Bold;
    if (s == "demibold" || s == "demi bold")
	return QFont::DemiBold;
    if (s == "black")
	return QFont::Black;
    if (s == "light")
	return QFont::Light;

    if (s.contains("bold")) {
	if (s.contains("demi"))
	    return (int) QFont::DemiBold;
	return (int) QFont::Bold;
    }

    if (s.contains("light"))
	return (int) QFont::Light;

    if (s.contains("black"))
	return (int) QFont::Black;

    return (int) QFont::Normal;
}

#ifdef Q_WS_X11
struct QtFontEncoding
{
    signed int encoding : 16;

    uint xpoint   : 16;
    uint xres     : 8;
    uint yres     : 8;
    uint avgwidth : 16;
    uchar pitch   : 8;
};
#endif // Q_WS_X11

struct QtFontSize
{
    unsigned short pixelSize;

#ifdef Q_WS_PM
    unsigned short pointSize;                   // in deca-points
    LONG lMatch;
#endif
#ifdef Q_WS_X11
    int count;
    QtFontEncoding *encodings;
    QtFontEncoding *encodingID( int id, uint xpoint = 0, uint xres = 0,
				uint yres = 0, uint avgwidth = 0, bool add = FALSE);
#endif // Q_WS_X11
};


#ifdef Q_WS_X11
QtFontEncoding *QtFontSize::encodingID( int id, uint xpoint, uint xres,
					uint yres, uint avgwidth, bool add )
{
    // we don't match using the xpoint, xres and yres parameters, only the id
    for ( int i = 0; i < count; ++i ) {
	if ( encodings[i].encoding == id )
	    return encodings + i;
    }

    if ( !add ) return 0;

    if ( !(count % 4) )
	encodings = ( QtFontEncoding * )
		    realloc( encodings,
			     (((count+4) >> 2 ) << 2 ) * sizeof( QtFontEncoding ) );
    encodings[count].encoding = id;
    encodings[count].xpoint = xpoint;
    encodings[count].xres = xres;
    encodings[count].yres = yres;
    encodings[count].avgwidth = avgwidth;
    encodings[count].pitch = '*';
    return encodings + count++;
}
#endif // Q_WS_X11

struct QtFontStyle
{
    struct Key {
	Key( const QString &styleString );
	Key() : italic( FALSE ), oblique( FALSE ),
		weight( QFont::Normal ), stretch( 0 ) { }
	Key( const Key &o ) : italic( o.italic ), oblique( o.oblique ),
			      weight( o.weight ), stretch( o.stretch ) { }
	uint italic : 1;
	uint oblique : 1;
	signed int  weight : 8;
	signed int stretch : 12;

	bool operator==( const Key & other ) {
	    return ( italic == other.italic &&
		     oblique == other.oblique &&
		     weight == other.weight &&
		     (stretch == 0 || other.stretch == 0 || stretch == other.stretch) );
	}
	bool operator!=( const Key &other ) {
	    return !operator==(other);
	}
	bool operator <( const Key &o ) {
	    int x = (italic << 13) + (oblique << 12) + (weight << 14) + stretch;
	    int y = (o.italic << 13) + (o.oblique << 12) + (o.weight << 14) + o.stretch;
	    return ( x < y );
	}
    };

    QtFontStyle( const Key &k )
	: key( k ), bitmapScalable( FALSE ), smoothScalable( FALSE ),
	  fakeOblique( FALSE ), count( 0 ), pixelSizes( 0 )
    {
#if defined(Q_WS_PM)
        szFacename[0] = 0;
#elif defined(Q_WS_X11)
	weightName = setwidthName = 0;
#endif
    }

    ~QtFontStyle() {
#ifdef Q_WS_X11
	delete [] weightName;
	delete [] setwidthName;
	while ( count-- )
	    free(pixelSizes[count].encodings);
#endif
	free( pixelSizes );
    }

    Key key;
    bool bitmapScalable : 1;
    bool smoothScalable : 1;
    bool fakeOblique    : 1;
    int count           : 29;
    QtFontSize *pixelSizes;

#ifdef Q_WS_PM
    CHAR szFacename [FACESIZE];
#endif
#ifdef Q_WS_X11
    const char *weightName;
    const char *setwidthName;
#endif // Q_WS_X11

#ifdef Q_WS_PM
    QtFontSize *pixelSize(
        unsigned short size, bool = FALSE, unsigned short pointSize = 0 );
#else    
    QtFontSize *pixelSize( unsigned short size, bool = FALSE );
#endif    
};

QtFontStyle::Key::Key( const QString &styleString )
    : italic( FALSE ), oblique( FALSE ), weight( QFont::Normal ), stretch( 0 )
{
    weight = getFontWeight( styleString );

    if ( styleString.contains( "Italic" ) )
	 italic = TRUE;
    else if ( styleString.contains( "Oblique" ) )
	 oblique = TRUE;
}

#ifdef Q_WS_PM
QtFontSize *QtFontStyle::pixelSize(
    unsigned short size, bool add, unsigned short pointSize )
#else
QtFontSize *QtFontStyle::pixelSize( unsigned short size, bool add )
#endif
{
    for ( int i = 0; i < count; i++ ) {
#ifdef Q_WS_PM
	if (
            pixelSizes[i].pixelSize == size &&
            (
                size == SMOOTH_SCALABLE ||
                !pointSize ||
                pixelSizes[i].pointSize == pointSize
            )
        )
#else        
	if ( pixelSizes[i].pixelSize == size )
#endif            
	    return pixelSizes + i;
    }
    if ( !add )
	return 0;

    if ( !(count % 8) )
	pixelSizes = (QtFontSize *)
		     realloc( pixelSizes,
			      (((count+8) >> 3 ) << 3) * sizeof(QtFontSize) );
    pixelSizes[count].pixelSize = size;
#ifdef Q_WS_PM
    pixelSizes[count].pointSize = pointSize;
    pixelSizes[count].lMatch = 0;
#endif
#ifdef Q_WS_X11
    pixelSizes[count].count = 0;
    pixelSizes[count].encodings = 0;
#endif
    return pixelSizes + (count++);
}

struct QtFontFoundry
{
    QtFontFoundry( const QString &n ) : name( n ), count( 0 ), styles( 0 ) {}
    ~QtFontFoundry() {
	while ( count-- )
	    delete styles[count];
	free( styles );
    }

    QString name;

    int count;
    QtFontStyle **styles;
    QtFontStyle *style( const QtFontStyle::Key &,  bool = FALSE );
};

QtFontStyle *QtFontFoundry::style( const QtFontStyle::Key &key, bool create )
{
    int pos = 0;
    if ( count ) {
	int low = 0;
	int high = count;
	pos = count / 2;
	while ( high > low ) {
	    if ( styles[pos]->key == key )
		return styles[pos];
	    if ( styles[pos]->key < key )
		low = pos + 1;
	    else
		high = pos;
	    pos = (high + low) / 2;
	};
	pos = low;
    }
    if ( !create )
	return 0;

//     qDebug("adding key (weight=%d, italic=%d, oblique=%d stretch=%d) at %d",  key.weight, key.italic, key.oblique, key.stretch, pos );
    if ( !(count % 8) )
	styles = (QtFontStyle **)
		 realloc( styles, (((count+8) >> 3 ) << 3) * sizeof( QtFontStyle * ) );

    memmove( styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *) );
    styles[pos] = new QtFontStyle( key );
    count++;
    return styles[pos];
}


struct QtFontFamily
{
    enum ScriptStatus { Unknown = 0, Supported = 1,
			UnSupported_Xft= 2, UnSupported_Xlfd = 4, UnSupported = 6 };

    QtFontFamily(const QString &n )
	: fixedPitch( FALSE ),
#ifdef Q_WS_X11
	hasXft( FALSE ), xftScriptCheck( FALSE ), xlfdLoaded( FALSE ),
#endif
#ifdef Q_WS_WIN
	scriptCheck( FALSE ),
#endif
#if defined(Q_OS_MAC) && !defined(QWS)
	fixedPitchComputed(FALSE),
#endif
	fullyLoaded( FALSE ),
	  name( n ), count( 0 ), foundries( 0 ) {
	memset( scripts, 0, sizeof( scripts ) );
#ifdef Q_WS_PM
//@@TODO (dmik): temporary solution to let QFontDialog work:
//  at least UnknownScript is supported.
        scripts[QFont::UnknownScript] = Supported;
#endif        
    }
    ~QtFontFamily() {
	while ( count-- )
	    delete foundries[count];
	free( foundries );
    }

    bool fixedPitch : 1;
#ifdef Q_WS_X11
    bool hasXft : 1;
    bool xftScriptCheck : 1;
    bool xlfdLoaded : 1;
#endif
#ifdef Q_WS_WIN
    bool scriptCheck : 1;
#endif
#if defined(Q_OS_MAC) && !defined(QWS)
    bool fixedPitchComputed : 1;
#endif
    bool fullyLoaded : 1;
    QString name;
#ifndef Q_WS_X11
    QString rawName;
#endif    
#ifdef Q_WS_X11
    QCString fontFilename;
    int fontFileIndex;
#endif
    int count;
    QtFontFoundry **foundries;

    unsigned char scripts[QFont::LastPrivateScript];

    QtFontFoundry *foundry( const QString &f, bool = FALSE );
};

QtFontFoundry *QtFontFamily::foundry( const QString &f, bool create )
{
    if ( f.isNull() && count == 1 )
	return foundries[0];

    for ( int i = 0; i < count; i++ ) {
	if ( ucstricmp( foundries[i]->name, f ) == 0 )
	    return foundries[i];
    }
    if ( !create )
	return 0;

    if ( !(count % 8) )
	foundries = (QtFontFoundry **)
		    realloc( foundries,
			     (((count+8) >> 3 ) << 3) * sizeof( QtFontFoundry * ) );

    foundries[count] = new QtFontFoundry( f );
    return foundries[count++];
}

class QFontDatabasePrivate {
public:
    QFontDatabasePrivate() : 
        count( 0 ), families( 0 ) { }
    ~QFontDatabasePrivate() {
#ifdef Q_WS_PM
        cleanup();
#else
	while ( count-- )
	    delete families[count];
	free( families );
#endif
    }
    QtFontFamily *family( const QString &f, bool = FALSE );

    int count;
    QtFontFamily **families;

#ifdef Q_WS_PM
    static QFontDatabasePrivate* instance();
private:    
    void cleanup() {
        while ( count )
            delete families[--count];
        free( families );
        families = 0;
    }
    void reload(); 
#endif
};

QtFontFamily *QFontDatabasePrivate::family( const QString &f, bool create )
{
    int low = 0;
    int high = count;
    int pos = count / 2;
    int res = 1;
    if ( count ) {
	while ( (res = ucstricmp( families[pos]->name, f )) && pos != low ) {
	    if ( res > 0 )
		high = pos;
	    else
		low = pos;
	    pos = (high + low) / 2;
	};
	if ( !res )
	    return families[pos];
    }
    if ( !create )
	return 0;

    if ( res < 0 )
	pos++;

    // qDebug("adding family %s at %d total=%d",  f.latin1(), pos, count);
    if ( !(count % 8) )
	families = (QtFontFamily **)
		   realloc( families,
			    (((count+8) >> 3 ) << 3) * sizeof( QtFontFamily * ) );

    memmove( families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *) );
    families[pos] = new QtFontFamily( f );
    count++;
    return families[pos];
}




#if defined(Q_WS_X11) || defined(Q_WS_WIN)
static const unsigned short sample_chars[QFont::LastPrivateScript] =
{
    // European Alphabetic Scripts
    // Latin,
    0x0041,
    // Greek,
    0x0390,
    // Cyrillic,
    0x0410,
    // Armenian,
    0x0540,
    // Georgian,
    0x10d0,
    // Runic,
    0x16a0,
    // Ogham,
    0x1680,
    // SpacingModifiers,
    0x02b0,
    // CombiningMarks,
    0x0300,

    // Middle Eastern Scripts
    // Hebrew,
    0x05d0,
    // Arabic,
    0x0630,
    // Syriac,
    0x0710,
    // Thaana,
    0x0780,

    // South and Southeast Asian Scripts
    // Devanagari,
    0x0910,
    // Bengali,
    0x0990,
    // Gurmukhi,
    0x0a10,
    // Gujarati,
    0x0a90,
    // Oriya,
    0x0b10,
    // Tamil,
    0x0b90,
    // Telugu,
    0x0c10,
    // Kannada,
    0x0c90,
    // Malayalam,
    0x0d10,
    // Sinhala,
    0x0d90,
    // Thai,
    0x0e10,
    // Lao,
    0x0e81,
    // Tibetan,
    0x0f00,
    // Myanmar,
    0x1000,
    // Khmer,
    0x1780,

    // East Asian Scripts
    // Han,
    0x4e00,
    // Hiragana,
    0x3050,
    // Katakana,
    0x30b0,
    // Hangul,
    0xac00,
    // Bopomofo,
    0x3110,
    // Yi,
    0xa000,

    // Additional Scripts
    // Ethiopic,
    0x1200,
    // Cherokee,
    0x13a0,
    // CanadianAboriginal,
    0x1410,
    // Mongolian,
    0x1800,

    // Symbols
    // CurrencySymbols,
    0x20aa,
    // LetterlikeSymbols,
    0x2122,
    // NumberForms,
    0x215b,
    // MathematicalOperators,
    0x222b,
    // TechnicalSymbols,
    0x2440,
    // GeometricSymbols,
    0x2500,
    // MiscellaneousSymbols,
    0x2600,
    // EnclosedAndSquare,
    0x2460,
    // Braille,
    0x2800,

    // Unicode,
    0xfffd,

    // some scripts added in Unicode 3.2
    // Tagalog,
    0x1700,
    // Hanunoo,
    0x1720,
    // Buhid,
    0x1740,
    // Tagbanwa,
    0x1770,

    // KatakanaHalfWidth
    0xff65,

    // Limbu
    0x1901,
    // TaiLe
    0x1950,

    // NScripts
    0x0000,
    // NoScript
    0x0000,

    // Han_Japanese
    0x4e00,
    // Han_SimplifiedChinese,
    0x4e00,
    // Han_TraditionalChinese,
    0x4e00,
    // Han_Korean
    0x4e00
};

#if defined(Q_WS_X11) && !defined(QT_NO_XFTFREETYPE)
static inline bool requiresOpenType(QFont::Script s)
{
    return (s >= QFont::Syriac && s <= QFont::Sinhala)
		 || (s >= QFont::Tibetan && s <= QFont::Khmer);
}
#endif

// returns a sample unicode character for the specified script
static QChar sampleCharacter(QFont::Script script)
{
    return QChar(sample_chars[script]);
}

static inline bool canRender( QFontEngine *fe, QFont::Script script )
{
    if ( !fe ) return FALSE;

    QChar sample = sampleCharacter(script);
    bool hasChar = fe->canRender( &sample, 1 );

#ifdef FONT_MATCH_DEBUG
    if (hasChar)
	FM_DEBUG("    font has char 0x%04x", sample.unicode() );
#endif
#if defined(Q_WS_X11) && !defined(QT_NO_XFTFREETYPE)
    if (hasChar && requiresOpenType(script)) {
	QOpenType *ot = fe->openType();
	if (!ot || !ot->supportsScript(script))
	    return false;
    }
#endif

    return hasChar;
}
#endif // Q_WS_X11 || Q_WS_WIN


static QSingleCleanupHandler<QFontDatabasePrivate> qfontdatabase_cleanup;
#ifdef Q_WS_PM
QFontDatabasePrivate* QFontDatabasePrivate::instance()
{
    static QFontDatabasePrivate *db = 0;
    if ( !db ) {
        db = new QFontDatabasePrivate;
        qfontdatabase_cleanup.set(&db);
        db->reload();
    }
    return db;
}
#else
static QFontDatabasePrivate *db=0;
#endif

#if defined( Q_WS_X11 )
#  include "qfontdatabase_x11.cpp"
#elif defined( Q_WS_MAC )
#  include "qfontdatabase_mac.cpp"
#elif defined( Q_WS_WIN )
#  include "qfontdatabase_win.cpp"
#elif defined( Q_WS_PM )
#  include "qfontdatabase_pm.cpp"
#elif defined( Q_WS_QWS )
#  include "qfontdatabase_qws.cpp"
#endif




#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_PM)
static
unsigned int bestFoundry( QFont::Script script, unsigned int score, int styleStrategy,
			  const QtFontFamily *family, const QString &foundry_name,
			  QtFontStyle::Key styleKey, int pixelSize, char pitch,
			  QtFontFoundry **best_foundry, QtFontStyle **best_style,
			  QtFontSize **best_size
#if defined(Q_WS_X11)
			  , QtFontEncoding **best_encoding, int force_encoding_id
#elif defined(Q_WS_PM)
                          , int pointSize
#endif
			  )
{
    Q_UNUSED( script );
    Q_UNUSED( pitch );

    FM_DEBUG( "  REMARK: looking for best foundry for family '%s'", family->name.latin1() );

    for ( int x = 0; x < family->count; ++x ) {
	QtFontFoundry *foundry = family->foundries[x];
	if ( ! foundry_name.isEmpty() &&
	     ucstricmp( foundry->name, foundry_name ) != 0 )
	    continue;

	FM_DEBUG( "          looking for matching style in foundry '%s'",
		  foundry->name.isEmpty() ? "-- none --" : foundry->name.latin1() );

	QtFontStyle *style = 0;
	int best = 0;
	int dist = 0xffff;

	for ( int i = 0; i < foundry->count; i++ ) {
	    style = foundry->styles[i];

	    int d = QABS( styleKey.weight - style->key.weight );

	    if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
		d += QABS( styleKey.stretch - style->key.stretch );
	    }

	    if ( styleKey.italic ) {
		if ( !style->key.italic )
		    d += style->key.oblique ? 0x0800 : 0x1000;
	    } else if ( styleKey.oblique ) {
		if (!style->key.oblique )
		    d += style->key.italic ? 0x0800 : 0x1000;
	    } else if ( style->key.italic || style->key.oblique ) {
		d += 0x1000;
	    }

	    if ( d < dist ) {
		best = i;
		dist = d;
	    }
	}

	FM_DEBUG( "          best style has distance 0x%x", dist );
	style = foundry->styles[best];

	if ( ! style->smoothScalable && ( styleStrategy & QFont::ForceOutline ) ) {
	    FM_DEBUG( "            ForceOutline set, but not smoothly scalable" );
	    continue;
	}

	int px = -1;
	QtFontSize *size = 0;

	// 1. see if we have an exact matching size
	if (! (styleStrategy & QFont::ForceOutline)) {
#if defined(Q_WS_PM)
	    size = style->pixelSize(pixelSize, FALSE, pointSize);
#else            
	    size = style->pixelSize(pixelSize);
#endif            
	    if (size) px = size->pixelSize;
	}

	// 2. see if we have a smoothly scalable font
	if (! size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
	    size = style->pixelSize(SMOOTH_SCALABLE);
	    if (size) px = pixelSize;
	}

	// 3. see if we have a bitmap scalable font
	if (! size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
	    size = style->pixelSize(0);
	    if (size) px = pixelSize;
	}

	// 4. find closest size match
	if (! size) {
	    unsigned int distance = ~0u;
	    for (int x = 0; x < style->count; ++x) {
		unsigned int d = QABS(style->pixelSizes[x].pixelSize - pixelSize);
		if (d < distance) {
		    distance = d;
		    size = style->pixelSizes + x;
		}
	    }

	    if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
		(distance * 10 / pixelSize) >= 2) {
		// the closest size is not close enough, go ahead and
		// use a bitmap scaled font
		size = style->pixelSize(0);
		px = pixelSize;
	    } else {
		px = size->pixelSize;
	    }
	}

#ifdef Q_WS_X11
	QtFontEncoding *encoding = 0;
	if ( force_encoding_id >= 0 ) {
	    encoding = size->encodingID( force_encoding_id );
	    if ( ! encoding ) {
		FM_DEBUG( "            required encoding_id not available" );
		continue;
	    }
	} else {
	    encoding = size->encodingID( -1 ); // -1 == prefer Xft

	    if ( encoding && ( styleStrategy & ( QFont::OpenGLCompatible |
						 QFont::PreferBitmap ) ) ) {
		FM_DEBUG( "            PreferBitmap and/or OpenGL set, skipping Xft" );
		continue;
	    }

	    if ( ! encoding ) { // Xft not available, find an XLFD font
		// try the default encoding first
		encoding = size->encodingID( QFontPrivate::defaultEncodingID );

		if ( ! encoding || ! scripts_for_xlfd_encoding[encoding->encoding][script] ) {
		    // find the first encoding that supports the requested script
		    encoding = 0;
		    for (int x = 0; !encoding && x < size->count; ++x ) {
			const int enc = size->encodings[x].encoding;
			if ( scripts_for_xlfd_encoding[enc][script] ) {
			    encoding = &size->encodings[x];
			    break;
			}
		    }
		}
	    }
	}

	if ( ! encoding ) {
	    FM_DEBUG( "          foundry doesn't support the script we want" );
	    continue;
	}
#endif // Q_WS_X11

	unsigned int this_score = 0x0000;
#ifdef Q_WS_X11
	if ( encoding->encoding != -1 ) {
	    this_score += 1;
	    if ( encoding->encoding != QFontPrivate::defaultEncodingID )
		this_score += 10;
	}
 	if (pitch != '*') {
 	    if ( !( pitch == 'm' && encoding->pitch == 'c' ) && pitch != encoding->pitch )
 		this_score += 200;
 	}
#else
	if (pitch != '*') {
	    if ((pitch == 'm' && !family->fixedPitch)
		|| (pitch == 'p' && family->fixedPitch))
		this_score += 200;
	}
#endif
	if ( styleKey != style->key )
	    this_score += 100;
	if ( !style->smoothScalable && px != size->pixelSize ) // bitmap scaled
	    this_score += 50;

	if ( this_score < score ) {
	    FM_DEBUG( "          found a match: score %u best score so far %u",
		      this_score, score );

	    score = this_score;
	    *best_foundry = foundry;
	    *best_style = style;
	    *best_size = size;
#ifdef Q_WS_X11
	    *best_encoding = encoding;
#endif // Q_WS_X11
	} else {
	    FM_DEBUG( "          score %u no better than best %u", this_score, score);
	}
    }

    return score;
}

/*!
    \internal
*/
QFontEngine *
QFontDatabase::findFont( QFont::Script script, const QFontPrivate *fp,
			 const QFontDef &request, int force_encoding_id )
{
#ifndef Q_WS_X11
    Q_UNUSED( force_encoding_id );
#endif

#ifdef Q_WS_PM
    QFontDatabasePrivate *db = QFontDatabasePrivate::instance();
#else    
    if ( !db )
	initializeDb();
#endif

    QFontEngine *fe = 0;
    if ( fp ) {
#ifndef Q_WS_PM
	if ( fp->rawMode ) {
	    fe = loadEngine( script, fp, request, 0, 0, 0
#ifdef Q_WS_X11
			     , 0, 0, FALSE
#endif
		);

	    // if we fail to load the rawmode font, use a 12pixel box engine instead
	    if (! fe) fe = new QFontEngineBox( 12 );
	    return fe;
	}
#endif // !Q_WS_PM

	QFontCache::Key key( request, script,
#if defined(Q_WS_WIN) || defined(Q_WS_PM)
			     (int)fp->paintdevice
#else
			     fp->screen
#endif
	    );
	fe = QFontCache::instance->findEngine( key );
	if ( fe ) return fe;
    }

    QString family_name, foundry_name;
    QtFontStyle::Key styleKey;
    styleKey.italic = request.italic;
    styleKey.weight = request.weight;
    styleKey.stretch = request.stretch;
    char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';

    parseFontName( request.family, foundry_name, family_name );

#ifdef Q_WS_PM
    // the "System VIO" PM font is broken in such way that its real pixel
    // sizes do not correspond to their nominal point sizes specified in the
    // font header (i.e. pixelSize is not equal to (pointSize * dpi) / 720).
    // therefore we use the special table to convert pointSize to pixelSize
    // in order to let bestFoundry() select the proper font with its nominal
    // point size corresponding to the requested one.
    // NOTE: this will produce incorrect results if "System VIO" is NOT
    // an OS/2 standatd supplied bitmap font.
    if( !ucstricmp( family_name, "System VIO") ) {
        // possible sizes of the "System VIO" font ("pixel, point" pairs),
        // sorted by point size
        static const short SystemVIO_sz[] = {
            12, 20,         16, 30,
            8,  40,         13, 50,
            15, 60,         24, 70,
            8,  80,         10, 90,
            12, 100,        14, 110,
            16, 120,        18, 130,
            16, 140,        12, 150,
            20, 160,        21, 170,
            29, 180,
        };
        const int SystemVIO_sz_len = sizeof(SystemVIO_sz) / sizeof(SystemVIO_sz[0]);
        int pt = request.pointSize;
        pt = QMAX( pt, SystemVIO_sz [1] );                      // min limit 
        pt = QMIN( pt, SystemVIO_sz [SystemVIO_sz_len - 1] );   // max limit
        int i = 1;
        while ( SystemVIO_sz[i] < pt ) i += 2;
        if ( SystemVIO_sz[i] > pt ) {
            int prev = SystemVIO_sz[i-2];
            int mid = prev + (SystemVIO_sz[i] - prev + 1) / 2;
            if ( pt < mid ) i -= 2; 
        }
        ((QFontDef&)request).pixelSize = SystemVIO_sz[i-1];
        ((QFontDef&)request).pointSize = SystemVIO_sz[i];
    }
#endif
    
#ifdef Q_WS_X11
    if (family_name.isEmpty() && script == QFont::Han) {
	// modify script according to locale
	static QFont::Script defaultHan = QFont::UnknownScript;
	if (defaultHan == QFont::UnknownScript) {
	    QCString locale = setlocale(LC_ALL, NULL);
	    if (locale.contains("ko"))
		defaultHan = QFont::Han_Korean;
	    else if (locale.contains("zh_TW"))
		defaultHan = QFont::Han_TraditionalChinese;
	    else if (locale.contains("zh"))
		defaultHan = QFont::Han_SimplifiedChinese;
	    else
		defaultHan = QFont::Han_Japanese;
	}
	script = defaultHan;
    }
#endif

    FM_DEBUG( "QFontDatabase::findFont\n"
	      "  request:\n"
	      "    family: %s [%s], script: %d (%s)\n"
	      "    weight: %d, italic: %d\n"
	      "    stretch: %d\n"
	      "    pixelSize: %d\n"
	      "    pointSize: %d\n"
	      "    pitch: %c",
	      family_name.isEmpty() ? "-- first in script --" : family_name.latin1(),
	      foundry_name.isEmpty() ? "-- any --" : foundry_name.latin1(),
	      script, scriptName( script ).latin1(),
	      request.weight, request.italic, request.stretch,
	      request.pixelSize, request.pointSize,
	      pitch );

#ifdef QT_XFT2
    if (family_name.isEmpty()
	|| family_name == "Sans Serif"
	|| family_name == "Serif"
	|| family_name == "Monospace") {
	fe = loadFontConfigFont(fp, request, script);
    }
    if (!fe)
#endif
    {
	QtFontFamily *best_family = 0;
	QtFontFoundry *best_foundry = 0;
	QtFontStyle *best_style = 0;
	QtFontSize *best_size = 0;
#ifdef Q_WS_X11
	QtFontEncoding *best_encoding = 0;
#endif // Q_WS_X11

	unsigned int score = ~0;

	load( family_name, script );

	for ( int x = 0; x < db->count; ++x ) {
	    QtFontFamily *try_family = db->families[x];
	    if ( !family_name.isEmpty() &&
		 ucstricmp( try_family->name, family_name ) != 0 )
		continue;

	    if ( family_name.isEmpty() )
		load( try_family->name, script );

	    uint score_adjust = 0;
	    QFont::Script override_script = script;
#ifndef Q_WS_PM
	    if ( ! ( try_family->scripts[script] & QtFontFamily::Supported )
		 && script != QFont::Unicode) {
		// family not supported in the script we want
#ifdef Q_WS_X11
		if (script >= QFont::Han_Japanese && script <= QFont::Han_Korean
		    && try_family->scripts[QFont::Han] == QtFontFamily::Supported) {
		    // try with the han script instead, give it a penalty
		    if (override_script == QFont::Han_TraditionalChinese
			&& (try_family->scripts[QFont::Han_SimplifiedChinese] & QtFontFamily::Supported)) {
			override_script = QFont::Han_SimplifiedChinese;
			score_adjust = 200;
		    } else if (override_script == QFont::Han_SimplifiedChinese
			&& (try_family->scripts[QFont::Han_TraditionalChinese] & QtFontFamily::Supported)) {
			override_script = QFont::Han_TraditionalChinese;
			score_adjust = 200;
		    } else {
			override_script = QFont::Han;
			score_adjust = 400;
		    }
		} else
#endif
		if (family_name.isEmpty()) {
		    continue;
		} else if (try_family->scripts[QFont::UnknownScript] & QtFontFamily::Supported) {
		    // try with the unknown script (for a symbol font)
		    override_script = QFont::UnknownScript;
		} else if (try_family->scripts[QFont::Unicode] & QtFontFamily::Supported) {
		    // try with the unicode script instead
		    override_script = QFont::Unicode;
		} else {
		    // family not supported by unicode/unknown scripts
		    continue;
		}
	    }
#endif // !Q_WS_PM

	    QtFontFoundry *try_foundry = 0;
	    QtFontStyle *try_style = 0;
	    QtFontSize *try_size = 0;
#ifdef Q_WS_X11
	    QtFontEncoding *try_encoding = 0;
#endif // Q_WS_X11

	    // as we know the script is supported, we can be sure
	    // to find a matching font here.
	    unsigned int newscore =
		bestFoundry( override_script, score, request.styleStrategy,
			     try_family, foundry_name, styleKey, request.pixelSize, pitch,
			     &try_foundry, &try_style, &try_size
#if defined(Q_WS_X11)
			     , &try_encoding, force_encoding_id
#elif defined(Q_WS_PM)
                             , request.pointSize
#endif
		    );
	    if ( try_foundry == 0 ) {
		// the specific foundry was not found, so look for
		// any foundry matching our requirements
		newscore = bestFoundry( override_script, score, request.styleStrategy, try_family,
					QString::null, styleKey, request.pixelSize,
					pitch, &try_foundry, &try_style, &try_size
#if defined(Q_WS_X11)
					, &try_encoding, force_encoding_id
#elif defined(Q_WS_PM)
                                        , request.pointSize
#endif
		    );
	    }
	    newscore += score_adjust;

	    if ( newscore < score ) {
		score = newscore;
		best_family = try_family;
		best_foundry = try_foundry;
		best_style = try_style;
		best_size = try_size;
#ifdef Q_WS_X11
		best_encoding = try_encoding;
#endif // Q_WS_X11
	    }
	    if ( newscore < 10 ) // xlfd instead of xft... just accept it
		break;
	}

	if ( best_family != 0 && best_foundry != 0 && best_style != 0
#ifdef Q_WS_X11
	     && best_size != 0 && best_encoding != 0
#endif
	    ) {
	    FM_DEBUG( "  BEST:\n"
		      "    family: %s [%s]\n"
		      "    weight: %d, italic: %d, oblique: %d\n"
		      "    stretch: %d\n"
		      "    pixelSize: %d\n"
		      "    pitch: %c\n"
		      "    encoding: %d\n",
		      best_family->name.latin1(),
		      best_foundry->name.isEmpty() ? "-- none --" : best_foundry->name.latin1(),
		      best_style->key.weight, best_style->key.italic, best_style->key.oblique,
		      best_style->key.stretch, best_size ? best_size->pixelSize : 0xffff,
#ifdef Q_WS_X11
		      best_encoding->pitch, best_encoding->encoding
#else
		      'p', 0
#endif
		);

	    fe = loadEngine( script, fp, request, best_family, best_foundry, best_style
#if defined(Q_WS_PM)
			     , best_size
#elif defined(Q_WS_X11)
			     , best_size, best_encoding, ( force_encoding_id >= 0 )
#endif
		);
	}
	if (fe) {
	    fe->fontDef.family = best_family->name;
	    if ( ! best_foundry->name.isEmpty() ) {
		fe->fontDef.family += QString::fromLatin1( " [" );
		fe->fontDef.family += best_foundry->name;
		fe->fontDef.family += QString::fromLatin1( "]" );
	    }

#ifdef Q_WS_PM
            // On OS/2, fontDef.pixelSize and fontDef.pointSize are filled
            // by QFontEnginePM constructor
#else             
	    if ( best_style->smoothScalable )
		fe->fontDef.pixelSize = request.pixelSize;
	    else if ( best_style->bitmapScalable &&
		      ( request.styleStrategy & QFont::PreferMatch ) )
		fe->fontDef.pixelSize = request.pixelSize;
	    else
		fe->fontDef.pixelSize = best_size->pixelSize;

	    if ( fp ) {
#if defined(Q_WS_X11)
		fe->fontDef.pointSize =
		    qRound(10. * qt_pointSize(fe->fontDef.pixelSize, fp->paintdevice, fp->screen));
#elif defined(Q_WS_WIN)
		fe->fontDef.pointSize     = int( double( fe->fontDef.pixelSize ) * 720.0 /
						 GetDeviceCaps(shared_dc,LOGPIXELSY) );
#else
		fe->fontDef.pointSize     = int( double( fe->fontDef.pixelSize ) * 720.0 /
						 96.0 );
#endif
	    } else {
		fe->fontDef.pointSize = request.pointSize;
	    }
#endif            
	    fe->fontDef.styleHint     = request.styleHint;
	    fe->fontDef.styleStrategy = request.styleStrategy;

	    fe->fontDef.weight        = best_style->key.weight;
	    fe->fontDef.italic        = best_style->key.italic || best_style->key.oblique;
	    fe->fontDef.fixedPitch    = best_family->fixedPitch;
	    fe->fontDef.stretch       = best_style->key.stretch;
	    fe->fontDef.ignorePitch   = FALSE;
	}
    }

    if ( fe ) {
#ifdef Q_WS_PM
///@@TODO (dmik): should do something here?
#else
	if ( script != QFont::Unicode && !canRender( fe, script ) ) {
	    FM_DEBUG( "  WARN: font loaded cannot render sample 0x%04x",
		      sampleCharacter(script).unicode() );
	    delete fe;

	    if ( ! request.family.isEmpty() )
		return 0;

	    FM_DEBUG( "returning box engine" );

	    fe = new QFontEngineBox( request.pixelSize );

	    if ( fp
#ifdef Q_WS_WIN
		 && !fp->paintdevice
#endif
		) {
		QFontCache::Key key( request, script, fp->screen );
		QFontCache::instance->insertEngine( key, fe );
	    }

	    return fe;
	}
#endif // !Q_WS_PM

	if ( fp ) {
	    QFontCache::Key key( request, script,
#if defined(Q_WS_WIN) || defined(Q_WS_PM)
				 (int)fp->paintdevice
#else
				 fp->screen
#endif
		);
	    QFontCache::instance->insertEngine( key, fe );

#ifndef Q_WS_PM
	    for ( int i = 0; i < QFont::NScripts; ++i ) {
		if ( i == script ) continue;

		if (!canRender(fe, (QFont::Script) i))
		    continue;

		key.script = i;
		QFontCache::instance->insertEngine( key, fe );
	    }
#endif // !Q_WS_PM
	}
    } else {
	if ( request.family.isEmpty() ) {
#ifdef Q_WS_PM
//@@TODO (dmik): what to return in such case?
            qFatal( "QFontDatabase::findFont: request.family is empty and nothing is found, should it ever happen?" );
#else
	    FM_DEBUG( "returning box engine" );

	    fe = new QFontEngineBox( request.pixelSize );

	    if ( fp ) {
		QFontCache::Key key( request, script,
#if defined(Q_WS_WIN) || defined(Q_WS_PM) 
				     (int)fp->paintdevice
#else
				     fp->screen
#endif
		    );
		QFontCache::instance->insertEngine( key, fe );
	    }
#endif // Q_WS_PM
	}
    }

    return fe;
}
#endif // Q_WS_X11 || Q_WS_WIN || Q_WS_PM




static QString styleString( int weight, bool italic, bool oblique )
{
    QString result;
    if ( weight >= QFont::Black )
	result = "Black";
    else if ( weight >= QFont::Bold )
	result = "Bold";
    else if ( weight >= QFont::DemiBold )
	result = "Demi Bold";
    else if ( weight < QFont::Normal )
	result = "Light";

    if ( italic )
	result += " Italic";
    else if ( oblique )
	result += " Oblique";

    if ( result.isEmpty() )
	result = "Normal";

    return result.simplifyWhiteSpace();
}

/*!
    Returns a string that describes the style of the font \a f. For
    example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
    string may be returned.
*/
QString QFontDatabase::styleString( const QFont &f )
{
    // ### fix oblique here
    return ::styleString( f.weight(), f.italic(), FALSE );
}


/*!
    \class QFontDatabase qfontdatabase.h
    \brief The QFontDatabase class provides information about the fonts available in the underlying window system.

    \ingroup environment
    \ingroup graphics

    The most common uses of this class are to query the database for
    the list of font families() and for the pointSizes() and styles()
    that are available for each family. An alternative to pointSizes()
    is smoothSizes() which returns the sizes at which a given family
    and style will look attractive.

    If the font family is available from two or more foundries the
    foundry name is included in the family name, e.g. "Helvetica
    [Adobe]" and "Helvetica [Cronyx]". When you specify a family you
    can either use the old hyphenated Qt 2.x "foundry-family" format,
    e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family
    [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a
    foundry it is always returned, e.g. by families(), using the
    bracketed format.

    The font() function returns a QFont given a family, style and
    point size.

    A family and style combination can be checked to see if it is
    italic() or bold(), and to retrieve its weight(). Similarly we can
    call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
    isFixedPitch().

    A text version of a style is given by styleString().

    The QFontDatabase class also supports some static functions, for
    example, standardSizes(). You can retrieve the Unicode 3.0
    description of a \link QFont::Script script\endlink using
    scriptName(), and a sample of characters in a script with
    scriptSample().

    Example:
\code
#include <qapplication.h>
#include <qfontdatabase.h>
#include <else.h>

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    QFontDatabase fdb;
    QStringList families = fdb.families();
    for ( QStringList::Iterator f = families.begin(); f != families.end(); ++f ) {
	QString family = *f;
	qDebug( family );
	QStringList styles = fdb.styles( family );
	for ( QStringList::Iterator s = styles.begin(); s != styles.end(); ++s ) {
	    QString style = *s;
	    QString dstyle = "\t" + style + " (";
	    QValueList<int> smoothies = fdb.smoothSizes( family, style );
	    for ( QValueList<int>::Iterator points = smoothies.begin();
		  points != smoothies.end(); ++points ) {
		dstyle += QString::number( *points ) + " ";
	    }
	    dstyle = dstyle.left( dstyle.length() - 1 ) + ")";
	    qDebug( dstyle );
	}
    }
    return 0;
}
\endcode
    This example gets the list of font families, then the list of
    styles for each family and the point sizes that are available for
    each family/style combination.
*/
/*!
    \obsolete
    \fn inline QStringList QFontDatabase::families( bool ) const
*/
/*!
    \obsolete
    \fn inline QStringList QFontDatabase::styles( const QString &family,
					  const QString & ) const
*/
/*!
    \obsolete
    \fn inline QValueList<int> QFontDatabase::pointSizes( const QString &family,
						  const QString &style ,
						  const QString & )
*/

/*!
    \obsolete
    \fn inline QValueList<int> QFontDatabase::smoothSizes( const QString &family,
						   const QString &style,
						   const QString & )
*/
/*!
    \obsolete
    \fn inline QFont QFontDatabase::font( const QString &familyName,
				  const QString &style,
				  int pointSize,
				  const QString &)
*/
/*!
    \obsolete
    \fn inline bool QFontDatabase::isBitmapScalable( const QString &family,
					     const QString &style,
					     const QString & ) const
*/

/*!
    \obsolete
    \fn inline bool QFontDatabase::isSmoothlyScalable( const QString &family,
					       const QString &style,
					       const QString & ) const
*/

/*!
    \obsolete
    \fn inline bool QFontDatabase::isScalable( const QString &family,
				       const QString &style,
				       const QString & ) const
*/

/*!
    \obsolete
    \fn inline bool QFontDatabase::isFixedPitch( const QString &family,
					 const QString &style,
					 const QString & ) const
*/

/*!
    \obsolete
    \fn inline bool QFontDatabase::italic( const QString &family,
				   const QString &style,
				   const QString & ) const
*/

/*!
    \obsolete
    \fn inline bool QFontDatabase::bold( const QString &family,
				 const QString &style,
				 const QString & ) const
*/

/*!
    \obsolete
    \fn inline int QFontDatabase::weight( const QString &family,
				  const QString &style,
				  const QString & ) const
*/


/*!
    Creates a font database object.
*/
QFontDatabase::QFontDatabase()
{
#ifdef Q_WS_PM
    d = QFontDatabasePrivate::instance();    
#else    
    createDatabase();

    d = db;
#endif
}


/*! Returns a sorted list of the names of the available font families.

    If a family exists in several foundries, the returned name for
    that font is in the form "family [foundry]". Examples: "Times
    [Adobe]", "Times [Cronyx]", "Palatino".
*/
QStringList QFontDatabase::families() const
{
    load();

    QStringList flist;
    for ( int i = 0; i < d->count; i++ ) {
	QtFontFamily *f = d->families[i];
	if ( f->count == 0 )
	    continue;
	if ( f->count == 1 ) {
	    flist.append( f->name );
	} else {
	    for ( int j = 0; j < f->count; j++ ) {
		QString str = f->name;
		QString foundry = f->foundries[j]->name;
		if ( !foundry.isEmpty() ) {
		    str += " [";
		    str += foundry;
		    str += "]";
		}
		flist.append( str );
	    }
	}
    }
    return flist;
}

/*!
    \overload

    Returns a sorted list of the available font families which support
    the Unicode script \a script.

    If a family exists in several foundries, the returned name for
    that font is in the form "family [foundry]". Examples: "Times
    [Adobe]", "Times [Cronyx]", "Palatino".
*/
QStringList QFontDatabase::families( QFont::Script script ) const
{
    load();

    QStringList flist;
    for ( int i = 0; i < d->count; i++ ) {
	QtFontFamily *f = d->families[i];
	if ( f->count == 0 )
	    continue;
	if (!(f->scripts[script] & QtFontFamily::Supported))
	    continue;
	if ( f->count == 1 ) {
	    flist.append( f->name );
	} else {
	    for ( int j = 0; j < f->count; j++ ) {
		QString str = f->name;
		QString foundry = f->foundries[j]->name;
		if ( !foundry.isEmpty() ) {
		    str += " [";
		    str += foundry;
		    str += "]";
		}
		flist.append( str );
	    }
	}
    }
    return flist;
}

/*!
    Returns a list of the styles available for the font family \a
    family. Some example styles: "Light", "Light Italic", "Bold",
    "Oblique", "Demi". The list may be empty.
*/
QStringList QFontDatabase::styles( const QString &family ) const
{
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QStringList l;
    QtFontFamily *f = d->family( familyName );
    if ( !f )
	return l;

    QtFontFoundry allStyles( foundryName );
    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ ) {
		QtFontStyle::Key ke( foundry->styles[k]->key );
		ke.stretch = 0;
		allStyles.style( ke,  TRUE );
	    }
	}
    }

    for ( int i = 0; i < allStyles.count; i++ )
	l.append( ::styleString( allStyles.styles[i]->key.weight,
				 allStyles.styles[i]->key.italic,
				 allStyles.styles[i]->key.oblique ) );
    return l;
}

/*!
    Returns TRUE if the font that has family \a family and style \a
    style is fixed pitch; otherwise returns FALSE.
*/

bool QFontDatabase::isFixedPitch(const QString &family,
				 const QString &style) const
{
    Q_UNUSED(style);

    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontFamily *f = d->family( familyName );
#if defined(Q_OS_MAC) && !defined(QWS)
    if (f) {
	if (!f->fixedPitchComputed) {
	    QFontMetrics fm(familyName);
	    f->fixedPitch = fm.width('i') == fm.width('m');
	    f->fixedPitchComputed = TRUE;
	}
    }
#endif

    return ( f && f->fixedPitch );
}

/*!
    Returns TRUE if the font that has family \a family and style \a
    style is a scalable bitmap font; otherwise returns FALSE. Scaling
    a bitmap font usually produces an unattractive hardly readable
    result, because the pixels of the font are scaled. If you need to
    scale a bitmap font it is better to scale it to one of the fixed
    sizes returned by smoothSizes().

    \sa isScalable(), isSmoothlyScalable()
*/
bool QFontDatabase::isBitmapScalable( const QString &family,
				      const QString &style) const
{
    bool bitmapScalable = FALSE;
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontStyle::Key styleKey( style );

    QtFontFamily *f = d->family( familyName );
    if ( !f ) return bitmapScalable;

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		if ( foundry->styles[k]->key == styleKey &&
		     foundry->styles[k]->bitmapScalable &&
		     !foundry->styles[k]->smoothScalable ) {
		    bitmapScalable = TRUE;
		    goto end;
		}
	}
    }
 end:
    return bitmapScalable;
}


/*!
    Returns TRUE if the font that has family \a family and style \a
    style is smoothly scalable; otherwise returns FALSE. If this
    function returns TRUE, it's safe to scale this font to any size,
    and the result will always look attractive.

    \sa isScalable(), isBitmapScalable()
*/
bool  QFontDatabase::isSmoothlyScalable( const QString &family,
                                         const QString &style) const
{
    bool smoothScalable = FALSE;
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontStyle::Key styleKey( style );

    QtFontFamily *f = d->family( familyName );
    if ( !f ) return smoothScalable;

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() ||
	     ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		if ( foundry->styles[k]->key == styleKey &&
		     foundry->styles[k]->smoothScalable ) {
		    smoothScalable = TRUE;
		    goto end;
		}
	}
    }
 end:
    return smoothScalable;
}

/*!
    Returns TRUE if the font that has family \a family and style \a
    style is scalable; otherwise returns FALSE.

    \sa isBitmapScalable(), isSmoothlyScalable()
*/
bool  QFontDatabase::isScalable( const QString &family,
                                 const QString &style) const
{
    if ( isSmoothlyScalable( family, style) )
        return TRUE;

    return isBitmapScalable( family, style);
}


/*!
    Returns a list of the point sizes available for the font that has
    family \a family and style \a style. The list may be empty.

    \sa smoothSizes(), standardSizes()
*/
QValueList<int> QFontDatabase::pointSizes( const QString &family,
					   const QString &style)
{
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
    // windows and macosx are always smoothly scalable
    Q_UNUSED( family );
    Q_UNUSED( style );
    return standardSizes();
#else
    bool smoothScalable = FALSE;
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontStyle::Key styleKey( style );

    QValueList<int> sizes;

    QtFontFamily *fam = d->family( familyName );
    if ( !fam ) return sizes;

    for ( int j = 0; j < fam->count; j++ ) {
	QtFontFoundry *foundry = fam->foundries[j];
	if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
	    QtFontStyle *style = foundry->style( styleKey );
	    if ( !style ) continue;

	    if ( style->smoothScalable ) {
		smoothScalable = TRUE;
		goto end;
	    }
	    for ( int l = 0; l < style->count; l++ ) {
		const QtFontSize *size = style->pixelSizes + l;

		if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
#if defined(Q_WS_X11)
		    const uint pointSize = qRound(qt_pointSize(size->pixelSize, 0, -1));
#elif defined(Q_WS_PM)
//@@TODO (dmik): some bitmap fonts (i.e. System VIO) have point sizes
//  that do not really correlate with their actual pixel sizes (i.e.
//  their pointsize != pixelsizde * DPI / 72), What to return in that case?  
		    const uint pointSize = size->pointSize / 10;
#else
		    const uint pointSize = size->pixelSize; // embedded uses 72dpi
#endif
		    if (! sizes.contains(pointSize))
			sizes.append(pointSize);
		}
	    }
	}
    }
 end:
    if ( smoothScalable )
	return standardSizes();

    qHeapSort( sizes );
    return sizes;
#endif
}

/*!
    Returns a QFont object that has family \a family, style \a style
    and point size \a pointSize. If no matching font could be created,
    a QFont object that uses the application's default font is
    returned.
*/
QFont QFontDatabase::font( const QString &family, const QString &style,
                           int pointSize)
{
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontFoundry allStyles( foundryName );
    QtFontFamily *f = d->family( familyName );
    if ( !f ) return QApplication::font();

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		allStyles.style( foundry->styles[k]->key,  TRUE );
	}
    }

    QtFontStyle::Key styleKey( style );
    QtFontStyle *s = allStyles.style( styleKey );

    // ### perhaps do a bit of matching to find the most compatible font?
    if ( !s && allStyles.count )
	s = allStyles.styles[0];

    if ( !s ) // no styles found?
	return QApplication::font();
    return QFont( family, pointSize, s->key.weight,
		  s->key.italic ? TRUE : s->key.oblique ? TRUE : FALSE );
}


/*!
    Returns the point sizes of a font that has family \a family and
    style \a style that will look attractive. The list may be empty.
    For non-scalable fonts and bitmap scalable fonts, this function
    is equivalent to pointSizes().

  \sa pointSizes(), standardSizes()
*/
QValueList<int> QFontDatabase::smoothSizes( const QString &family,
					    const QString &style)
{
#ifdef Q_WS_WIN
    Q_UNUSED( family );
    Q_UNUSED( style );
    return QFontDatabase::standardSizes();
#else
    bool smoothScalable = FALSE;
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontStyle::Key styleKey( style );

    QValueList<int> sizes;

    QtFontFamily *fam = d->family( familyName );
    if ( !fam )
	return sizes;

    for ( int j = 0; j < fam->count; j++ ) {
	QtFontFoundry *foundry = fam->foundries[j];
	if ( foundryName.isEmpty() ||
	     ucstricmp( foundry->name, foundryName ) == 0 ) {
	    QtFontStyle *style = foundry->style( styleKey );
	    if ( !style ) continue;

	    if ( style->smoothScalable ) {
		smoothScalable = TRUE;
		goto end;
	    }
	    for ( int l = 0; l < style->count; l++ ) {
		const QtFontSize *size = style->pixelSizes + l;

		if ( size->pixelSize != 0 && size->pixelSize != USHRT_MAX ) {
#if defined(Q_WS_X11)
		    const uint pointSize = qRound(qt_pointSize(size->pixelSize, 0, -1));
#elif defined(Q_WS_PM)
//@@TODO (dmik): some bitmap fonts (i.e. System VIO) have point sizes
//  that do not really correlate with their actual pixel sizes (i.e.
//  their pointsize != pixelsizde * DPI / 72), What to return in that case?  
		    const uint pointSize = size->pointSize / 10;
#else
		    const uint pointSize = size->pixelSize; // embedded uses 72dpi
#endif
		    if (! sizes.contains(pointSize))
			sizes.append( pointSize );
		}
	    }
	}
    }
 end:
    if ( smoothScalable )
	return QFontDatabase::standardSizes();

    qHeapSort( sizes );
    return sizes;
#endif
}


/*!
    Returns a list of standard font sizes.

    \sa smoothSizes(), pointSizes()
*/
QValueList<int> QFontDatabase::standardSizes()
{
    QValueList<int> ret;
    static const unsigned short standard[] =
	{ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
    const unsigned short *sizes = standard;
    while ( *sizes ) ret << *sizes++;
    return ret;
}


/*!
    Returns TRUE if the font that has family \a family and style \a
    style is italic; otherwise returns FALSE.

    \sa weight(), bold()
*/
bool QFontDatabase::italic( const QString &family,
                            const QString &style) const
{
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontFoundry allStyles( foundryName );
    QtFontFamily *f = d->family( familyName );
    if ( !f ) return FALSE;

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() || ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		allStyles.style( foundry->styles[k]->key,  TRUE );
	}
    }

    QtFontStyle::Key styleKey( style );
    QtFontStyle *s = allStyles.style( styleKey );
    return s && s->key.italic;
}


/*!
    Returns TRUE if the font that has family \a family and style \a
    style is bold; otherwise returns FALSE.

    \sa italic(), weight()
*/
bool QFontDatabase::bold( const QString &family,
			  const QString &style) const
{
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontFoundry allStyles( foundryName );
    QtFontFamily *f = d->family( familyName );
    if ( !f ) return FALSE;

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() ||
	     ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		allStyles.style( foundry->styles[k]->key,  TRUE );
	}
    }

    QtFontStyle::Key styleKey( style );
    QtFontStyle *s = allStyles.style( styleKey );
    return s && s->key.weight >= QFont::Bold;
}


/*!
    Returns the weight of the font that has family \a family and style
    \a style. If there is no such family and style combination,
    returns -1.

    \sa italic(), bold()
*/
int QFontDatabase::weight( const QString &family,
                           const QString &style) const
{
    QString familyName,  foundryName;
    parseFontName( family, foundryName, familyName );

    load( familyName );

    QtFontFoundry allStyles( foundryName );
    QtFontFamily *f = d->family( familyName );
    if ( !f ) return -1;

    for ( int j = 0; j < f->count; j++ ) {
	QtFontFoundry *foundry = f->foundries[j];
	if ( foundryName.isEmpty() ||
	     ucstricmp( foundry->name, foundryName ) == 0 ) {
	    for ( int k = 0; k < foundry->count; k++ )
		allStyles.style( foundry->styles[k]->key,  TRUE );
	}
    }

    QtFontStyle::Key styleKey( style );
    QtFontStyle *s = allStyles.style( styleKey );
    return s ? s->key.weight : -1;
}


/*!
    Returns a string that gives a default description of the \a script
    (e.g. for displaying to the user in a dialog).  The name matches
    the name of the script as defined by the Unicode 3.0 standard.

    \sa QFont::Script
*/
QString QFontDatabase::scriptName(QFont::Script script)
{
    const char *name = 0;

    switch (script) {
    case QFont::Latin:
	name = QT_TRANSLATE_NOOP("QFont",  "Latin");
	break;
    case QFont::Greek:
	name = QT_TRANSLATE_NOOP("QFont",  "Greek" );
	break;
    case QFont::Cyrillic:
	name = QT_TRANSLATE_NOOP("QFont",  "Cyrillic" );
	break;
    case QFont::Armenian:
	name = QT_TRANSLATE_NOOP("QFont",  "Armenian" );
	break;
    case QFont::Georgian:
	name = QT_TRANSLATE_NOOP("QFont",  "Georgian" );
	break;
    case QFont::Runic:
	name = QT_TRANSLATE_NOOP("QFont",  "Runic" );
	break;
    case QFont::Ogham:
	name = QT_TRANSLATE_NOOP("QFont",  "Ogham" );
	break;
    case QFont::SpacingModifiers:
	name = QT_TRANSLATE_NOOP("QFont",  "SpacingModifiers" );
	break;
    case QFont::CombiningMarks:
	name = QT_TRANSLATE_NOOP("QFont",  "CombiningMarks" );
	break;
    case QFont::Hebrew:
	name = QT_TRANSLATE_NOOP("QFont",  "Hebrew" );
	break;
    case QFont::Arabic:
	name = QT_TRANSLATE_NOOP("QFont",  "Arabic" );
	break;
    case QFont::Syriac:
	name = QT_TRANSLATE_NOOP("QFont",  "Syriac" );
	break;
    case QFont::Thaana:
	name = QT_TRANSLATE_NOOP("QFont",  "Thaana" );
	break;
    case QFont::Devanagari:
	name = QT_TRANSLATE_NOOP("QFont",  "Devanagari" );
	break;
    case QFont::Bengali:
	name = QT_TRANSLATE_NOOP("QFont",  "Bengali" );
	break;
    case QFont::Gurmukhi:
	name = QT_TRANSLATE_NOOP("QFont",  "Gurmukhi" );
	break;
    case QFont::Gujarati:
	name = QT_TRANSLATE_NOOP("QFont",  "Gujarati" );
	break;
    case QFont::Oriya:
	name = QT_TRANSLATE_NOOP("QFont",  "Oriya" );
	break;
    case QFont::Tamil:
	name = QT_TRANSLATE_NOOP("QFont",  "Tamil" );
	break;
    case QFont::Telugu:
	name = QT_TRANSLATE_NOOP("QFont",  "Telugu" );
	break;
    case QFont::Kannada:
	name = QT_TRANSLATE_NOOP("QFont",  "Kannada" );
	break;
    case QFont::Malayalam:
	name = QT_TRANSLATE_NOOP("QFont",  "Malayalam" );
	break;
    case QFont::Sinhala:
	name = QT_TRANSLATE_NOOP("QFont",  "Sinhala" );
	break;
    case QFont::Thai:
	name = QT_TRANSLATE_NOOP("QFont",  "Thai" );
	break;
    case QFont::Lao:
	name = QT_TRANSLATE_NOOP("QFont",  "Lao" );
	break;
    case QFont::Tibetan:
	name = QT_TRANSLATE_NOOP("QFont",  "Tibetan" );
	break;
    case QFont::Myanmar:
	name = QT_TRANSLATE_NOOP("QFont",  "Myanmar" );
	break;
    case QFont::Khmer:
	name = QT_TRANSLATE_NOOP("QFont",  "Khmer" );
	break;
    case QFont::Han:
	name = QT_TRANSLATE_NOOP("QFont",  "Han" );
	break;
    case QFont::Hiragana:
	name = QT_TRANSLATE_NOOP("QFont",  "Hiragana" );
	break;
    case QFont::Katakana:
	name = QT_TRANSLATE_NOOP("QFont",  "Katakana" );
	break;
    case QFont::Hangul:
	name = QT_TRANSLATE_NOOP("QFont",  "Hangul" );
	break;
    case QFont::Bopomofo:
	name = QT_TRANSLATE_NOOP("QFont",  "Bopomofo" );
	break;
    case QFont::Yi:
	name = QT_TRANSLATE_NOOP("QFont",  "Yi" );
	break;
    case QFont::Ethiopic:
	name = QT_TRANSLATE_NOOP("QFont",  "Ethiopic" );
	break;
    case QFont::Cherokee:
	name = QT_TRANSLATE_NOOP("QFont",  "Cherokee" );
	break;
    case QFont::CanadianAboriginal:
	name = QT_TRANSLATE_NOOP("QFont",  "Canadian Aboriginal" );
	break;
    case QFont::Mongolian:
	name = QT_TRANSLATE_NOOP("QFont",  "Mongolian" );
	break;

    case QFont::CurrencySymbols:
	name = QT_TRANSLATE_NOOP("QFont",  "Currency Symbols" );
	break;

    case QFont::LetterlikeSymbols:
	name = QT_TRANSLATE_NOOP("QFont",  "Letterlike Symbols" );
	break;

    case QFont::NumberForms:
	name = QT_TRANSLATE_NOOP("QFont",  "Number Forms" );
	break;

    case QFont::MathematicalOperators:
	name = QT_TRANSLATE_NOOP("QFont",  "Mathematical Operators" );
	break;

    case QFont::TechnicalSymbols:
	name = QT_TRANSLATE_NOOP("QFont",  "Technical Symbols" );
	break;

    case QFont::GeometricSymbols:
	name = QT_TRANSLATE_NOOP("QFont",  "Geometric Symbols" );
	break;

    case QFont::MiscellaneousSymbols:
	name = QT_TRANSLATE_NOOP("QFont",  "Miscellaneous Symbols" );
	break;

    case QFont::EnclosedAndSquare:
	name = QT_TRANSLATE_NOOP("QFont",  "Enclosed and Square" );
	break;

    case QFont::Braille:
	name = QT_TRANSLATE_NOOP("QFont",  "Braille" );
	break;

    case QFont::Unicode:
	name = QT_TRANSLATE_NOOP("QFont",  "Unicode" );
	break;

    case QFont::Tagalog:
	name = QT_TRANSLATE_NOOP( "QFont", "Tagalog" );
	break;

    case QFont::Hanunoo:
	name = QT_TRANSLATE_NOOP( "QFont", "Hanunoo" );
	break;

    case QFont::Buhid:
	name = QT_TRANSLATE_NOOP( "QFont", "Buhid" );
    	break;

    case QFont::Tagbanwa:
	name = QT_TRANSLATE_NOOP( "QFont", "Tagbanwa" );
	break;

    case QFont::KatakanaHalfWidth:
	name = QT_TRANSLATE_NOOP( "QFont", "Katakana Half-Width Forms" );
	break;

    case QFont::Han_Japanese:
	name = QT_TRANSLATE_NOOP( "QFont", "Han (Japanese)" );
	break;

    case QFont::Han_SimplifiedChinese:
	name = QT_TRANSLATE_NOOP( "QFont", "Han (Simplified Chinese)" );
	break;

    case QFont::Han_TraditionalChinese:
	name = QT_TRANSLATE_NOOP( "QFont", "Han (Traditional Chinese)" );
	break;

    case QFont::Han_Korean:
	name = QT_TRANSLATE_NOOP( "QFont", "Han (Korean)" );
	break;

    default:
	name = QT_TRANSLATE_NOOP( "QFont", "Unknown Script" );
	break;
    }

    return qApp ? qApp->translate("QFont", name) : QString::fromLatin1(name);
}


/*!
    Returns a string with sample characters from \a script.

    \sa QFont::Script
*/
QString QFontDatabase::scriptSample(QFont::Script script)
{
    QString sample = "AaBb";

    switch (script) {
    case QFont::Latin:
	// This is cheating... we only show latin-1 characters so that we don't
	// end up loading lots of fonts - at least on X11...
	sample += QChar(0x00C3);
	sample += QChar(0x00E1);
	sample += "Zz";
	break;
    case QFont::Greek:
	sample += QChar(0x0393);
	sample += QChar(0x03B1);
	sample += QChar(0x03A9);
	sample += QChar(0x03C9);
	break;
    case QFont::Cyrillic:
	sample += QChar(0x0414);
	sample += QChar(0x0434);
	sample += QChar(0x0436);
	sample += QChar(0x0402);
	break;
    case QFont::Armenian:
	sample += QChar(0x053f);
	sample += QChar(0x054f);
	sample += QChar(0x056f);
	sample += QChar(0x057f);
	break;
    case QFont::Georgian:
	sample += QChar(0x10a0);
	sample += QChar(0x10b0);
	sample += QChar(0x10c0);
	sample += QChar(0x10d0);
	break;
    case QFont::Runic:
	sample += QChar(0x16a0);
	sample += QChar(0x16b0);
	sample += QChar(0x16c0);
	sample += QChar(0x16d0);
	break;
    case QFont::Ogham:
	sample += QChar(0x1681);
	sample += QChar(0x1687);
	sample += QChar(0x1693);
	sample += QChar(0x168d);
	break;



    case QFont::Hebrew:
        sample += QChar(0x05D0);
        sample += QChar(0x05D1);
        sample += QChar(0x05D2);
        sample += QChar(0x05D3);
	break;
    case QFont::Arabic:
	sample += QChar(0x0628);
	sample += QChar(0x0629);
        sample += QChar(0x062A);
        sample += QChar(0x063A);
	break;
    case QFont::Syriac:
	sample += QChar(0x0715);
	sample += QChar(0x0725);
	sample += QChar(0x0716);
	sample += QChar(0x0726);
	break;
    case QFont::Thaana:
	sample += QChar(0x0784);
	sample += QChar(0x0794);
	sample += QChar(0x078c);
	sample += QChar(0x078d);
	break;



    case QFont::Devanagari:
	sample += QChar(0x0905);
	sample += QChar(0x0915);
	sample += QChar(0x0925);
	sample += QChar(0x0935);
	break;
    case QFont::Bengali:
	sample += QChar(0x0986);
	sample += QChar(0x0996);
	sample += QChar(0x09a6);
	sample += QChar(0x09b6);
	break;
    case QFont::Gurmukhi:
	sample += QChar(0x0a05);
	sample += QChar(0x0a15);
	sample += QChar(0x0a25);
	sample += QChar(0x0a35);
	break;
    case QFont::Gujarati:
	sample += QChar(0x0a85);
	sample += QChar(0x0a95);
	sample += QChar(0x0aa5);
	sample += QChar(0x0ab5);
	break;
    case QFont::Oriya:
	sample += QChar(0x0b06);
	sample += QChar(0x0b16);
	sample += QChar(0x0b2b);
	sample += QChar(0x0b36);
	break;
    case QFont::Tamil:
	sample += QChar(0x0b89);
	sample += QChar(0x0b99);
	sample += QChar(0x0ba9);
	sample += QChar(0x0bb9);
	break;
    case QFont::Telugu:
	sample += QChar(0x0c05);
	sample += QChar(0x0c15);
	sample += QChar(0x0c25);
	sample += QChar(0x0c35);
	break;
    case QFont::Kannada:
	sample += QChar(0x0c85);
	sample += QChar(0x0c95);
	sample += QChar(0x0ca5);
	sample += QChar(0x0cb5);
	break;
    case QFont::Malayalam:
	sample += QChar(0x0d05);
	sample += QChar(0x0d15);
	sample += QChar(0x0d25);
	sample += QChar(0x0d35);
	break;
    case QFont::Sinhala:
	sample += QChar(0x0d90);
	sample += QChar(0x0da0);
	sample += QChar(0x0db0);
	sample += QChar(0x0dc0);
	break;
    case QFont::Thai:
	sample += QChar(0x0e02);
	sample += QChar(0x0e12);
	sample += QChar(0x0e22);
	sample += QChar(0x0e32);
	break;
    case QFont::Lao:
	sample += QChar(0x0e8d);
	sample += QChar(0x0e9d);
	sample += QChar(0x0ead);
	sample += QChar(0x0ebd);
	break;
    case QFont::Tibetan:
	sample += QChar(0x0f00);
	sample += QChar(0x0f01);
	sample += QChar(0x0f02);
	sample += QChar(0x0f03);
	break;
    case QFont::Myanmar:
	sample += QChar(0x1000);
	sample += QChar(0x1001);
	sample += QChar(0x1002);
	sample += QChar(0x1003);
	break;
    case QFont::Khmer:
	sample += QChar(0x1780);
	sample += QChar(0x1790);
	sample += QChar(0x17b0);
	sample += QChar(0x17c0);
	break;



    case QFont::Han:
	sample += QChar(0x6f84);
	sample += QChar(0x820a);
	sample += QChar(0x61a9);
	sample += QChar(0x9781);
	break;
    case QFont::Hiragana:
	sample += QChar(0x3050);
	sample += QChar(0x3060);
	sample += QChar(0x3070);
	sample += QChar(0x3080);
	break;
    case QFont::Katakana:
	sample += QChar(0x30b0);
	sample += QChar(0x30c0);
	sample += QChar(0x30d0);
	sample += QChar(0x30e0);
	break;
    case QFont::Hangul:
	sample += QChar(0xac00);
	sample += QChar(0xac11);
	sample += QChar(0xac1a);
	sample += QChar(0xac2f);
	break;
    case QFont::Bopomofo:
	sample += QChar(0x3105);
	sample += QChar(0x3115);
	sample += QChar(0x3125);
	sample += QChar(0x3129);
	break;
    case QFont::Yi:
	sample += QChar(0xa1a8);
	sample += QChar(0xa1a6);
	sample += QChar(0xa200);
	sample += QChar(0xa280);
	break;



    case QFont::Ethiopic:
	sample += QChar(0x1200);
	sample += QChar(0x1240);
	sample += QChar(0x1280);
	sample += QChar(0x12c0);
	break;
    case QFont::Cherokee:
	sample += QChar(0x13a0);
	sample += QChar(0x13b0);
	sample += QChar(0x13c0);
	sample += QChar(0x13d0);
	break;
    case QFont::CanadianAboriginal:
	sample += QChar(0x1410);
	sample += QChar(0x1500);
	sample += QChar(0x15f0);
	sample += QChar(0x1650);
	break;
    case QFont::Mongolian:
	sample += QChar(0x1820);
	sample += QChar(0x1840);
	sample += QChar(0x1860);
	sample += QChar(0x1880);
	break;


    case QFont::CurrencySymbols:
    case QFont::LetterlikeSymbols:
    case QFont::NumberForms:
    case QFont::MathematicalOperators:
    case QFont::TechnicalSymbols:
    case QFont::GeometricSymbols:
    case QFont::MiscellaneousSymbols:
    case QFont::EnclosedAndSquare:
    case QFont::Braille:
	break;


    case QFont::Unicode:
	sample += QChar(0x0174);
	sample += QChar(0x0628);
	sample += QChar(0x0e02);
	sample += QChar(0x263A);
	sample += QChar(0x3129);
	sample += QChar(0x61a9);
	sample += QChar(0xac2f);
	break;



    default:
	sample += QChar(0xfffd);
	sample += QChar(0xfffd);
	sample += QChar(0xfffd);
	sample += QChar(0xfffd);
	break;
    }

    return sample;
}




/*!
  \internal

  This makes sense of the font family name:

  1) if the family name contains a '-' (ie. "Adobe-Courier"), then we
  split at the '-', and use the string as the foundry, and the string to
  the right as the family

  2) if the family name contains a '[' and a ']', then we take the text
  between the square brackets as the foundry, and the text before the
  square brackets as the family (ie. "Arial [Monotype]")
*/
void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
{
    if ( name.contains('-') ) {
	int i = name.find('-');
	foundry = name.left( i );
	family = name.right( name.length() - i - 1 );
    } else if ( name.contains('[') && name.contains(']')) {
	int i = name.find('[');
	int li = name.findRev(']');

	if (i < li) {
	    foundry = name.mid(i + 1, li - i - 1);
	    if (name[i - 1] == ' ')
		i--;
	    family = name.left(i);
	}
    } else {
	foundry = QString::null;
	family = name;
    }
}

#endif // QT_NO_FONTDATABASE
