static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont) { ByteCount length = 0; if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, 0, 0, &length) != noErr) return; QVarLengthArray<uchar> os2Table(length); if (length < 86 || ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, length, os2Table.data(), &length) != noErr) return; 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) }; QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); #if 0 QCFString name; ATSFontGetName(atsFont, kATSOptionFlagsDefault, &name); qDebug() << systems.count() << "writing systems for" << QString(name); qDebug() << "first char" << hex << unicodeRange[0]; for (int i = 0; i < systems.count(); ++i) qDebug() << QFontDatabase::writingSystemName(systems.at(i)); #endif for (int i = 0; i < systems.count(); ++i) family->writingSystems[systems.at(i)] = QtFontFamily::Supported; }
char* GetGlyphName_AAT(ATSUStyle style, UInt16 gid, int* len) { static char buffer[256]; const char* namePtr; ATSUFontID fontID; ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); ByteCount length; OSStatus status = ATSFontGetTable(fontRef, kPost, 0, 0, 0, &length); if (status != noErr) return 0; void* table = xmalloc(length); status = ATSFontGetTable(fontRef, kPost, 0, length, table, &length); if (status != noErr) { free(table); return 0; } namePtr = getGlyphNamePtr(table, length, gid, len); if (*len > 255) *len = 255; if (namePtr) { memcpy(buffer, namePtr, *len); buffer[*len] = 0; } free(table); return &buffer[0]; }
QFontEngine::Properties QFontEngineMac::properties() const { QFontEngine::Properties props; ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); quint16 tmp; if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 18, 2, &tmp, 0) == noErr) props.emSquare = qFromBigEndian<quint16>(tmp); struct { qint16 xMin; qint16 yMin; qint16 xMax; qint16 yMax; } bbox; bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0; if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 36, 8, &bbox, 0) == noErr) { bbox.xMin = qFromBigEndian<quint16>(bbox.xMin); bbox.yMin = qFromBigEndian<quint16>(bbox.yMin); bbox.xMax = qFromBigEndian<quint16>(bbox.xMax); bbox.yMax = qFromBigEndian<quint16>(bbox.yMax); } struct { qint16 ascender; qint16 descender; qint16 linegap; } metrics; metrics.ascender = metrics.descender = metrics.linegap = 0; if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'h', 'e', 'a'), 4, 6, &metrics, 0) == noErr) { metrics.ascender = qFromBigEndian<quint16>(metrics.ascender); metrics.descender = qFromBigEndian<quint16>(metrics.descender); metrics.linegap = qFromBigEndian<quint16>(metrics.linegap); } props.ascent = metrics.ascender; props.descent = -metrics.descender; props.leading = metrics.linegap; props.boundingBox = QRectF(bbox.xMin, -bbox.yMax, bbox.xMax - bbox.xMin, bbox.yMax - bbox.yMin); props.italicAngle = 0; props.capHeight = props.ascent; qint16 lw = 0; if (ATSFontGetTable(atsFont, MAKE_TAG('p', 'o', 's', 't'), 10, 2, &lw, 0) == noErr) lw = qFromBigEndian<quint16>(lw); props.lineWidth = lw; QCFString psName; if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr) props.postscriptName = QString(psName).toUtf8(); props.postscriptName = QPdf::stripSpecialCharacters(props.postscriptName); return props; }
QByteArray QFontEngineMac::getSfntTable(uint tag) const { ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); ByteCount length; OSStatus status = ATSFontGetTable(atsFont, tag, 0, 0, 0, &length); if (status != noErr) return QByteArray(); QByteArray table(length, 0); status = ATSFontGetTable(atsFont, tag, 0, table.length(), table.data(), &length); if (status != noErr) return QByteArray(); return table; }
int MapGlyphToIndex_AAT(ATSUStyle style, const char* glyphName) { ATSUFontID fontID; ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &fontID, 0); ATSFontRef fontRef = FMGetATSFontRefFromFont(fontID); ByteCount length; OSStatus status = ATSFontGetTable(fontRef, kPost, 0, 0, 0, &length); if (status != noErr) return 0; void* table = xmalloc(length); status = ATSFontGetTable(fontRef, kPost, 0, length, table, &length); if (status != noErr) { free(table); return 0; } int rval = findGlyphInPostTable(table, length, glyphName); free(table); return rval; }
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); } } }
QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine) : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false) { fontDef = def; ATSUCreateAndCopyStyle(baseStyle, &style); ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); cgFont = CGFontCreateWithPlatformFont(&atsFont); const int maxAttributeCount = 4; ATSUAttributeTag tags[maxAttributeCount + 1]; ByteCount sizes[maxAttributeCount + 1]; ATSUAttributeValuePtr values[maxAttributeCount + 1]; int attributeCount = 0; synthesisFlags = 0; 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); } Boolean atsuBold = false; Boolean atsuItalic = false; if (fontDef.weight >= QFont::Bold) { if (!(macStyle & 1)) { synthesisFlags |= SynthesizedBold; atsuBold = true; tags[attributeCount] = kATSUQDBoldfaceTag; sizes[attributeCount] = sizeof(atsuBold); values[attributeCount] = &atsuBold; ++attributeCount; } } if (fontDef.style != QFont::StyleNormal) { if (!(macStyle & 2)) { synthesisFlags |= SynthesizedItalic; atsuItalic = true; tags[attributeCount] = kATSUQDItalicTag; sizes[attributeCount] = sizeof(atsuItalic); values[attributeCount] = &atsuItalic; ++attributeCount; } } tags[attributeCount] = kATSUFontTag; values[attributeCount] = &fontID; sizes[attributeCount] = sizeof(fontID); ++attributeCount; Q_ASSERT(attributeCount < maxAttributeCount + 1); OSStatus err = ATSUSetAttributes(style, attributeCount, tags, sizes, values); Q_ASSERT(err == noErr); Q_UNUSED(err); quint16 tmpFsType; if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 8, 2, &tmpFsType, 0) == noErr) fsType = qFromBigEndian<quint16>(tmpFsType); else fsType = 0; }