예제 #1
0
QT_BEGIN_NAMESPACE

Q_GUI_EXPORT  void qt_registerFont(const QString &familyName, const QString &foundryname, int weight,
                                   QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize,
                                   const QSupportedWritingSystems &writingSystems, void *handle)
{
    QFontDatabasePrivate *d = privateDb();
        QtFontStyle::Key styleKey;
        styleKey.style = style;
        styleKey.weight = weight;
        styleKey.stretch = stretch;
        QtFontFamily *f = d->family(familyName, true);

        for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
            if (writingSystems.supported(QFontDatabase::WritingSystem(i))) {
                f->writingSystems[i] = QtFontFamily::Supported;
            } else {
                f->writingSystems[i] = QtFontFamily::Unsupported;
            }
        }

        QtFontFoundry *foundry = f->foundry(foundryname, true);
        QtFontStyle *fontStyle = foundry->style(styleKey, QString(), true);
        fontStyle->smoothScalable = scalable;
        fontStyle->antialiased = antialiased;
        QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
        size->handle = handle;
}
예제 #2
0
static
QFontEngine *loadEngine(int script, const QFontDef &request,
                        QtFontFamily *family, QtFontFoundry *foundry,
                        QtFontStyle *style, QtFontSize *size)
{

    QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
    //make sure that the db has all fallback families
    if (engine
        && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {

        if (family && !family->askedForFallback) {
            QFont::Style fontStyle = QFont::Style(style->key.style);
            QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
            if (styleHint == QFont::AnyStyle && request.fixedPitch)
                styleHint = QFont::TypeWriter;
            family->fallbackFamilies = fallbackFamilies(family->name,fontStyle,styleHint,QUnicodeTables::Script(script));

            family->askedForFallback = true;
        }

        QStringList fallbacks = privateDb()->fallbackFamilies;
        if (family && !family->fallbackFamilies.isEmpty())
            fallbacks = family->fallbackFamilies;

        engine = new QFontEngineMultiQPA(engine, script, fallbacks);
    }

    return engine;
}
예제 #3
0
static
QFontEngine *loadEngine(int script, const QFontDef &request,
                        QtFontFamily *family, QtFontFoundry *foundry,
                        QtFontStyle *style, QtFontSize *size)
{

    QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
    //make sure that the db has all fallback families
    if (engine && engine->type() != QFontEngine::Multi
        && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {

        if (family && !family->askedForFallback) {
            QFont::Style fontStyle = QFont::Style(style->key.style);
            QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
            if (styleHint == QFont::AnyStyle && request.fixedPitch)
                styleHint = QFont::TypeWriter;
            family->fallbackFamilies = fallbackFamilies(family->name,fontStyle,styleHint,QUnicodeTables::Script(script));

            family->askedForFallback = true;
        }

        QStringList fallbacks = privateDb()->fallbackFamilies;
        if (family && !family->fallbackFamilies.isEmpty())
            fallbacks = family->fallbackFamilies;

        engine = new QFontEngineMultiQPA(engine, script, fallbacks);

        // Cache Multi font engine as well in case we got the FT single
        // font engine when we are actually looking for a Multi one
        QFontCache::Key key(request, script, 1);
        QFontCache::instance()->instance()->insertEngine(key, engine);
    }

    return engine;
}
예제 #4
0
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
{
    QFontDatabasePrivate *db = privateDb();

    fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);

    db->reregisterAppFonts = true;
}
예제 #5
0
bool QFontDatabase::removeAllApplicationFonts()
{
    QFontDatabasePrivate *db = privateDb();
    for(int i = 0; i < db->applicationFonts.count(); ++i) {
        if(!removeApplicationFont(i))
            return false;
    }
    return true;
}
예제 #6
0
static QFontEngine *loadFromDatabase(QFontDef &req, const QFontPrivate *d)
{
#if defined(QT_MAC_USE_COCOA)
    QCFString fontName = NULL;
#else
    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;
#endif

    QStringList family_list = familyList(req);

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with previous versions
    family_list << QApplication::font().defaultFamily();

    QMutexLocker locker(fontDatabaseMutex());
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for (int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
                QByteArray family_name = db->families[k]->name.toUtf8();
#if defined(QT_MAC_USE_COCOA)
                QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL);
                if (ctFont) {
                    fontName = CTFontCopyFullName(ctFont);
                    goto found;
                }
#else
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto found;
                }
#endif
            }
        }
    }
found:
#ifdef QT_MAC_USE_COCOA
    if (fontName)
        return new QCoreTextFontEngineMulti(fontName, req, d->kerning);
#else
    if (familyRef) {
        QCFString actualName;
        if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            req.family = actualName;
        return new QFontEngineMacMulti(familyRef, fontRef, req, d->kerning);
    }
#endif
    return NULL;
}
예제 #7
0
bool QFontDatabase::removeAllApplicationFonts()
{
    QMutexLocker locker(fontDatabaseMutex());

    QFontDatabasePrivate *db = privateDb();
    for (int i = 0; i < db->applicationFonts.count(); ++i)
        if (!removeApplicationFont(i))
            return false;
    return true;
}
예제 #8
0
bool QFontDatabase::removeAllApplicationFonts()
{
    QMutexLocker locker(fontDatabaseMutex());

    QFontDatabasePrivate *db = privateDb();
    if (db->applicationFonts.isEmpty())
        return false;

    db->applicationFonts.clear();
    db->invalidate();
    return true;
}
예제 #9
0
// called from qapplication_qws.cpp
void qt_applyFontDatabaseSettings(const QSettings &settings)
{
    initializeDb();
    QFontDatabasePrivate *db = privateDb();
    for (int i = 0; i < db->count; ++i) {
        QtFontFamily *family = db->families[i];
        if (settings.contains(family->name))
            family->fallbackFamilies = settings.value(family->name).toStringList();
    }

    if (settings.contains(QLatin1String("Global Fallbacks")))
        db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList();
}
예제 #10
0
void QFontDatabase::load(const QFontPrivate *d, int script)
{
    // sanity checks
    if (!qApp)
        qWarning("QFontDatabase::load: Must construct QApplication first");
    Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);

    // normalize the request to get better caching
    QFontDef req = d->request;
    if (req.pixelSize <= 0)
        req.pixelSize = floor((100.0 * req.pointSize * d->dpi) / 72. + 0.5) / 100;
    if (req.pixelSize < 1)
        req.pixelSize = 1;
    if (req.weight == 0)
        req.weight = QFont::Normal;
    if (req.stretch == 0)
        req.stretch = 100;

    QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
    if (!d->engineData)
        getEngineData(d, key);

    // the cached engineData could have already loaded the engine we want
    if (d->engineData->engines[script])
        return;

    QFontEngine *fe = QFontCache::instance()->findEngine(key);

    // set it to the actual pointsize, so QFontInfo will do the right thing
    if (req.pointSize < 0)
        req.pointSize = req.pixelSize*72./d->dpi;

    if (!fe) {
        if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
            fe = new QTestFontEngine(req.pixelSize);
            fe->fontDef = req;
        } else {
            QMutexLocker locker(fontDatabaseMutex());
            if (!privateDb()->count)
                initializeDb();
            fe = loadWin(d, script, req);
        }
        if (!fe) {
            fe = new QFontEngineBox(req.pixelSize);
            fe->fontDef = QFontDef();
        }
    }
    d->engineData->engines[script] = fe;
    fe->ref.ref();
    QFontCache::instance()->insertEngine(key, fe);
}
예제 #11
0
bool QFontDatabase::removeApplicationFont(int handle)
{
    QMutexLocker locker(fontDatabaseMutex());

    QFontDatabasePrivate *db = privateDb();
    if (handle < 0 || handle >= db->applicationFonts.count())
        return false;

    db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();

    db->reregisterAppFonts = true;
    db->invalidate();
    return true;
}
예제 #12
0
bool QFontDatabase::removeApplicationFont(int handle)
{
    QFontDatabasePrivate *db = privateDb();
    if(handle < 0 || handle >= db->applicationFonts.count())
        return false;

    OSStatus e = ATSFontDeactivate(db->applicationFonts.at(handle).handle,
                                   /*iRefCon=*/0, kATSOptionFlagsDefault);
    if(e != noErr)
        return false;

    db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();

    db->invalidate();
    return true;
}
예제 #13
0
static void initializeDb()
{
    QFontDatabasePrivate *db = privateDb();

    // init by asking for the platformfontdb for the first time or after invalidation
    if (!db->count)
        QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();

    if (db->reregisterAppFonts) {
        for (int i = 0; i < db->applicationFonts.count(); i++) {
            if (!db->applicationFonts.at(i).families.isEmpty())
                registerFont(&db->applicationFonts[i]);
        }
        db->reregisterAppFonts = false;
    }
}
예제 #14
0
bool QFontDatabase::removeApplicationFont(int handle)
{
    QMutexLocker locker(fontDatabaseMutex());

    QFontDatabasePrivate *db = privateDb();
    if (handle < 0 || handle >= db->applicationFonts.count())
        return false;

    const QFontDatabasePrivate::ApplicationFont font = db->applicationFonts.at(handle);
    db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
    if (font.memoryFont) {
#ifdef Q_OS_WINCE
        bool removeSucceeded = RemoveFontResource((LPCWSTR)font.fileName.utf16());
        QFile tempfile(font.fileName);
        tempfile.remove();
        if (!removeSucceeded)
            return false;
#else
        PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"),
                                                                                                              "RemoveFontMemResourceEx");
        if (!ptrRemoveFontMemResourceEx
            || !ptrRemoveFontMemResourceEx(font.handle))
            return false;
#endif // Q_OS_WINCE
    } else {
#ifdef Q_OS_WINCE
        if (!RemoveFontResource((LPCWSTR)font.fileName.utf16()))
            return false;
#else
        PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"),
                                                                                                        "RemoveFontResourceExW");
        if (!ptrRemoveFontResourceExW
            || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0))
            return false;
#endif // Q_OS_WINCE
    }

    db->invalidate();
    return true;
}
예제 #15
0
static void initializeDb()
{
    QFontDatabasePrivate *db = privateDb();
    if (!db || db->count)
        return;

    populate_database(QString());

#ifdef QFONTDATABASE_DEBUG
    // print the database
    for (int f = 0; f < db->count; f++) {
        QtFontFamily *family = db->families[f];
        qDebug("    %s: %p", qPrintable(family->name), family);
        populate_database(family->name);

#if 0
        qDebug("        scripts supported:");
        for (int i = 0; i < QUnicodeTables::ScriptCount; i++)
            if(family->writingSystems[i] & QtFontFamily::Supported)
                qDebug("            %d", i);
        for (int fd = 0; fd < family->count; fd++) {
            QtFontFoundry *foundry = family->foundries[fd];
            qDebug("        %s", foundry->name.latin1());
            for (int s = 0; s < foundry->count; s++) {
                QtFontStyle *style = foundry->styles[s];
                qDebug("            style: style=%d weight=%d smooth=%d",  style->key.style,
                       style->key.weight, style->smoothScalable );
                if(!style->smoothScalable) {
                    for(int i = 0; i < style->count; ++i) {
                        qDebug("                %d", style->pixelSizes[i].pixelSize);
                    }
                }
            }
        }
#endif
    }
#endif // QFONTDATABASE_DEBUG

}
예제 #16
0
static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script)
{
    QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
    QFontDatabasePrivate *db = privateDb();

    QStringList::iterator i;
    for (i = retList.begin(); i != retList.end(); ++i) {
        bool contains = false;
        for (int j = 0; j < db->count; j++) {
            QtFontFamily *qtFamily = db->families[j];
            if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) {
                contains = true;
                break;
            }
        }
        if (!contains) {
            i = retList.erase(i);
            i--;
        }
    }
    return retList;
}
예제 #17
0
static void initializeDb()
{
    QFontDatabasePrivate *db = privateDb();
    if(!db || db->count)
        return;

#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
    QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0);
    if(!collection)
        return;
    QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection);
    if(!fonts)
        return;
    QString foundry_name = "CoreText";
    const int numFonts = CFArrayGetCount(fonts);
    for(int i = 0; i < numFonts; ++i) {
        CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i);

        QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
        QtFontFamily *family = db->family(family_name, true);
        for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws)
            family->writingSystems[ws] = QtFontFamily::Supported;
        QtFontFoundry *foundry = family->foundry(foundry_name, true);

        QtFontStyle::Key styleKey;
        if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) {
            if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
                Q_ASSERT(CFNumberIsFloatType(weight));
                double d;
                if(CFNumberGetValue(weight, kCFNumberDoubleType, &d)) {
                    //qDebug() << "BOLD" << (QString)family_name << d;
                    styleKey.weight = (d > 0.0) ? QFont::Bold : QFont::Normal;
                }
            }
            if(CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
                Q_ASSERT(CFNumberIsFloatType(italic));
                double d;
                if(CFNumberGetValue(italic, kCFNumberDoubleType, &d)) {
                    //qDebug() << "ITALIC" << (QString)family_name << d;
                    if (d > 0.0)
                        styleKey.style = QFont::StyleItalic;
                }
            }
        }

        QtFontStyle *style = foundry->style(styleKey, true);
        style->smoothScalable = true;
        if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) {
            //qDebug() << "WHEE";
            int pixel_size=0;
            if(CFNumberIsFloatType(size)) {
                double d;
                CFNumberGetValue(size, kCFNumberDoubleType, &d);
                pixel_size = d;
            } else {
                CFNumberGetValue(size, kCFNumberIntType, &pixel_size);
            }
            //qDebug() << "SIZE" << (QString)family_name << pixel_size;
            if(pixel_size)
                style->pixelSize(pixel_size, true);
        } else {
            //qDebug() << "WTF?";
        }
    }
} else 
#endif
{ 
    FMFontIterator it;
    if (!FMCreateFontIterator(0, 0, kFMUseGlobalScopeOption, &it)) {
        while (true) {
            FMFont fmFont;
            if (FMGetNextFont(&it, &fmFont) != noErr)
                break;

            FMFontFamily fmFamily;
            FMFontStyle fmStyle;
            QString familyName;

            QtFontStyle::Key styleKey;

            ATSFontRef atsFont = FMGetATSFontRefFromFont(fmFont);

            if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) {
                { //sanity check the font, and see if we can use it at all! --Sam
                    ATSUFontID fontID;
                    if(ATSUFONDtoFontID(fmFamily, 0, &fontID) != noErr)
                        continue;
                }

                if (fmStyle & ::italic)
                    styleKey.style = QFont::StyleItalic;
                if (fmStyle & ::bold)
                    styleKey.weight = QFont::Bold;

                ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily);
                QCFString cfFamilyName;;
                ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName);
                familyName = cfFamilyName;
            } else {
                QCFString cfFontName;
                ATSFontGetName(atsFont, kATSOptionFlagsDefault, &cfFontName);
                familyName = cfFontName;
                quint16 macStyle = 0;
                {
                    uchar data[4];
                    ByteCount len = 4;
                    if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr)
                        macStyle = qFromBigEndian<quint16>(data);
                }
                if (macStyle & 1)
                    styleKey.weight = QFont::Bold;
                if (macStyle & 2)
                    styleKey.style = QFont::StyleItalic;
            }

            QtFontFamily *family = db->family(familyName, true);
            QtFontFoundry *foundry = family->foundry(QString(), true);
            QtFontStyle *style = foundry->style(styleKey, true);
            style->pixelSize(0, true);
            style->smoothScalable = true;

            initWritingSystems(family, atsFont);
        }
        FMDisposeFontIterator(&it);
    }
}
}
예제 #18
0
static inline void load(const QString & = QString(), int = -1)
{
    // Only initialize the database if it has been cleared or not initialized yet
    if (!privateDb()->count)
        initializeDb();
}
예제 #19
0
void QFontDatabase::load(const QFontPrivate *d, int script)
{
    // sanity checks
    if(!qApp)
        qWarning("QFont: Must construct a QApplication before a QFont");

    Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
    Q_UNUSED(script);

    QFontDef req = d->request;
    req.pixelSize = qt_mac_pixelsize(req, d->dpi);

    // set the point size to 0 to get better caching
    req.pointSize = 0;
    QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen);

    if(!(d->engineData = QFontCache::instance()->findEngineData(key))) {
        d->engineData = new QFontEngineData;
        QFontCache::instance()->insertEngineData(key, d->engineData);
    } else {
        d->engineData->ref.ref();
    }
    if(d->engineData->engine) // already loaded
        return;

    // set it to the actual pointsize, so QFontInfo will do the right thing
    req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi));

    QFontEngine *e = QFontCache::instance()->findEngine(key);
    if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
        e = new QTestFontEngine(req.pixelSize);
        e->fontDef = req;
    }

    if(e) {
        e->ref.ref();
        d->engineData->engine = e;
        return; // the font info and fontdef should already be filled
    }

    //find the font
    QStringList family_list = familyList(req);

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with
    // previous versions
    family_list << QApplication::font().defaultFamily();

    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;

    QMutexLocker locker(fontDatabaseMutex());
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for(int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
                QByteArray family_name = db->families[k]->name.toUtf8();
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto FamilyFound;
                } else {
#if defined(QT_MAC_USE_COCOA)
                    // ATS and CT disagrees on what the family name should be,
                    // use CT to look up the font if ATS fails.
                    QCFString familyName = QString::fromAscii(family_name);
                    QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL);
                    QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef);
                    QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute);

                    familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault);
                    if (familyRef) {
                        fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault);
                        goto FamilyFound;
                    }
#endif
                }
            }
        }
    }
FamilyFound:
    //fill in the engine's font definition
    QFontDef fontDef = d->request; //copy..
    if(fontDef.pointSize < 0)
	fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi);
    else
	fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi);
#if 0
    ItemCount name_count;
    if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) {
        ItemCount actualName_size;
        if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) {
            QByteArray actualName(actualName_size);
            if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size)
                fontDef.family = QString::fromUtf8(actualName);
        }
    }
#else
    {
        QCFString actualName;
        if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            fontDef.family = actualName;
    }
#endif

#ifdef QT_MAC_USE_COCOA
    QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning);
#elif 1
    QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning);
#else
    ATSFontFamilyRef atsFamily = familyRef;
    ATSFontFamilyRef atsFontRef = fontRef;

    FMFont fontID;
    FMFontFamily fmFamily;
    FMFontStyle fntStyle = 0;
    fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily);
    if (fmFamily == kInvalidFontFamily) {
        // Use the ATSFont then...
        fontID = FMGetFontFromATSFontRef(atsFontRef);
    } else {
        if (fontDef.weight >= QFont::Bold)
            fntStyle |= ::bold;
        if (fontDef.style != QFont::StyleNormal)
            fntStyle |= ::italic;

        FMFontStyle intrinsicStyle;
        FMFont fnt = 0;
        if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr)
           fontID = FMGetATSFontRefFromFont(fnt);
    }

    OSStatus status;

    const int maxAttributeCount = 5;
    ATSUAttributeTag tags[maxAttributeCount + 1];
    ByteCount sizes[maxAttributeCount + 1];
    ATSUAttributeValuePtr values[maxAttributeCount + 1];
    int attributeCount = 0;

    Fixed size = FixRatio(fontDef.pixelSize, 1);
    tags[attributeCount] = kATSUSizeTag;
    sizes[attributeCount] = sizeof(size);
    values[attributeCount] = &size;
    ++attributeCount;

    tags[attributeCount] = kATSUFontTag;
    sizes[attributeCount] = sizeof(fontID);
    values[attributeCount] = &fontID;
    ++attributeCount;

    CGAffineTransform transform = CGAffineTransformIdentity;
    if (fontDef.stretch != 100) {
        transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
        tags[attributeCount] = kATSUFontMatrixTag;
        sizes[attributeCount] = sizeof(transform);
        values[attributeCount] = &transform;
        ++attributeCount;
    }

    ATSUStyle style;
    status = ATSUCreateStyle(&style);
    Q_ASSERT(status == noErr);

    Q_ASSERT(attributeCount < maxAttributeCount + 1);
    status = ATSUSetAttributes(style, attributeCount, tags, sizes, values);
    Q_ASSERT(status == noErr);

    QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0);
    ATSUDisposeStyle(style);
#endif
    d->engineData->engine = engine;
    engine->ref.ref(); //a ref for the engineData->engine
    QFontCache::instance()->insertEngine(key, engine);
}
예제 #20
0
/*!
    \internal
*/
QFontEngine *
QFontDatabase::findFont(int script, const QFontPrivate *fp,
                        const QFontDef &request)
{
    QMutexLocker locker(fontDatabaseMutex());
    const int force_encoding_id = -1;

    if (!privateDb()->count)
        initializeDb();

    QFontEngine *engine;
    QFontCache::Key key(request, script);
    engine = QFontCache::instance()->findEngine(key);
    if (engine) {
        qDebug() << "Cache hit level 1";
        return engine;
    }

    QString family_name, foundry_name;

    parseFontName(request.family, foundry_name, family_name);
    if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
        engine =new QTestFontEngine(request.pixelSize);
        engine->fontDef = request;
    }

    QtFontDesc desc;
    match(script, request, family_name, foundry_name, force_encoding_id, &desc);
    if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) {
        engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
    } else {
        FM_DEBUG("  NO MATCH FOUND\n");
    }

    if (engine) {
        initFontDef(desc, request, &engine->fontDef);

        if (fp) {
            QFontDef def = request;
            if (def.family.isEmpty()) {
                def.family = fp->request.family;
                def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
            }
        }
    }

    if (!engine) {
        if (!request.family.isEmpty()) {
            QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QFont::StyleHint(request.styleHint),QUnicodeTables::Script(script));
            for (int i = 0; i < fallbacks.size(); i++) {
                QFontDef def = request;
                def.family = fallbacks.at(i);
                QFontCache::Key key(def,script);
                engine = QFontCache::instance()->findEngine(key);
                if (!engine) {
                    QtFontDesc desc;
                    match(script, def, def.family, QLatin1String(""), 0, &desc);
                    if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) {
                        continue;
                    }
                    engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size);
                    if (engine) {
                        initFontDef(desc, def, &engine->fontDef);
                        break;
                    }
                }
            }
        }

        if (!engine)
            engine = new QFontEngineBox(request.pixelSize);

        FM_DEBUG("returning box engine");
    }

    if (fp && fp->dpi > 0) {
        engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
    } else {
        engine->fontDef.pointSize = request.pointSize;
    }
    return engine;
}
예제 #21
0
static
void addFontToDatabase(QString familyName, const QString &scriptName,
                       TEXTMETRIC *textmetric,
                       const FONTSIGNATURE *signature,
                       int type)
{
    const int script = -1;
    const QString foundryName;
    Q_UNUSED(script);

    bool italic = false;
    int weight;
    bool fixed;
    bool ttf;
    bool scalable;
    int size;

//    QString escript = QString::fromWCharArray(f->elfScript);
//    qDebug("script=%s", escript.latin1());

    NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
    fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
    ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
    scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
    size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
    italic = tm->tmItalic;
    weight = tm->tmWeight;

    // the "@family" fonts are just the same as "family". Ignore them.
    if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) {
        QtFontStyle::Key styleKey;
        styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
        styleKey.weight = weightFromInteger(weight);

        QtFontFamily *family = privateDb()->family(familyName, true);

        if(ttf && localizedName(familyName) && family->english_name.isEmpty())
            family->english_name = getEnglishName(familyName);

        QtFontFoundry *foundry = family->foundry(foundryName, true);
        QtFontStyle *style = foundry->style(styleKey, QString(), true);
        style->smoothScalable = scalable;
        style->pixelSize( size, TRUE);

        // add fonts windows can generate for us:
        if (styleKey.weight <= QFont::DemiBold) {
            QtFontStyle::Key key(styleKey);
            key.weight = QFont::Bold;
            QtFontStyle *style = foundry->style(key, QString(), true);
            style->smoothScalable = scalable;
            style->pixelSize( size, TRUE);
        }
        if (styleKey.style != QFont::StyleItalic) {
            QtFontStyle::Key key(styleKey);
            key.style = QFont::StyleItalic;
            QtFontStyle *style = foundry->style(key, QString(), true);
            style->smoothScalable = scalable;
            style->pixelSize( size, TRUE);
        }
        if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) {
            QtFontStyle::Key key(styleKey);
            key.weight = QFont::Bold;
            key.style = QFont::StyleItalic;
            QtFontStyle *style = foundry->style(key, QString(), true);
            style->smoothScalable = scalable;
            style->pixelSize( size, TRUE);
        }

        family->fixedPitch = fixed;

        if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) {
            quint32 unicodeRange[4] = {
                signature->fsUsb[0], signature->fsUsb[1],
                signature->fsUsb[2], signature->fsUsb[3]
            };
#ifdef Q_WS_WINCE
            if (signature->fsUsb[0] == 0) {
                // If the unicode ranges bit mask is zero then
                // EnumFontFamiliesEx failed to determine it properly.
                // In this case we just pretend that the font supports all languages.
                unicodeRange[0] = 0xbfffffff;   // second most significant bit must be zero
                unicodeRange[1] = 0xffffffff;
                unicodeRange[2] = 0xffffffff;
                unicodeRange[3] = 0xffffffff;
            }
#endif
            quint32 codePageRange[2] = {
                signature->fsCsb[0], signature->fsCsb[1]
            };
            QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);

            for (int i = 0; i < systems.count(); ++i) {
                QFontDatabase::WritingSystem writingSystem = systems.at(i);

                // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
                // the symbol for Baht, and Windows thus reports that it supports the Thai script.
                // Since it's the default UI font on this platform, most widgets will be unable to
                // display Thai text by default. As a temporary work around, we special case Segoe UI
                // and remove the Thai script from its list of supported writing systems.
                if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI"))
                    family->writingSystems[writingSystem] = QtFontFamily::Supported;
            }
        } else if (!family->writingSystemCheck) {
            //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1());
            if (scriptName == QLatin1String("Western")
                || scriptName == QLatin1String("Baltic")
                || scriptName == QLatin1String("Central European")
                || scriptName == QLatin1String("Turkish")
                || scriptName == QLatin1String("Vietnamese"))
                family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Thai"))
                family->writingSystems[QFontDatabase::Thai] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Symbol")
                     || scriptName == QLatin1String("Other"))
                family->writingSystems[QFontDatabase::Symbol] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("OEM/Dos"))
                family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("CHINESE_GB2312"))
                family->writingSystems[QFontDatabase::SimplifiedChinese] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("CHINESE_BIG5"))
                family->writingSystems[QFontDatabase::TraditionalChinese] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Cyrillic"))
                family->writingSystems[QFontDatabase::Cyrillic] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Hangul"))
                family->writingSystems[QFontDatabase::Korean] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Hebrew"))
                family->writingSystems[QFontDatabase::Hebrew] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Greek"))
                family->writingSystems[QFontDatabase::Greek] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Japanese"))
                family->writingSystems[QFontDatabase::Japanese] = QtFontFamily::Supported;
            else if (scriptName == QLatin1String("Arabic"))
                family->writingSystems[QFontDatabase::Arabic] = QtFontFamily::Supported;
        }
    }
}
예제 #22
0
static
void populate_database(const QString& fam)
{
    QFontDatabasePrivate *d = privateDb();
    if (!d)
        return;

    QtFontFamily *family = 0;
    if(!fam.isEmpty()) {
        family = d->family(fam);
        if(family && family->loaded)
            return;
    } else if (d->count) {
        return;
    }

    HDC dummy = GetDC(0);

    LOGFONT lf;
    lf.lfCharSet = DEFAULT_CHARSET;
    if (fam.isNull()) {
        lf.lfFaceName[0] = 0;
    } else {
        memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded
    }
    lf.lfPitchAndFamily = 0;

    EnumFontFamiliesEx(dummy, &lf,
        (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0);

    ReleaseDC(0, dummy);

    for (int i = 0; i < d->applicationFonts.count(); ++i) {
        QFontDatabasePrivate::ApplicationFont fnt = d->applicationFonts.at(i);
        if (!fnt.memoryFont)
            continue;
        for (int j = 0; j < fnt.families.count(); ++j) {
            const QString familyName = fnt.families.at(j);
            HDC hdc = GetDC(0);
            LOGFONT lf;
            memset(&lf, 0, sizeof(LOGFONT));
            memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
            lf.lfCharSet = DEFAULT_CHARSET;
            HFONT hfont = CreateFontIndirect(&lf);
            HGDIOBJ oldobj = SelectObject(hdc, hfont);

            TEXTMETRIC textMetrics;
            GetTextMetrics(hdc, &textMetrics);

            addFontToDatabase(familyName, QString(),
                              &textMetrics,
                              &fnt.signatures.at(j),
                              TRUETYPE_FONTTYPE);

            SelectObject(hdc, oldobj);
            DeleteObject(hfont);
            ReleaseDC(0, hdc);
        }
    }

    if(!fam.isEmpty()) {
        family = d->family(fam);
        if(family) {
            if(!family->writingSystemCheck) {
            }
            family->loaded = true;
        }
    }
}
예제 #23
0
void QFontDatabase::load(const QFontPrivate *d, int script)
{
    // sanity checks
    if(!QFontCache::instance)
        qWarning("QFont: Must construct a QApplication before a QFont");
    Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
    Q_UNUSED(script);

    QFontDef req = d->request;
    req.pixelSize = qt_mac_pixelsize(req, d->dpi);

    // set the point size to 0 to get better caching
    req.pointSize = 0;
    QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen);

    if(!(d->engineData = QFontCache::instance->findEngineData(key))) {
        d->engineData = new QFontEngineData;
        QFontCache::instance->insertEngineData(key, d->engineData);
    } else {
        d->engineData->ref.ref();
    }
    if(d->engineData->engine) // already loaded
        return;

    // set it to the actual pointsize, so QFontInfo will do the right thing
    req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi));

    QFontEngine *e = QFontCache::instance->findEngine(key);
    if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
        e = new QTestFontEngine(req.pixelSize);
        e->fontDef = req;
    }

    if(e) {
        Q_ASSERT(e->type() == QFontEngine::Multi || e->type() == QFontEngine::TestFontEngine);
        e->ref.ref();
        d->engineData->engine = e;
        return; // the font info and fontdef should already be filled
    }

    //find the font
    QStringList family_list = req.family.split(QLatin1Char(','));
    // append the substitute list for each family in family_list
    {
	    QStringList subs_list;
	    for(QStringList::ConstIterator it = family_list.begin(); it != family_list.end(); ++it)
		    subs_list += QFont::substitutes(*it);
	    family_list += subs_list;
    }

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with
    // previous versions
    family_list << QApplication::font().defaultFamily();

    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for(int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
                QByteArray family_name = db->families[k]->name.toUtf8();
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto FamilyFound;
                }
            }
        }
    }
FamilyFound:
    //fill in the engine's font definition
    QFontDef fontDef = d->request; //copy..
    if(fontDef.pointSize < 0)
	fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi);
    else
	fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi);
#if 0
    ItemCount name_count;
    if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) {
        ItemCount actualName_size;
        if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) {
            QByteArray actualName(actualName_size);
            if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size)
                fontDef.family = QString::fromUtf8(actualName);
        }
    }
#else
    {
        QCFString actualName;
        if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            fontDef.family = actualName;
    }
#endif

    QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning);
    d->engineData->engine = engine;
    engine->ref.ref(); //a ref for the engineData->engine
    QFontCache::instance->insertEngine(key, engine);
}
예제 #24
0
static QFontEngine *loadEngine(int script, const QFontDef &request,
                               HDC fontHdc, int dpi, bool rawMode,
                               const QtFontDesc *desc,
                               const QStringList &family_list)
{
    LOGFONT lf;
    memset(&lf, 0, sizeof(LOGFONT));

    bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc;

    HDC hdc = shared_dc();
    QString font_name = desc != 0 ? desc->family->name : request.family;

    if (useDevice) {
        hdc = fontHdc;
        font_name = request.family;
    }

    bool stockFont = false;
    bool preferClearTypeAA = false;

    HFONT hfont = 0;


#if !defined(QT_NO_DIRECTWRITE)
    bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
                       || (request.hintingPreference == QFont::PreferVerticalHinting);
    IDWriteFont *directWriteFont = 0;
#else
    bool useDirectWrite = false;
#endif

    if (rawMode) {                        // will choose a stock font
        int f, deffnt = SYSTEM_FONT;
        QString fam = desc != 0 ? desc->family->name.toLower() : request.family.toLower();
        if (fam == QLatin1String("default"))
            f = deffnt;
        else if (fam == QLatin1String("system"))
            f = SYSTEM_FONT;
#ifndef Q_WS_WINCE
        else if (fam == QLatin1String("system_fixed"))
            f = SYSTEM_FIXED_FONT;
        else if (fam == QLatin1String("ansi_fixed"))
            f = ANSI_FIXED_FONT;
        else if (fam == QLatin1String("ansi_var"))
            f = ANSI_VAR_FONT;
        else if (fam == QLatin1String("device_default"))
            f = DEVICE_DEFAULT_FONT;
        else if (fam == QLatin1String("oem_fixed"))
            f = OEM_FIXED_FONT;
#endif
        else if (fam[0] == QLatin1Char('#'))
            f = fam.right(fam.length()-1).toInt();
        else
            f = deffnt;
        hfont = (HFONT)GetStockObject(f);
        if (!hfont) {
            qErrnoWarning("QFontEngine::loadEngine: GetStockObject failed");
            hfont = systemFont();
        }
        stockFont = true;
    } else {

        int hint = FF_DONTCARE;
        switch (request.styleHint) {
            case QFont::Helvetica:
                hint = FF_SWISS;
                break;
            case QFont::Times:
                hint = FF_ROMAN;
                break;
            case QFont::Courier:
                hint = FF_MODERN;
                break;
            case QFont::OldEnglish:
                hint = FF_DECORATIVE;
                break;
            case QFont::System:
                hint = FF_MODERN;
                break;
            default:
                break;
        }

        lf.lfHeight = -qRound(request.pixelSize);
        lf.lfWidth                = 0;
        lf.lfEscapement        = 0;
        lf.lfOrientation        = 0;
        if (desc == 0 || desc->style->key.weight == 50)
            lf.lfWeight = FW_DONTCARE;
        else
            lf.lfWeight = (desc->style->key.weight*900)/99;
        lf.lfItalic         = (desc != 0 && desc->style->key.style != QFont::StyleNormal);
        lf.lfCharSet        = DEFAULT_CHARSET;

        int strat = OUT_DEFAULT_PRECIS;
        if (request.styleStrategy & QFont::PreferBitmap) {
            strat = OUT_RASTER_PRECIS;
#ifndef Q_WS_WINCE
        } else if (request.styleStrategy & QFont::PreferDevice) {
            strat = OUT_DEVICE_PRECIS;
        } else if (request.styleStrategy & QFont::PreferOutline) {
            strat = OUT_OUTLINE_PRECIS;
        } else if (request.styleStrategy & QFont::ForceOutline) {
            strat = OUT_TT_ONLY_PRECIS;
#endif
        }

        lf.lfOutPrecision   = strat;

        int qual = DEFAULT_QUALITY;

        if (request.styleStrategy & QFont::PreferMatch)
            qual = DRAFT_QUALITY;
#ifndef Q_WS_WINCE
        else if (request.styleStrategy & QFont::PreferQuality)
            qual = PROOF_QUALITY;
#endif

        if (request.styleStrategy & QFont::PreferAntialias) {
            if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) {
                qual = CLEARTYPE_QUALITY;
                preferClearTypeAA = true;
            } else {
                qual = ANTIALIASED_QUALITY;
            }
        } else if (request.styleStrategy & QFont::NoAntialias) {
            qual = NONANTIALIASED_QUALITY;
        }

        lf.lfQuality        = qual;

        lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
        lf.lfPitchAndFamily = DEFAULT_PITCH | hint;

        QString fam = font_name;

        if(fam.isEmpty())
            fam = QLatin1String("MS Sans Serif");

        if ((fam == QLatin1String("MS Sans Serif"))
            && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
            fam = QLatin1String("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
        }
        if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
            fam = QLatin1String("Courier New");

        memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded

        hfont = CreateFontIndirect(&lf);
        if (!hfont)
            qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed");

        stockFont = (hfont == 0);
        bool ttf = false;
        int avWidth = 0;
        BOOL res;
        HGDIOBJ oldObj = SelectObject(hdc, hfont);

        TEXTMETRIC tm;
        res = GetTextMetrics(hdc, &tm);
        avWidth = tm.tmAveCharWidth;
        ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
        SelectObject(hdc, oldObj);

        if (!ttf || !useDirectWrite) {
            useDirectWrite = false;

            if (hfont && (!ttf || request.stretch != 100)) {
                DeleteObject(hfont);
                if (!res)
                    qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed");
                lf.lfWidth = avWidth * request.stretch/100;
                hfont = CreateFontIndirect(&lf);
                if (!hfont)
                    qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed");
            }

#ifndef Q_WS_WINCE
            if (hfont == 0) {
                hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
                stockFont = true;
            }
#else
            if (hfont == 0) {
                hfont = (HFONT)GetStockObject(SYSTEM_FONT);
                stockFont = true;
            }
#endif

        }

#if !defined(QT_NO_DIRECTWRITE)
        else {
            // Default to false for DirectWrite (and re-enable once/if everything
            // turns out okay)
            useDirectWrite = false;

            QFontDatabasePrivate *db = privateDb();
            if (db->directWriteFactory == 0) {
                HRESULT hr = DWriteCreateFactory(
                            DWRITE_FACTORY_TYPE_SHARED,
                            __uuidof(IDWriteFactory),
                            reinterpret_cast<IUnknown **>(&db->directWriteFactory)
                            );
                if (FAILED(hr)) {
                    qErrnoWarning("QFontEngine::loadEngine: DWriteCreateFactory failed");
                } else {
                    hr = db->directWriteFactory->GetGdiInterop(&db->directWriteGdiInterop);
                    if (FAILED(hr))
                        qErrnoWarning("QFontEngine::loadEngine: GetGdiInterop failed");
                }
            }

            if (db->directWriteGdiInterop != 0) {
                QString nameSubstitute = fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName));
                memcpy(lf.lfFaceName, nameSubstitute.utf16(),
                       sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));

                HRESULT hr = db->directWriteGdiInterop->CreateFontFromLOGFONT(
                            &lf,
                            &directWriteFont);
                if (FAILED(hr)) {
#ifndef QT_NO_DEBUG
                    qErrnoWarning("QFontEngine::loadEngine: CreateFontFromLOGFONT failed "
                                  "for %ls (0x%lx)",
                                  lf.lfFaceName, hr);
#endif
                } else {
                    DeleteObject(hfont);
                    useDirectWrite = true;
                }
            }
        }
#endif

    }

    QFontEngine *fe = 0;
    if (!useDirectWrite)  {
        QFontEngineWin *few = new QFontEngineWin(font_name, hfont, stockFont, lf);
        if (preferClearTypeAA)
            few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;

        // Also check for OpenType tables when using complex scripts
        // ### TODO: This only works for scripts that require OpenType. More generally
        // for scripts that do not require OpenType we should just look at the list of
        // supported writing systems in the font's OS/2 table.
        if (scriptRequiresOpenType(script)) {
            HB_Face hbFace = few->harfbuzzFace();
            if (!hbFace || !hbFace->supported_scripts[script]) {
                FM_DEBUG("  OpenType support missing for script\n");
                delete few;
                return 0;
            }
        }

        initFontInfo(few, request, fontHdc, dpi);
        fe = few;
    }

#if !defined(QT_NO_DIRECTWRITE)
    else {
        QFontDatabasePrivate *db = privateDb();

        IDWriteFontFace *directWriteFontFace = NULL;
        HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace);
        if (SUCCEEDED(hr)) {
            QFontEngineDirectWrite *fedw = new QFontEngineDirectWrite(db->directWriteFactory,
                                                                      directWriteFontFace,
                                                                      request.pixelSize);

            initFontInfo(fedw, request, dpi, directWriteFont);

            fe = fedw;
        } else {
            qErrnoWarning(hr, "QFontEngine::loadEngine: CreateFontFace failed");
        }
    }

    if (directWriteFont != 0)
        directWriteFont->Release();
#endif

    if(script == QUnicodeTables::Common
       && !(request.styleStrategy & QFont::NoFontMerging)
       && desc != 0
       && !(desc->family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) {
        if(!tryFonts) {
            LANGID lid = GetUserDefaultLangID();
            switch( lid&0xff ) {
            case LANG_CHINESE: // Chinese (Taiwan)
                if ( lid == 0x0804 ) // Taiwan
                    tryFonts = ch_TW_tryFonts;
                else
                    tryFonts = ch_CN_tryFonts;
                break;
            case LANG_JAPANESE:
                tryFonts = jp_tryFonts;
                break;
            case LANG_KOREAN:
                tryFonts = kr_tryFonts;
                break;
            default:
                tryFonts = other_tryFonts;
                break;
            }
        }
        QStringList fm = QFontDatabase().families();
        QStringList list = family_list;
        const char **tf = tryFonts;
        while(tf && *tf) {
            if(fm.contains(QLatin1String(*tf)))
                list << QLatin1String(*tf);
            ++tf;
        }
        QFontEngine *mfe = new QFontEngineMultiWin(fe, list);
        mfe->fontDef = fe->fontDef;
        fe = mfe;
    }
    return fe;
}
예제 #25
0
static QFontEngine *loadFromDatabase(QFontDef &req, const QFontPrivate *d)
{
#if defined(QT_MAC_USE_COCOA)
    QCFString fontName = NULL;
#else
    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;
#endif

    QStringList family_list = familyList(req);

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with previous versions
    family_list << QApplication::font().defaultFamily();

    QMutexLocker locker(fontDatabaseMutex());
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for (int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
#if defined(QT_MAC_USE_COCOA)
                CFStringRef familyName = QCFString::toCFStringRef(db->families[k]->name);
                QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(
                                    QCFType<CFDictionaryRef>(CFDictionaryCreate(kCFAllocatorDefault,
                                        (const void**)&kCTFontFamilyNameAttribute,
                                        (const void**)&familyName, 1,
                                        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)));
                CFRelease(familyName);
                QCFType<CTFontRef> ctFont = CTFontCreateWithFontDescriptor(descriptor, 0, NULL);
                if (ctFont) {
                    fontName = CTFontCopyFullName(ctFont);
                    goto found;
                }
#else
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto found;
                }
#endif
            }
        }
    }
found:
#ifdef QT_MAC_USE_COCOA
    if (fontName)
        return new QCoreTextFontEngineMulti(fontName, req, d->kerning);
#else
    if (familyRef) {
        QCFString actualName;
        if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            req.family = actualName;
        return new QFontEngineMacMulti(familyRef, fontRef, req, d->kerning);
    }
#endif
    return NULL;
}