ATSUFontFeatureSelector find_selector_by_name(ATSUFontID fontID, ATSUFontFeatureType featureType, const char* name, int nameLength) { ATSUFontFeatureSelector result = 0x0000FFFF; Str255 inName; inName[0] = nameLength; int i; for (i = 0; i < inName[0]; ++i) inName[i + 1] = name[i]; ItemCount selectorCount; ATSUCountFontFeatureSelectors(fontID, featureType, &selectorCount); if (selectorCount > 0) { ATSUFontFeatureSelector* selectors = (ATSUFontFeatureSelector*)xmalloc(selectorCount * sizeof(ATSUFontFeatureSelector)); ATSUGetFontFeatureSelectors(fontID, featureType, selectorCount, selectors, 0, 0, 0); for (i = 0; i < selectorCount; ++i) { FontNameCode nameCode; ATSUGetFontFeatureNameCode(fontID, featureType, selectors[i], &nameCode); Str255 name; ByteCount nameLen; ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 255, (Ptr)&name[1], &nameLen, 0); name[0] = nameLen; if (EqualString(inName, name, false, true)) { result = selectors[i]; break; } } free((char*)selectors); } return result; }
ATSUFontFeatureType find_feature_by_name(ATSUFontID fontID, const char* name, int nameLength) { ATSUFontFeatureType result = 0x0000FFFF; Str255 inName; inName[0] = nameLength; int i; for (i = 0; i < inName[0]; ++i) inName[i + 1] = name[i]; ItemCount typeCount; ATSUCountFontFeatureTypes(fontID, &typeCount); if (typeCount > 0) { ATSUFontFeatureType* types = (ATSUFontFeatureType*)xmalloc(typeCount * sizeof(ATSUFontFeatureType)); ATSUGetFontFeatureTypes(fontID, typeCount, types, 0); for (i = 0; i < typeCount; ++i) { FontNameCode nameCode; ATSUGetFontFeatureNameCode(fontID, types[i], 0x0000FFFF, &nameCode); Str255 name; ByteCount nameLen; ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 255, (Ptr)&name[1], &nameLen, 0); name[0] = nameLen; if (EqualString(inName, name, false, true)) { result = types[i]; break; } } free((char*)types); } return result; }
ATSUFontVariationAxis find_axis_by_name(ATSUFontID fontID, const char* name, int nameLength) { ATSUFontVariationAxis result = 0; Str255 inName; inName[0] = nameLength; int i; for (i = 0; i < inName[0]; ++i) inName[i + 1] = name[i]; ItemCount varCount; ATSUCountFontVariations(fontID, &varCount); if (varCount > 0) { for (i = 0; i < varCount; ++i) { ATSUFontVariationAxis axis; ATSUGetIndFontVariation(fontID, i, &axis, 0, 0, 0); FontNameCode nameCode; ATSUGetFontVariationNameCode(fontID, axis, &nameCode); Str255 name; ByteCount nameLen; ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 255, (Ptr)&name[1], &nameLen, 0); name[0] = nameLen; if (EqualString(inName, name, false, true)) { result = axis; break; } } } return result; }
bool MCField::macmatchfontname(const char *p_font_name, char p_derived_font_name[]) { ATSUFontID t_font_id; if (ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontUniqueName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontFamilyName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr || ATSUFindFontFromName(p_font_name, strlen(p_font_name), kFontNoName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &t_font_id) == noErr) { // Fetch the style name char t_style_name[64]; ByteCount t_style_name_length; t_style_name_length = 0; ATSUFindFontName(t_font_id, kFontStyleName, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 63, t_style_name, &t_style_name_length, NULL); t_style_name[t_style_name_length] = '\0'; // Fetch the full name char t_full_name[256]; ByteCount t_full_name_length; t_full_name_length = 0; ATSUFindFontName(t_font_id, kFontFullName, kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, 255, t_full_name, &t_full_name_length, NULL); t_full_name[t_full_name_length] = '\0'; // MW-2011-09-02: Make sure we don't do anything at all if style is regular // (output name should be fullname!) if (MCCStringEqualCaseless(t_style_name, "Regular")) p_font_name = p_font_name; // Do nothing else if (MCCStringEndsWithCaseless(t_full_name, "Bold Italic")) t_full_name[t_full_name_length - 12] = '\0'; else if (MCCStringEndsWithCaseless(t_full_name, "Bold")) t_full_name[t_full_name_length - 5] = '\0'; else if (MCCStringEndsWithCaseless(t_full_name, "Italic")) t_full_name[t_full_name_length - 7] = '\0'; strcpy(p_derived_font_name, t_full_name); return true; } return false; }
pascal OSStatus wxMacCarbonFontPanelHandler(EventHandlerCallRef WXUNUSED(nextHandler), EventRef event, void *userData) { OSStatus result = eventNotHandledErr ; wxFontDialog *fontdialog = (wxFontDialog*) userData ; wxFontData& fontdata= fontdialog->GetFontData() ; wxMacCarbonEvent cEvent( event ); switch(cEvent.GetKind()) { case kEventFontSelection : { bool setup = false ; #if wxOSX_USE_CORE_TEXT if ( UMAGetSystemVersion() >= 0x1050 ) { CTFontDescriptorRef descr; if ( cEvent.GetParameter<CTFontDescriptorRef>( kEventParamCTFontDescriptor, typeCTFontDescriptorRef, &descr ) == noErr ) { wxFont font; wxNativeFontInfo fontinfo; fontinfo.Init(descr); font.Create(fontinfo); fontdata.SetChosenFont( font ) ; setup = true; } } #endif #if wxOSX_USE_ATSU_TEXT ATSUFontID fontId = 0 ; if ( !setup && (cEvent.GetParameter<ATSUFontID>(kEventParamATSUFontID, &fontId) == noErr) ) { FMFontStyle fontStyle = cEvent.GetParameter<FMFontStyle>(kEventParamFMFontStyle); FMFontSize fontSize = cEvent.GetParameter<FMFontSize>(kEventParamFMFontSize); CFStringRef cfName = NULL; #if 1 FMFontFamily fontFamily = cEvent.GetParameter<FMFontFamily>(kEventParamFMFontFamily); ATSFontFamilyRef atsfontfamilyref = FMGetATSFontFamilyRefFromFontFamily( fontFamily ) ; OSStatus err = ATSFontFamilyGetName( atsfontfamilyref , kATSOptionFlagsDefault , &cfName ) ; if ( err != noErr ) { wxFAIL_MSG("ATSFontFamilyGetName failed"); } #else // we don't use the ATSU naming anymore ByteCount actualLength = 0; char *c = NULL; OSStatus err = ATSUFindFontName(fontId , kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode, kFontNoLanguageCode , 0 , NULL , &actualLength , NULL ); if ( err == noErr) { actualLength += 1 ; char *c = (char*)malloc( actualLength ); err = ATSUFindFontName(fontId, kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode, kFontNoLanguageCode, actualLength, c , NULL, NULL); cfName = CFStringCreateWithCharacters(NULL, (UniChar*) c, (actualLength-1) >> 1); } else { err = ATSUFindFontName(fontId , kFontFamilyName, kFontNoPlatformCode, kFontNoScriptCode, kFontNoLanguageCode , 0 , NULL , &actualLength , NULL ); if ( err == noErr ) { actualLength += 1 ; c = (char*)malloc(actualLength); err = ATSUFindFontName(fontId, kFontFamilyName, kFontNoPlatformCode, kFontNoScriptCode, kFontNoLanguageCode, actualLength, c , NULL, NULL); c[actualLength-1] = 0; cfName = CFStringCreateWithCString(NULL, c, kCFStringEncodingMacRoman ); } } if ( c!=NULL ) free(c); #endif if ( cfName!=NULL ) { fontdata.m_chosenFont.SetFaceName(wxCFStringRef(cfName).AsString(wxLocale::GetSystemEncoding())); fontdata.m_chosenFont.SetPointSize(fontSize); fontdata.m_chosenFont.SetStyle(fontStyle & italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL); fontdata.m_chosenFont.SetUnderlined((fontStyle & underline)!=0); fontdata.m_chosenFont.SetWeight(fontStyle & bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); } }
void PlatformFont::enumeratePlatformFonts( Vector< StringTableEntry >& fonts, UTF16* fontFamily ) { if( fontFamily ) { // Determine the font ID from the family name. ATSUFontID fontID; if( ATSUFindFontFromName( fontFamily, dStrlen( fontFamily ) * 2, kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, &fontID ) != kATSUInvalidFontErr ) { // Get the number of fonts in the family. ItemCount numFonts; ATSUCountFontNames( fontID, &numFonts ); // Read out font names. U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; FontNameCode fontNameCode; FontPlatformCode fontPlatformCode; FontScriptCode fontScriptCode; FontLanguageCode fontLanguageCode; if( ATSUGetIndFontName( fontID, i, bufferSize - 2, buffer, &actualNameLength, &fontNameCode, &fontPlatformCode, &fontScriptCode, &fontLanguageCode ) == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); fonts.push_back( StringTable->insert( utf8 ) ); delete [] utf8; break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } } else { // Get the number of installed fonts. ItemCount numFonts; ATSUFontCount( &numFonts ); // Get all the font IDs. ATSUFontID* fontIDs = new ATSUFontID[ numFonts ]; if( ATSUGetFontIDs( fontIDs, numFonts, &numFonts ) == noErr ) { U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); // Read all family names. for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; ItemCount fontIndex; OSStatus result = ATSUFindFontName( fontIDs[ i ], kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, bufferSize - 2, buffer, &actualNameLength, &fontIndex ); if( result == kATSUNoFontNameErr ) break; else if( result == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); StringTableEntry name = StringTable->insert( utf8 ); delete [] utf8; // Avoid duplicates. bool duplicate = false; for( U32 i = 0, num = fonts.size(); i < num; ++ i ) if( fonts[ i ] == name ) { duplicate = true; break; } if( !duplicate ) fonts.push_back( name ); break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } delete [] fontIDs; } }
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { const char *str; bool result = false; callback->FindMissingGlyphs(&str); #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 if (strncmp(language_isocode, "ur", 2) == 0) { /* The urdu alphabet is variant of persian. As OS X has no default * font that advertises an urdu language code, search for persian * support instead. */ strecpy(lang, "fa", 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'; } CFStringRef lang_code; lang_code = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8); /* Create a font iterator and iterate over all fonts that * are available to the application. */ ATSFontIterator itr; ATSFontRef font; ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsUnRestrictedScope, &itr); while (!result && ATSFontIteratorNext(itr, &font) == noErr) { /* Get CoreText font handle. */ CTFontRef font_ref = CTFontCreateWithPlatformFont(font, 0.0, NULL, NULL); CFArrayRef langs = CTFontCopySupportedLanguages(font_ref); if (langs != NULL) { /* Font has a list of supported languages. */ for (CFIndex i = 0; i < CFArrayGetCount(langs); i++) { CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(langs, i); if (CFStringCompare(lang, lang_code, kCFCompareAnchored) == kCFCompareEqualTo) { /* Lang code is supported by font, get full font name. */ CFStringRef font_name = CTFontCopyFullName(font_ref); char name[128]; CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8); CFRelease(font_name); /* Skip some inappropriate or ugly looking fonts that have better alternatives. */ if (strncmp(name, "Courier", 7) == 0 || strncmp(name, "Apple Symbols", 13) == 0 || strncmp(name, ".Aqua", 5) == 0 || strncmp(name, "LastResort", 10) == 0 || strncmp(name, "GB18030 Bitmap", 14) == 0) continue; /* Save result. */ callback->SetFontNames(settings, name); DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); result = true; break; } } CFRelease(langs); } CFRelease(font_ref); } ATSFontIteratorRelease(&itr); CFRelease(lang_code); } else #endif { #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !__LP64__ /* Determine fallback font using ATSUI. This uses a string sample with * missing characters. This is not failure-proof, but a better way like * using the isocode as in the CoreText code path is not available. * ATSUI was deprecated with 10.6 and is only partially available in * 64-bit mode. */ /* Remove all control characters in the range from SCC_CONTROL_START to * SCC_CONTROL_END as well as all ASCII < 0x20 from the string as it will * mess with the automatic font detection */ char buff[256]; // This length is enough to find a suitable replacement font strecpy(buff, str, lastof(buff)); str_validate(buff, lastof(buff), SVS_ALLOW_NEWLINE); /* Extract a UniChar representation of the sample string. */ CFStringRef cf_str = CFStringCreateWithCString(kCFAllocatorDefault, buff, kCFStringEncodingUTF8); if (cf_str == NULL) { /* Something went wrong. Corrupt/invalid sample string? */ return false; } CFIndex str_len = CFStringGetLength(cf_str); UniChar string[str_len]; CFStringGetCharacters(cf_str, CFRangeMake(0, str_len), string); /* Create a default text style with the default font. */ ATSUStyle style; ATSUCreateStyle(&style); /* Create a text layout object from the sample string using the text style. */ UniCharCount run_len = kATSUToTextEnd; ATSUTextLayout text_layout; ATSUCreateTextLayoutWithTextPtr(string, kATSUFromTextBeginning, kATSUToTextEnd, str_len, 1, &run_len, &style, &text_layout); /* Try to match a font for the sample text. ATSUMatchFontsToText stops after * it finds the first continuous character run not renderable with the currently * selected font starting at offset. The matching needs to be repeated until * the end of the string is reached to make sure the fallback font matches for * all characters in the string and not only the first run. */ UniCharArrayOffset offset = kATSUFromTextBeginning; OSStatus os_err; do { ATSUFontID font; UniCharCount run_len; os_err = ATSUMatchFontsToText(text_layout, offset, kATSUToTextEnd, &font, &offset, &run_len); if (os_err == kATSUFontsMatched) { /* Found a better fallback font. Update the text layout * object with the new font. */ ATSUAttributeTag tag = kATSUFontTag; ByteCount size = sizeof(font); ATSUAttributeValuePtr val = &font; ATSUSetAttributes(style, 1, &tag, &size, &val); offset += run_len; } /* Exit if the end of the string is reached or some other error occurred. */ } while (os_err == kATSUFontsMatched && offset < (UniCharArrayOffset)str_len); if (os_err == noErr || os_err == kATSUFontsMatched) { /* ATSUMatchFontsToText exited normally. Extract font * out of the text layout object. */ ATSUFontID font; ByteCount act_len; ATSUGetAttribute(style, kATSUFontTag, sizeof(font), &font, &act_len); /* Get unique font name. The result is not a c-string, we have * to leave space for a \0 and terminate it ourselves. */ char name[128]; ATSUFindFontName(font, kFontUniqueName, kFontNoPlatformCode, kFontNoScriptCode, kFontNoLanguageCode, 127, name, &act_len, NULL); name[act_len > 127 ? 127 : act_len] = '\0'; /* Save Result. */ callback->SetFontNames(settings, name); DEBUG(freetype, 2, "ATSUI-Font for %s: %s", language_isocode, name); result = true; } ATSUDisposeTextLayout(text_layout); ATSUDisposeStyle(style); CFRelease(cf_str); #endif } if (result && strncmp(settings->medium.font, "Geeza Pro", 9) == 0) { /* The font 'Geeza Pro' is often found for arabic characters, but * it has the 'tiny' problem of not having any latin characters. * 'Arial Unicode MS' on the other hand has arabic and latin glyphs, * but seems to 'forget' to inform the OS about this fact. Manually * substitute the latter for the former if it is loadable. */ bool ft_init = _library != NULL; FT_Face face; /* Init FreeType if needed. */ if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName("Arial Unicode MS", &face) == FT_Err_Ok) { FT_Done_Face(face); callback->SetFontNames(settings, "Arial Unicode MS"); DEBUG(freetype, 1, "Replacing font 'Geeza Pro' with 'Arial Unicode MS'"); } if (!ft_init) { /* Uninit FreeType if we did the init. */ FT_Done_FreeType(_library); _library = NULL; } } callback->FindMissingGlyphs(NULL); return result; }