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); } } }
static bool osx_draw_text_to_cgcontext_at_location(const void *p_text, uindex_t p_length, MCGPoint p_location, const MCGFont &p_font, CGContextRef p_cgcontext, MCGIntRectangle &r_bounds) { OSStatus t_err; t_err = noErr; ATSUFontID t_font_id; Fixed t_font_size; t_font_size = p_font . size << 16; ATSUAttributeTag t_tags[] = { kATSUFontTag, kATSUSizeTag, }; ByteCount t_sizes[] = { sizeof(ATSUFontID), sizeof(Fixed), }; ATSUAttributeValuePtr t_attrs[] = { &t_font_id, &t_font_size, }; ATSLineLayoutOptions t_layout_options; ATSUAttributeTag t_layout_tags[] = { kATSULineLayoutOptionsTag, kATSUCGContextTag, }; ByteCount t_layout_sizes[] = { sizeof(ATSLineLayoutOptions), sizeof(CGContextRef), }; ATSUAttributeValuePtr t_layout_attrs[] = { &t_layout_options, &p_cgcontext, }; if (t_err == noErr) { // if the specified fon't can't be found, just use the default if (ATSUFONDtoFontID((short)(intptr_t)p_font . fid, p_font . style, &t_font_id) != noErr) t_err = ATSUFONDtoFontID(0, p_font . style, &t_font_id); } ATSUStyle t_style; t_style = NULL; if (t_err == noErr) t_err = ATSUCreateStyle(&t_style); if (t_err == noErr) t_err = ATSUSetAttributes(t_style, sizeof(t_tags) / sizeof(ATSUAttributeTag), t_tags, t_sizes, t_attrs); ATSUTextLayout t_layout; t_layout = NULL; if (t_err == noErr) { UniCharCount t_run; t_run = p_length / 2; t_err = ATSUCreateTextLayoutWithTextPtr((const UniChar *)p_text, 0, p_length / 2, p_length / 2, 1, &t_run, &t_style, &t_layout); } if (t_err == noErr) t_err = ATSUSetTransientFontMatching(t_layout, true); if (t_err == noErr) { t_layout_options = kATSLineUseDeviceMetrics | kATSLineFractDisable; t_err = ATSUSetLayoutControls(t_layout, sizeof(t_layout_tags) / sizeof(ATSUAttributeTag), t_layout_tags, t_layout_sizes, t_layout_attrs); } MCGIntRectangle t_bounds; if (p_cgcontext == NULL) { ATSUTextMeasurement t_before, t_after, t_ascent, t_descent; if (t_err == noErr) t_err = ATSUGetUnjustifiedBounds(t_layout, 0, p_length / 2, &t_before, &t_after, &t_ascent, &t_descent); if (t_err == noErr) { t_ascent = (t_ascent + 0xffff) >> 16; t_descent = (t_descent + 0xffff) >> 16; t_after = (t_after + 0xffff) >> 16; t_bounds . x = p_location . x; t_bounds . y = p_location . y - p_font . ascent; t_bounds . width = t_after; t_bounds . height = p_font . descent + p_font . ascent; r_bounds = t_bounds; }
static bool osx_prepare_text(const void *p_text, uindex_t p_length, const MCGFont &p_font) { OSStatus t_err; t_err = noErr; if (t_err == noErr) if (s_layout == NULL) t_err = ATSUCreateTextLayout(&s_layout); if (t_err == noErr) if (s_style == NULL) t_err = ATSUCreateStyle(&s_style); if (t_err == noErr) if (s_colour_space == NULL) s_colour_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); if (t_err == noErr) if (s_colour == NULL) { // Components are grey and alpha const float t_colour_components[] = {1.0, 1.0}; s_colour = CGColorCreate(s_colour_space, t_colour_components); } ATSUFontID t_font_id; Fixed t_font_size; Boolean t_font_is_italic; ATSUTextMeasurement t_imposed_width; if (t_err == noErr) { t_font_size = p_font . size << 16; // MM-2013-09-16: [[ Bug 11283 ]] It appears that ATSUI doesn't like italic being passed as a style parameter to ATSUFONDtoFontID. // Instead, set italic as an attribute tag. uint8_t t_style; t_style = p_font . style & ~italic; t_font_is_italic = p_font . style & italic; // MW-2013-12-05: [[ Bug 11535 ]] Set the imposed width to the fixed advance width // if non-zero. Otherwise use the glyph advance. if (p_font . fixed_advance != 0) t_imposed_width = p_font . fixed_advance << 16; else t_imposed_width = kATSUseGlyphAdvance; // if the specified font can't be found, just use the default // MM-2013-09-16: [[ Bug 11283 ]] Do the same for font styles - if the font/style paring cannot be found, try font with no style. t_err = ATSUFONDtoFontID((short)(intptr_t)p_font . fid, t_style, &t_font_id); if (t_err != noErr) t_err = ATSUFONDtoFontID((short)(intptr_t)p_font . fid, 0, &t_font_id); if (t_err != noErr) t_err = ATSUFONDtoFontID(0, t_style, &t_font_id); if (t_err != noErr) t_err = ATSUFONDtoFontID(0, 0, &t_font_id); } ATSUAttributeTag t_tags[] = { kATSUFontTag, kATSUSizeTag, kATSUQDItalicTag, kATSUImposeWidthTag, }; ByteCount t_sizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(Boolean), sizeof(ATSUTextMeasurement), }; ATSUAttributeValuePtr t_attrs[] = { &t_font_id, &t_font_size, &t_font_is_italic, &t_imposed_width, }; if (t_err == noErr) t_err = ATSUSetAttributes(s_style, sizeof(t_tags) / sizeof(ATSUAttributeTag), t_tags, t_sizes, t_attrs); if (t_err == noErr) t_err = ATSUSetTextPointerLocation(s_layout, (const UniChar *) p_text, 0, p_length / 2, p_length / 2); if (t_err == noErr) t_err = ATSUSetRunStyle(s_layout, s_style, 0, p_length / 2); if (t_err == noErr) t_err = ATSUSetTransientFontMatching(s_layout, true); return t_err == noErr; }
void QFontDatabase::createDatabase() { if(db) return; db = new QFontDatabasePrivate; qfontdatabase_cleanup.set(&db); FMFontFamilyIterator it; QString foundry_name = "Mac"; if(!FMCreateFontFamilyIterator(NULL, NULL, kFMUseGlobalScopeOption, &it)) { FMFontFamily fam; QString fam_name; while(!FMGetNextFontFamily(&it, &fam)) { static Str255 n; if(FMGetFontFamilyName(fam, n) != noErr) qDebug("Qt: internal: WH0A, %s %d", __FILE__, __LINE__); if(!n[0] || n[1] == '.') //throw out ones starting with a . continue; { short fnum; ATSUFontID fond; GetFNum(n, &fnum); if(ATSUFONDtoFontID(fnum, 0, &fond) != noErr) continue; } TextEncoding encoding; FMGetFontFamilyTextEncoding(fam, &encoding); TextToUnicodeInfo uni_info; CreateTextToUnicodeInfoByEncoding(encoding, &uni_info); unsigned long len = n[0] * 2; unsigned char *buff = (unsigned char *)malloc(len); ConvertFromPStringToUnicode(uni_info, n, len, &len, (UniCharArrayPtr)buff); fam_name = ""; for(unsigned long x = 0; x < len; x+=2) { #if defined(__i386__) fam_name += QChar(buff[x], buff[x+1]); #else fam_name += QChar(buff[x+1], buff[x]); #endif } free(buff); DisposeTextToUnicodeInfo(&uni_info); QtFontFamily *family = db->family( fam_name, TRUE ); family->macFamily = fam; for(int script = 0; script < QFont::LastPrivateScript; ++script) family->scripts[script] = QtFontFamily::Supported; QtFontFoundry *foundry = family->foundry( foundry_name, TRUE ); FMFontFamilyInstanceIterator fit; if(!FMCreateFontFamilyInstanceIterator(fam, &fit)) { FMFont font; FMFontStyle font_style; FMFontSize font_size; while(!FMGetNextFontFamilyInstance(&fit, &font, &font_style, &font_size)) { bool italic = (bool)(font_style & ::italic); int weight = ((font_style & ::bold) ? QFont::Bold : QFont::Normal); QtFontStyle::Key styleKey; styleKey.italic = italic; styleKey.oblique = false; styleKey.weight = weight; QtFontStyle *style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; if( !italic ) { styleKey.oblique = TRUE; style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; styleKey.oblique = FALSE; } if(weight < QFont::DemiBold) { // Can make bolder styleKey.weight = QFont::Bold; if(italic) { style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; } else { styleKey.oblique = TRUE; style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; } } } FMDisposeFontFamilyInstanceIterator(&fit); } } FMDisposeFontFamilyIterator(&it); } }