OSX: Properly detect language support in fonts

The language support detection in Cocoa does not report the correct
set of languages for all fonts. One consequence of this is that e.g.
Mkhedruli (Georgian) was not supported on Mac because the
'ka' language code was not reported for e.g. the Arial Unicode MS
font.

This was never detected in Qt 4, because the writing system support
we set for each font was never used for font matching, since we let
CoreText do the matching in Qt 4.

To remedy this, we also detect writing system support based on the OS/2
table in the font. We add this in addition to the current test in case
the language list has information about fonts with incomplete OS/2 tables,
to avoid regressing.

[ChangeLog][OS X] Fixed detection of writing system support in fonts for
some scripts such as Mkhedruli.

Change-Id: I26c2a42ef45112e17d6794d8798a57c8d8aaaafa
Task-number: QTBUG-41208
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2014-09-10 10:29:48 +02:00
parent 2368e62f32
commit 8610534f53
3 changed files with 25 additions and 1 deletions

View File

@ -52,6 +52,7 @@
#include "qfontengine_coretext_p.h" #include "qfontengine_coretext_p.h"
#include <QtCore/QSettings> #include <QtCore/QSettings>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtCore/QtEndian>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -262,6 +263,27 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
fd->stretch = QFont::Unstretched; fd->stretch = QFont::Unstretched;
fd->fixedPitch = false; fd->fixedPitch = false;
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
uint length = 0;
uint tag = MAKE_TAG('O', 'S', '/', '2');
CTFontRef tempFontRef = tempFont;
void *userData = reinterpret_cast<void *>(&tempFontRef);
if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, 0, &length)) {
QVarLengthArray<uchar> os2Table(length);
if (length >= 86 && QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length)) {
quint32 unicodeRange[4] = {
qFromBigEndian<quint32>(os2Table.data() + 42),
qFromBigEndian<quint32>(os2Table.data() + 46),
qFromBigEndian<quint32>(os2Table.data() + 50),
qFromBigEndian<quint32>(os2Table.data() + 54)
};
quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78),
qFromBigEndian<quint32>(os2Table.data() + 82) };
fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
}
}
}
if (styles) { if (styles) {
if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) { if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
double normalizedWeight; double normalizedWeight;

View File

@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length) bool QCoreTextFontEngine::ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
{ {
CTFontRef ctfont = *(CTFontRef *)user_data; CTFontRef ctfont = *(CTFontRef *)user_data;

View File

@ -118,6 +118,8 @@ public:
#endif #endif
} }
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length);
static int antialiasingThreshold; static int antialiasingThreshold;
static QFontEngine::GlyphFormat defaultGlyphFormat; static QFontEngine::GlyphFormat defaultGlyphFormat;