static void match_fonts(ASS_Library *lib, ASS_FontProvider *provider, char *name) { const size_t attributes_n = 3; CTFontDescriptorRef ctdescrs[attributes_n]; CFMutableDictionaryRef cfattrs[attributes_n]; CFStringRef attributes[attributes_n] = { kCTFontFamilyNameAttribute, kCTFontDisplayNameAttribute, kCTFontNameAttribute, }; CFStringRef cfname = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); for (int i = 0; i < attributes_n; i++) { cfattrs[i] = CFDictionaryCreateMutable(NULL, 0, 0, 0); CFDictionaryAddValue(cfattrs[i], attributes[i], cfname); ctdescrs[i] = CTFontDescriptorCreateWithAttributes(cfattrs[i]); } CFArrayRef descriptors = CFArrayCreate(NULL, (const void **)&ctdescrs, attributes_n, NULL); CTFontCollectionRef ctcoll = CTFontCollectionCreateWithFontDescriptors(descriptors, 0); CFArrayRef fontsd = CTFontCollectionCreateMatchingFontDescriptors(ctcoll); process_descriptors(provider, fontsd); SAFE_CFRelease(fontsd); SAFE_CFRelease(ctcoll); for (int i = 0; i < attributes_n; i++) { SAFE_CFRelease(cfattrs[i]); SAFE_CFRelease(ctdescrs[i]); } SAFE_CFRelease(descriptors); SAFE_CFRelease(cfname); }
QString QFontDatabase::resolveFontFamilyAlias(const QString &family) { QCFString expectedFamily = QCFString(family); QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, expectedFamily); QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes); QCFType<CFMutableSetRef> mandatoryAttributes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); CFSetAddValue(mandatoryAttributes, kCTFontFamilyNameAttribute); QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL); QCFType<CTFontDescriptorRef> matched = CTFontDescriptorCreateMatchingFontDescriptor(descriptor, mandatoryAttributes); if (!matched) return family; QCFString familyName = (CFStringRef) CTFontDescriptorCopyLocalizedAttribute(matched, kCTFontFamilyNameAttribute, NULL); return familyName; }
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 } QFontEngine *engine = NULL; #if defined(QT_MAC_USE_COCOA) // Shortcut to get the font directly without going through the font database if (!req.family.isEmpty() && !req.styleName.isEmpty()) { QCFString expectedFamily = QCFString(req.family); QCFString expectedStyle = QCFString(req.styleName); QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, expectedFamily); CFDictionaryAddValue(attributes, kCTFontStyleNameAttribute, expectedStyle); QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes); CGAffineTransform transform = qt_transform_from_fontdef(req); QCFType<CTFontRef> ctFont = CTFontCreateWithFontDescriptor(descriptor, req.pixelSize, &transform); if (ctFont) { QCFString familyName = CTFontCopyFamilyName(ctFont); // Only accept the font if the family name is exactly the same as we specified if (CFEqual(expectedFamily, familyName)) { engine = new QCoreTextFontEngineMulti(ctFont, req, d->kerning); } } } #endif if (!engine) engine = loadFromDatabase(req, d); if (engine) { d->engineData->engine = engine; engine->ref.ref(); QFontCache::instance()->insertEngine(key, engine); } }
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; }
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { bool result = false; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (MacOSVersionIsAtLeast(10, 5, 0)) { /* Determine fallback font using CoreText. This uses the language isocode * to find a suitable font. CoreText is available from 10.5 onwards. */ char lang[16]; if (strcmp(language_isocode, "zh_TW") == 0) { /* Traditional Chinese */ strecpy(lang, "zh-Hant", lastof(lang)); } else if (strcmp(language_isocode, "zh_CN") == 0) { /* Simplified Chinese */ strecpy(lang, "zh-Hans", lastof(lang)); } else { /* Just copy the first part of the isocode. */ strecpy(lang, language_isocode, lastof(lang)); char *sep = strchr(lang, '_'); if (sep != NULL) *sep = '\0'; } /* Create a font descriptor matching the wanted language and latin (english) glyphs. */ CFStringRef lang_codes[2]; lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8); lang_codes[1] = CFSTR("en"); CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks); CFDictionaryRef lang_attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void**)&kCTFontLanguagesAttribute, (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CTFontDescriptorRef lang_desc = CTFontDescriptorCreateWithAttributes(lang_attribs); CFRelease(lang_arr); CFRelease(lang_attribs); CFRelease(lang_codes[0]); /* Get array of all font descriptors for the wanted language. */ CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontLanguagesAttribute, 1, &kCFTypeSetCallBacks); CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(lang_desc, mandatory_attribs); CFRelease(mandatory_attribs); CFRelease(lang_desc); for (CFIndex i = 0; descs != NULL && i < CFArrayGetCount(descs); i++) { CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i); /* Get font traits. */ CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute); CTFontSymbolicTraits symbolic_traits; CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); CFRelease(traits); /* Skip symbol fonts and vertical fonts. */ if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ if (symbolic_traits & kCTFontBoldTrait) continue; /* Select monospaced fonts if asked for. */ if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; /* Get font name. */ char name[128]; CFStringRef font_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute); CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8); CFRelease(font_name); /* There are some special fonts starting with an '.' and the last * resort font that aren't usable. Skip them. */ if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; /* Save result. */ callback->SetFontNames(settings, name); if (!callback->FindMissingGlyphs(NULL)) { DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); result = true; break; } } if (descs != NULL) CFRelease(descs); } else #endif { /* Create a font iterator and iterate over all fonts that * are available to the application. */ ATSFontIterator itr; ATSFontRef font; ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsDefaultScope, &itr); while (!result && ATSFontIteratorNext(itr, &font) == noErr) { /* Get font name. */ char name[128]; CFStringRef font_name; ATSFontGetName(font, kATSOptionFlagsDefault, &font_name); CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8); bool monospace = IsMonospaceFont(font_name); CFRelease(font_name); /* Select monospaced fonts if asked for. */ if (monospace != callback->Monospace()) continue; /* We only want the base font and not bold or italic variants. */ if (strstr(name, "Italic") != NULL || strstr(name, "Bold")) continue; /* Skip some inappropriate or ugly looking fonts that have better alternatives. */ if (name[0] == '.' || strncmp(name, "Apple Symbols", 13) == 0 || strncmp(name, "LastResort", 10) == 0) continue; /* Save result. */ callback->SetFontNames(settings, name); if (!callback->FindMissingGlyphs(NULL)) { DEBUG(freetype, 2, "ATS-Font for %s: %s", language_isocode, name); result = true; break; } } ATSFontIteratorRelease(&itr); } if (!result) { /* For some OS versions, the font 'Arial Unicode MS' does not report all languages it * supports. If we didn't find any other font, just try it, maybe we get lucky. */ callback->SetFontNames(settings, "Arial Unicode MS"); result = !callback->FindMissingGlyphs(NULL); } callback->FindMissingGlyphs(NULL); return result; }
static void *coretext_font_create_with_name_and_size(MCStringRef p_name, uint32_t p_size) { /*CFStringRef t_name; t_name = CFStringCreateWithCString(NULL, p_name, kCFStringEncodingMacRoman); CTFontRef t_font; t_font = NULL; if (t_name != NULL) { t_font = CTFontCreateWithName(t_name, p_size, NULL); CFRelease(t_name); } return (void *)t_font;*/ bool t_success; t_success = true; MCAutoStringRefAsCFString t_cf_name; t_success = t_cf_name . Lock(p_name); CFDictionaryRef t_attributes; t_attributes = NULL; if (t_success) { // MW-2014-07-23: [[ Bug 12426 ]] Only specify the 'name' attribute in the font descriptor // otherwise things don't work correctly on iOS. It seems going via a descriptor stops // the warning on 10.9. // // Updated the font creation routine to use font descriptors. Though CTFontCreateWithName worked, // it logged warnings (on 10.9) whenever it was passed a non-postscript font name. Hopefully using // the display name first in the descriptor will remove the warnings but still keep the fall back behaviour. CFStringRef t_keys[] = { // kCTFontDisplayNameAttribute, kCTFontNameAttribute, // kCTFontFamilyNameAttribute, }; CFTypeRef t_values[] = { *t_cf_name, *t_cf_name, *t_cf_name, }; t_attributes = CFDictionaryCreate(NULL, (const void **)&t_keys, (const void **)&t_values, sizeof(t_keys) / sizeof(t_keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); t_success = t_attributes != NULL; } CTFontDescriptorRef t_descriptor; t_descriptor = NULL; if (t_success) { t_descriptor = CTFontDescriptorCreateWithAttributes(t_attributes); t_success = t_descriptor != NULL; } CTFontRef t_font; t_font = NULL; if (t_success) t_font = CTFontCreateWithFontDescriptor(t_descriptor, p_size, NULL); CFStringRef t_font_name = CTFontCopyFullName(t_font); if (t_descriptor != NULL) CFRelease(t_descriptor); if (t_attributes != NULL) CFRelease(t_attributes); return (void *)t_font; }
static void pango_core_text_family_list_faces (PangoFontFamily *family, PangoFontFace ***faces, int *n_faces) { PangoCoreTextFamily *ctfamily = PANGO_CORE_TEXT_FAMILY (family); if (ctfamily->n_faces < 0) { GList *l; GList *faces = NULL; GList *synthetic_faces = NULL; GHashTable *italic_faces; const char *real_family = get_real_family (ctfamily->family_name); CTFontCollectionRef collection; CFArrayRef ctfaces; CFArrayRef font_descriptors; CFDictionaryRef attributes; CFIndex i, count; CFTypeRef keys[] = { (CFTypeRef) kCTFontFamilyNameAttribute }; CFStringRef values[] = { CFStringCreateWithCString (kCFAllocatorDefault, real_family, kCFStringEncodingUTF8) }; CTFontDescriptorRef descriptors[1]; attributes = CFDictionaryCreate (kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); descriptors[0] = CTFontDescriptorCreateWithAttributes (attributes); font_descriptors = CFArrayCreate (kCFAllocatorDefault, (const void **)descriptors, 1, &kCFTypeArrayCallBacks); collection = CTFontCollectionCreateWithFontDescriptors (font_descriptors, NULL); ctfaces = CTFontCollectionCreateMatchingFontDescriptors (collection); italic_faces = g_hash_table_new (g_direct_hash, g_direct_equal); count = CFArrayGetCount (ctfaces); for (i = 0; i < count; i++) { PangoCoreTextFace *face; CTFontDescriptorRef desc = CFArrayGetValueAtIndex (ctfaces, i); face = pango_core_text_face_from_ct_font_descriptor (desc); face->family = ctfamily; faces = g_list_prepend (faces, face); if (face->traits & kCTFontItalicTrait || pango_core_text_face_is_oblique (face)) g_hash_table_insert (italic_faces, GINT_TO_POINTER ((gint)face->weight), face); } CFRelease (font_descriptors); CFRelease (attributes); CFRelease (ctfaces); /* For all fonts for which a non-synthetic italic variant does * not exist on the system, we create synthesized versions here. */ for (l = faces; l; l = l->next) { PangoCoreTextFace *face = l->data; if (!g_hash_table_lookup (italic_faces, GINT_TO_POINTER ((gint)face->weight))) { PangoCoreTextFace *italic_face; italic_face = g_object_new (PANGO_TYPE_CORE_TEXT_FACE, NULL); italic_face->family = ctfamily; italic_face->postscript_name = g_strdup (face->postscript_name); italic_face->weight = face->weight; italic_face->traits = face->traits | kCTFontItalicTrait; italic_face->synthetic_italic = TRUE; italic_face->coverage = pango_coverage_ref (face->coverage); /* Try to create a sensible face name. */ if (strcasecmp (face->style_name, "regular") == 0) italic_face->style_name = g_strdup ("Oblique"); else italic_face->style_name = g_strdup_printf ("%s Oblique", face->style_name); synthetic_faces = g_list_prepend (synthetic_faces, italic_face); } } faces = g_list_concat (faces, synthetic_faces); ctfamily->n_faces = g_list_length (faces); ctfamily->faces = g_new (PangoFontFace *, ctfamily->n_faces); for (l = faces, i = 0; l; l = l->next, i++) ctfamily->faces[i] = l->data; g_list_free (faces); g_hash_table_destroy (italic_faces); }