From 1496976a05b8804135608c7dde9bca5620950c33 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Mon, 7 Nov 2011 16:24:21 +0100 Subject: Fix localized font family access in OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Font family names listed in QFontDatabase::families() should be localized names rather than their default (English) names, to be consistent with behaviors in other Mac apps and previous Qt/Mac based on ATS. It should also be possible to verify if a font exists with any family name, regardless it's localized or not. Say we have font "Hiragino Mincho Pro", which has a Japanese name called "ヒラギ ノ明朝 Pro", then db.hasFamily(QString::fromUtf8("ヒラギノ明朝 Pro")) should return true. Task-number: QTBUG-22372 Reviewed-by: Morten Sorvig --- src/gui/text/qfontdatabase.cpp | 2 +- src/gui/text/qfontdatabase_mac.cpp | 26 +++++++++++++++++++++++--- tests/auto/qfontdatabase/tst_qfontdatabase.cpp | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 796c455..8d375b8 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1132,7 +1132,7 @@ QT_BEGIN_INCLUDE_NAMESPACE #endif QT_END_INCLUDE_NAMESPACE -#if !defined(Q_WS_X11) +#if !defined(Q_WS_X11) && !defined(Q_WS_MAC) QString QFontDatabase::resolveFontFamilyAlias(const QString &family) { return family; diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index 9a8e8af..81500c7 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -104,9 +104,8 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { 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); - QCFString style_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute); + QCFString family_name = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL); + QCFString style_name = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL); QtFontFamily *family = db->family(family_name, true); for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) family->writingSystems[ws] = QtFontFamily::Supported; @@ -489,4 +488,25 @@ bool QFontDatabase::supportsThreadedFontRendering() return true; } +QString QFontDatabase::resolveFontFamilyAlias(const QString &family) +{ + QCFString expectedFamily = QCFString(family); + + QCFType attributes = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, expectedFamily); + QCFType descriptor = CTFontDescriptorCreateWithAttributes(attributes); + + QCFType mandatoryAttributes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); + CFSetAddValue(mandatoryAttributes, kCTFontFamilyNameAttribute); + + QCFType font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL); + QCFType matched = CTFontDescriptorCreateMatchingFontDescriptor(descriptor, mandatoryAttributes); + if (!matched) + return family; + + QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(matched, kCTFontFamilyNameAttribute, NULL); + return familyName; +} + QT_END_NAMESPACE diff --git a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp index 735c7e4..15be776 100644 --- a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp @@ -80,6 +80,10 @@ private slots: void addAppFont_data(); void addAppFont(); + +#ifdef Q_WS_MAC + void localizedFonts(); +#endif }; tst_QFontDatabase::tst_QFontDatabase() @@ -275,5 +279,16 @@ void tst_QFontDatabase::addAppFont() QVERIFY(db.families() == oldFamilies); } +#ifdef Q_WS_MAC +void tst_QFontDatabase::localizedFonts() +{ + QFontDatabase db; + + QVERIFY(db.hasFamily(QString::fromUtf8("ヒラギノ明朝 Pro"))); + QVERIFY(db.hasFamily(QString::fromUtf8("华文宋体"))); + QVERIFY(!db.hasFamily(QString::fromUtf8("NotValidFont"))); +} +#endif + QTEST_MAIN(tst_QFontDatabase) #include "tst_qfontdatabase.moc" -- cgit v0.12 From 738b1d2d93a77283bc40e3d03f378a2db8aec97f Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Tue, 8 Nov 2011 12:49:27 +0100 Subject: Fix styleName listing with the same QtFontStyle::Key value We should store fonts with different style names but the same QtFontStyle::Key value (italic, weight and stretch) separately, so that fonts like Osaka (Regular, Regular-Mono) can be listed correctly. dd0205e0fbacf340508686cc136d70eda7bf664d introduced this regression when moving styleName out of Key. Without a styleName specified, we will do binary search and insertion for styles by comparing QtFontStyle::Key. We should do the same but comparing styleName instead when it's available. Reviewed-by: Eskil --- src/gui/text/qfontdatabase.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 8d375b8..675c292 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -359,23 +359,26 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &st { int pos = 0; if (count) { - // if styleName for searching first if possible - if (!styleName.isEmpty()) { - for (; pos < count; pos++) { - if (styles[pos]->styleName == styleName) - return styles[pos]; - } - } int low = 0; int high = count; + bool hasStyleName = !styleName.isEmpty(); // search styleName first if available 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; + if (hasStyleName) { + if (styles[pos]->styleName == styleName) + return styles[pos]; + if (styles[pos]->styleName < styleName) + low = pos + 1; + else + high = pos; + } else { + 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; @@ -383,7 +386,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &st if (!create) return 0; -// qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos); + // qDebug("adding key (weight=%d, style=%d, stretch=%d) at %d", key.weight, key.style, key.stretch, pos); if (!(count % 8)) { QtFontStyle **newStyles = (QtFontStyle **) realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *)); -- cgit v0.12 From 68de09f538ae1103a3104e0fba1086ea93581b6e Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Wed, 9 Nov 2011 16:06:55 +0100 Subject: Fix regression in styleName searching 1. Faked styles should have styleNames as well otherwise we couldn't find them. 2. With a QtFontFoundry mixed with style keys and style names, there is no way to sort them in a manner than binary search will work, we have to use linear search instead. --- src/gui/text/qfontdatabase.cpp | 33 +++++++++------------------------ src/gui/text/qfontdatabase_x11.cpp | 1 + 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 675c292..d5d8a12 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -91,6 +91,8 @@ QT_BEGIN_NAMESPACE bool qt_enable_test_font = false; +static QString styleStringHelper(int weight, QFont::Style style); + Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value) { qt_enable_test_font = value; @@ -358,30 +360,15 @@ struct QtFontFoundry QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create) { int pos = 0; - if (count) { - int low = 0; - int high = count; + for (; pos < count; pos++) { bool hasStyleName = !styleName.isEmpty(); // search styleName first if available - pos = count / 2; - while (high > low) { - if (hasStyleName) { - if (styles[pos]->styleName == styleName) - return styles[pos]; - if (styles[pos]->styleName < styleName) - low = pos + 1; - else - high = pos; - } else { - if (styles[pos]->key == key) - return styles[pos]; - if (styles[pos]->key < key) - low = pos + 1; - else - high = pos; - } - pos = (high + low) / 2; + if (hasStyleName && !styles[pos]->styleName.isEmpty()) { + if (styles[pos]->styleName == styleName) + return styles[pos]; + } else { + if (styles[pos]->key == key) + return styles[pos]; } - pos = low; } if (!create) return 0; @@ -396,13 +383,11 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &st QtFontStyle *style = new QtFontStyle(key); style->styleName = styleName; - memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *)); styles[pos] = style; count++; return styles[pos]; } - struct QtFontFamily { enum WritingSystemStatus { diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index 922a97f..df25aa6 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -1361,6 +1361,7 @@ static void initializeDb() // let's fake one... equiv = foundry->style(key, QString(), true); + equiv->styleName = styleStringHelper(key.weight, QFont::Style(key.style)); equiv->smoothScalable = true; QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); -- cgit v0.12 From f322c563baabab704044810373041d99a2b03a6f Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Sun, 13 Nov 2011 13:29:38 +0100 Subject: Remove font that may not exists in some OS X systems --- tests/auto/qfontdatabase/tst_qfontdatabase.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp index 15be776..7bbd32d 100644 --- a/tests/auto/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/qfontdatabase/tst_qfontdatabase.cpp @@ -285,7 +285,6 @@ void tst_QFontDatabase::localizedFonts() QFontDatabase db; QVERIFY(db.hasFamily(QString::fromUtf8("ヒラギノ明朝 Pro"))); - QVERIFY(db.hasFamily(QString::fromUtf8("华文宋体"))); QVERIFY(!db.hasFamily(QString::fromUtf8("NotValidFont"))); } #endif -- cgit v0.12