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); } }
/* PsychInitFontList() Build a list of records describing installed fonts. */ void PsychInitFontList(void) { ATSFontRef tempATSFontRef; //for font structures PsychFontStructPtrType fontListHead, fontRecord, previousFontRecord; //for ATI font iteration ATSFontIterator fontIterator; OSStatus halt; //for font field names CFStringRef cfFontName; int i; psych_bool resultOK; //for font file //OSErr osError; OSStatus osStatus; FSSpec fontFileSpec; FSRef fontFileRef; //for the font metrics ATSFontMetrics horizontalMetrics; ATSFontMetrics verticalMetrics; //for info from Font Manager FMFontStyle fmStyle; OSStatus fmStatus; Str255 fmFontFamilyNamePString; //whatever Str255 fontFamilyQuickDrawNamePString; TextEncoding textEncoding; OSStatus scriptInfoOK; ScriptCode scriptCode; LangCode languageCode; OSStatus localOK; LocaleRef locale; psych_bool trouble = FALSE; fontListHead=PsychFontListHeadKeeper(FALSE, NULL); //get the font list head. if(fontListHead) PsychErrorExitMsg(PsychError_internal, "Attempt to set new font list head when one is already set."); fontRecord=NULL; halt= ATSFontIteratorCreate(PSYCH_ATS_ITERATOR_CONTEXT, NULL, NULL, PSYCH_ATS_ITERATOR_SCOPE, &fontIterator); i=0; while(halt==noErr){ halt=ATSFontIteratorNext(fontIterator, &tempATSFontRef); if(halt==noErr){ //create a new font font structure. Set the next field to NULL as soon as we allocate the font so that if //we break with an error then we can find the end when we walk down the linked list. fontRecord=(PsychFontStructPtrType)malloc(sizeof(PsychFontStructType)); fontRecord->next=NULL; //Get FM and ATS font and font family references from the ATS font reference, which we get from iteration. fontRecord->fontATSRef=tempATSFontRef; fontRecord->fontFMRef=FMGetFontFromATSFontRef(fontRecord->fontATSRef); fmStatus=FMGetFontFamilyInstanceFromFont(fontRecord->fontFMRef, &(fontRecord->fontFamilyFMRef), &fmStyle); fontRecord->fontFamilyATSRef=FMGetATSFontFamilyRefFromFontFamily(fontRecord->fontFamilyFMRef); //get the font name and set the the corresponding field of the struct if (ATSFontGetName(fontRecord->fontATSRef, kATSOptionFlagsDefault, &cfFontName)!=noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to query font name in ATSFontGetName! OS-X font handling screwed up?!? Skipped this entry...\n"); trouble = TRUE; continue; } resultOK=CFStringGetCString(cfFontName, (char*) fontRecord->fontFMName, 255, kCFStringEncodingASCII); if(!resultOK){ CFRelease(cfFontName); if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to convert fontFMName CF string to char string. Defective font?!? Skipped this entry...\n"); trouble = TRUE; continue; } CFRelease(cfFontName); //get the font postscript name and set the corresponding field of the struct if (ATSFontGetPostScriptName(fontRecord->fontATSRef, kATSOptionFlagsDefault, &cfFontName)!=noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: The following font makes trouble: %s. Please REMOVE the offending font file from your font folders and restart Matlab. Skipped entry for now...\n", fontRecord->fontFMName); trouble = TRUE; continue; } resultOK=CFStringGetCString(cfFontName, (char*) fontRecord->fontPostScriptName, 255, kCFStringEncodingASCII); //kCFStringEncodingASCII matches MATLAB for 0-127 if(!resultOK){ CFRelease(cfFontName); if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to convert fontPostScriptName CF string to char string for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } CFRelease(cfFontName); //get the QuickDraw name of the font ATSFontFamilyGetQuickDrawName(fontRecord->fontFamilyATSRef, fontFamilyQuickDrawNamePString); CopyPascalStringToC(fontFamilyQuickDrawNamePString, (char*) fontRecord->fontFamilyQuickDrawName); //get the font file used for this font osStatus= ATSFontGetFileSpecification(fontRecord->fontATSRef, &fontFileSpec); if(osStatus != noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the font file specifier for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } FSpMakeFSRef(&fontFileSpec, &fontFileRef); osStatus= FSRefMakePath(&fontFileRef, (UInt8*) fontRecord->fontFile, (UInt32)(kPsychMaxFontFileNameChars - 1)); if(osStatus!=noErr){ if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the font file path for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } //get the font metrics of this font. //Explicit copy between fields to make it clear what is going one, will likely have to mix & match between native and Psych structures for different //platforms. ATSFontGetHorizontalMetrics(fontRecord->fontATSRef, kATSOptionFlagsDefault, &horizontalMetrics); ATSFontGetVerticalMetrics(fontRecord->fontATSRef, kATSOptionFlagsDefault, &verticalMetrics); //horizontal fontRecord->horizontalMetrics.ascent= horizontalMetrics.ascent; fontRecord->horizontalMetrics.descent= horizontalMetrics.descent; fontRecord->horizontalMetrics.leading= horizontalMetrics.leading; fontRecord->horizontalMetrics.avgAdvanceWidth= horizontalMetrics.avgAdvanceWidth; fontRecord->horizontalMetrics.minLeftSideBearing= horizontalMetrics.minLeftSideBearing; fontRecord->horizontalMetrics.minRightSideBearing= horizontalMetrics.minRightSideBearing; fontRecord->horizontalMetrics.stemWidth= horizontalMetrics.stemWidth; fontRecord->horizontalMetrics.stemHeight= horizontalMetrics.stemHeight; fontRecord->horizontalMetrics.capHeight= horizontalMetrics.capHeight; fontRecord->horizontalMetrics.xHeight= horizontalMetrics.xHeight; fontRecord->horizontalMetrics.italicAngle= horizontalMetrics.italicAngle; fontRecord->horizontalMetrics.underlinePosition= horizontalMetrics.underlinePosition; fontRecord->horizontalMetrics.underlineThickness= horizontalMetrics.underlineThickness; fontRecord->horizontalMetrics.underlineThickness= horizontalMetrics.underlineThickness; //vertical fontRecord->verticalMetrics.ascent= verticalMetrics.ascent; fontRecord->verticalMetrics.descent= verticalMetrics.descent; fontRecord->verticalMetrics.leading= verticalMetrics.leading; fontRecord->verticalMetrics.avgAdvanceWidth= verticalMetrics.avgAdvanceWidth; fontRecord->verticalMetrics.minLeftSideBearing= verticalMetrics.minLeftSideBearing; fontRecord->verticalMetrics.minRightSideBearing= verticalMetrics.minRightSideBearing; fontRecord->verticalMetrics.stemWidth= verticalMetrics.stemWidth; fontRecord->verticalMetrics.stemHeight= verticalMetrics.stemHeight; fontRecord->verticalMetrics.capHeight= verticalMetrics.capHeight; fontRecord->verticalMetrics.xHeight= verticalMetrics.xHeight; fontRecord->verticalMetrics.italicAngle= verticalMetrics.italicAngle; fontRecord->verticalMetrics.underlinePosition= verticalMetrics.underlinePosition; fontRecord->verticalMetrics.underlineThickness= verticalMetrics.underlineThickness; fontRecord->verticalMetrics.underlineThickness= verticalMetrics.underlineThickness; //use Font Manager to get the FM font family name font style fmStatus=FMGetFontFamilyName(fontRecord->fontFamilyFMRef, fmFontFamilyNamePString); CopyPascalStringToC(fmFontFamilyNamePString, (char*) fontRecord->fontFMFamilyName); fontRecord->fontFMStyle=fmStyle; fontRecord->fontFMNumStyles=PsychFindNumFMFontStylesFromStyle(fmStyle); fontRecord->fontFMNumStyles= fontRecord->fontFMNumStyles ? fontRecord->fontFMNumStyles : 1; //because the name is "normal" even if there are no styles. //get the locale info which is a property of the font family textEncoding=ATSFontFamilyGetEncoding(fontRecord->fontFamilyATSRef); scriptInfoOK=RevertTextEncodingToScriptInfo(textEncoding, &scriptCode, &languageCode, NULL); localOK=LocaleRefFromLangOrRegionCode(languageCode, kTextRegionDontCare, &locale); localOK=LocaleRefGetPartString(locale, kLocaleLanguageMask, 255, (char*) fontRecord->locale.language); fontRecord->locale.language[255]='\0'; localOK=LocaleRefGetPartString(locale, kLocaleLanguageVariantMask, 255, (char*) fontRecord->locale.languageVariant); fontRecord->locale.languageVariant[255]='\0'; localOK=LocaleRefGetPartString(locale, kLocaleRegionMask, 255, (char*) fontRecord->locale.region); fontRecord->locale.region[255]='\0'; localOK=LocaleRefGetPartString(locale, kLocaleRegionVariantMask, 255, (char*) fontRecord->locale.regionVariant); fontRecord->locale.regionVariant[255]='\0'; localOK=LocaleRefGetPartString(locale, kLocaleAllPartsMask, 255, (char*) fontRecord->locale.fullName); fontRecord->locale.fullName[255]='\0'; // Init for fontRecord (nearly) finished. // Set this fontRecord as head of font-list, or enqueue it in existing list: if(i==0) { PsychFontListHeadKeeper(TRUE, fontRecord); } else { previousFontRecord->next=fontRecord; } // Set the font number field of the struct fontRecord->fontNumber=i+1; // Increment the font index and update the next font pointer ++i; previousFontRecord=fontRecord; }else if(halt == kATSIterationScopeModified){ //exit because the font database changed during this loop. PsychFreeFontList(); PsychErrorExitMsg(PsychError_internal, "The system font database was modified during font list setup. Please 'clear all' and restart your script."); } // Next parse iteration in system font database... } if(halt != kATSIterationCompleted){ PsychFreeFontList(); PsychErrorExitMsg(PsychError_internal, "Font iteration terminated prematurely. OS-X Font database corrupted?!?"); } // Did we get a hand on at least one font? if (i==0) { if (PsychPrefStateGet_Verbosity() > 0) { printf("PTB-ERROR: In font initialization: Could not even retrieve one valid font from the system! The OS-X font database must be corrupt.\n"); printf("PTB-ERROR: Will try to continue but will likely crash if your code tries to call any of the font handling or text drawing functions.\n"); trouble = TRUE; } } if (trouble && PsychPrefStateGet_Verbosity() > 0) { printf("PTB-HINT: Go to the Application folder and open the 'Font Book' application. It allows you to check and repair your font database.\n"); } ATSFontIteratorRelease(&fontIterator); // Font database ready for use. return; }
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); } } }
/* PsychInitFontList() Build a list of records describing installed fonts. */ void PsychInitFontList(void) { ATSFontRef tempATSFontRef; #ifdef __LP64__ CTFontRef tempCTFontRef; #endif //for font structures PsychFontStructPtrType fontListHead, fontRecord, previousFontRecord; //for ATI font iteration ATSFontIterator fontIterator; OSStatus halt; //for font field names CFStringRef cfFontName; int i, j; psych_bool resultOK; //for font file OSStatus osStatus; FSSpec fontFileSpec; FSRef fontFileRef; //for the font metrics ATSFontMetrics horizontalMetrics; ATSFontMetrics verticalMetrics; //for info from Font Manager FMFontStyle fmStyle; OSStatus fmStatus; Str255 fmFontFamilyNamePString; //whatever Str255 fontFamilyQuickDrawNamePString; TextEncoding textEncoding; OSStatus scriptInfoOK; ScriptCode scriptCode; LangCode languageCode; OSStatus localOK; LocaleRef locale; psych_bool trouble = FALSE; fontListHead=PsychFontListHeadKeeper(FALSE, NULL); //get the font list head. if(fontListHead) PsychErrorExitMsg(PsychError_internal, "Attempt to set new font list head when one is already set."); fontRecord = NULL; fontIterator = NULL; halt = ATSFontIteratorCreate(PSYCH_ATS_ITERATOR_CONTEXT, NULL, NULL, PSYCH_ATS_ITERATOR_SCOPE, &fontIterator); i = 0; while (halt==noErr) { // Give repair hints early and obnoxiously. Experience shows we might crash during enumeration of a // corrupt OSX font database, so make sure we get out the helpful message as early as possible. Doing // this (just) at the end of enumeration might be too late - we might never get there... if (trouble && PsychPrefStateGet_Verbosity() > 0) { printf("\nPTB-HINT: ========================================================================================================================\n"); printf("PTB-HINT: Go to the Application folder and open the 'Font Book' application. It allows you to check and repair your font database.\n"); printf("PTB-HINT: Run its 'Validate' function on all installed fonts. Another thing you could try is downloading and running the free\n"); printf("PTB-HINT: FontNuke application (Google will find it for you) to regenerate corrupt OSX font caches. Good luck!\n"); printf("PTB-HINT: ========================================================================================================================\n\n"); } halt=ATSFontIteratorNext(fontIterator, &tempATSFontRef); if(halt==noErr){ //create a new font font structure. Set the next field to NULL as soon as we allocate the font so that if //we break with an error then we can find the end when we walk down the linked list. fontRecord=(PsychFontStructPtrType) calloc(1, sizeof(PsychFontStructType)); fontRecord->next=NULL; //Get FM and ATS font and font family references from the ATS font reference, which we get from iteration. fontRecord->fontATSRef=tempATSFontRef; fontRecord->fontFMRef=FMGetFontFromATSFontRef(fontRecord->fontATSRef); #ifndef __LP64__ fmStatus=FMGetFontFamilyInstanceFromFont(fontRecord->fontFMRef, &(fontRecord->fontFamilyFMRef), &fmStyle); fontRecord->fontFamilyATSRef = FMGetATSFontFamilyRefFromFontFamily(fontRecord->fontFamilyFMRef); #else // Create CTFont from given ATSFontRef. Available since OSX 10.5 tempCTFontRef = CTFontCreateWithPlatformFont(fontRecord->fontATSRef, 0.0, NULL, NULL); if (tempCTFontRef) { // Get font family name from CTFont: CFStringRef cfFamilyName = CTFontCopyFamilyName(tempCTFontRef); // Retrieve symbolic traits of font -- the closest equivalent of the fmStyle from the // good'ol fontManager: CTFontSymbolicTraits ctTraits = CTFontGetSymbolicTraits(tempCTFontRef); // Remap new trait constants to old constants for later Screen('TextStyle') matching. fmStyle = 0; if (ctTraits & kCTFontBoldTrait) fmStyle |= 1; if (ctTraits & kCTFontItalicTrait) fmStyle |= 2; if (ctTraits & kCTFontCondensedTrait) fmStyle |= 32; if (ctTraits & kCTFontExpandedTrait) fmStyle |= 64; // CTFont no longer needed: CFRelease(tempCTFontRef); // Convert to C-String and assign: resultOK = cfFamilyName && CFStringGetCString(cfFamilyName, (char*) fontRecord->fontFMFamilyName, 255, kCFStringEncodingASCII); if(!resultOK){ if (cfFamilyName) CFRelease(cfFamilyName); if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to retrieve font family name for font... Defective font?!? Skipped this entry...\n"); trouble = TRUE; continue; } // Get ATSRef for font family: fontRecord->fontFamilyATSRef = ATSFontFamilyFindFromName(cfFamilyName, kATSOptionFlagsDefault); CFRelease(cfFamilyName); } else { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to retrieve CTFontRef for font... Defective font?!? Skipped this entry...\n"); trouble = TRUE; continue; } #endif //get the font name and set the the corresponding field of the struct if (ATSFontGetName(fontRecord->fontATSRef, kATSOptionFlagsDefault, &cfFontName)!=noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to query font name in ATSFontGetName! OS-X font handling screwed up?!? Skipped this entry...\n"); trouble = TRUE; continue; } resultOK = cfFontName && CFStringGetCString(cfFontName, (char*) fontRecord->fontFMName, 255, kCFStringEncodingASCII); if(!resultOK){ if (cfFontName) CFRelease(cfFontName); if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to convert fontFMName CF string to char string. Defective font?!? Skipped this entry...\n"); trouble = TRUE; continue; } CFRelease(cfFontName); //get the font postscript name and set the corresponding field of the struct if (ATSFontGetPostScriptName(fontRecord->fontATSRef, kATSOptionFlagsDefault, &cfFontName)!=noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: The following font makes trouble: %s. Please REMOVE the offending font file from your font folders and restart Matlab. Skipped entry for now...\n", fontRecord->fontFMName); trouble = TRUE; continue; } resultOK = cfFontName && CFStringGetCString(cfFontName, (char*) fontRecord->fontPostScriptName, 255, kCFStringEncodingASCII); //kCFStringEncodingASCII matches MATLAB for 0-127 if(!resultOK){ if (cfFontName) CFRelease(cfFontName); if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to convert fontPostScriptName CF string to char string for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } CFRelease(cfFontName); // Get the QuickDraw name of the font: fontRecord->fontFamilyQuickDrawName[0] = 0; fontFamilyQuickDrawNamePString[0] = 0; ATSFontFamilyGetQuickDrawName(fontRecord->fontFamilyATSRef, fontFamilyQuickDrawNamePString); #ifndef __LP64__ CopyPascalStringToC(fontFamilyQuickDrawNamePString, (char*) fontRecord->fontFamilyQuickDrawName); #else for (j = 0; j < fontFamilyQuickDrawNamePString[0]; j++) fontRecord->fontFamilyQuickDrawName[j] = fontFamilyQuickDrawNamePString[j+1]; fontRecord->fontFamilyQuickDrawName[j] = 0; #endif #ifndef __LP64__ // Get the font file used for this font osStatus = ATSFontGetFileSpecification(fontRecord->fontATSRef, &fontFileSpec); if(osStatus != noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the font file specifier for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } FSpMakeFSRef(&fontFileSpec, &fontFileRef); #else // 64-Bit version, available since OSX 10.5: osStatus = ATSFontGetFileReference(fontRecord->fontATSRef, &fontFileRef); if(osStatus != noErr) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the font file specifier for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } #endif osStatus= FSRefMakePath(&fontFileRef, (UInt8*) fontRecord->fontFile, (UInt32)(kPsychMaxFontFileNameChars - 1)); if(osStatus!=noErr){ if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the font file path for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } //get the font metrics of this font. //Explicit copy between fields to make it clear what is going one, will likely have to mix & match between native and Psych structures for different //platforms. ATSFontGetHorizontalMetrics(fontRecord->fontATSRef, kATSOptionFlagsDefault, &horizontalMetrics); ATSFontGetVerticalMetrics(fontRecord->fontATSRef, kATSOptionFlagsDefault, &verticalMetrics); //horizontal fontRecord->horizontalMetrics.ascent= horizontalMetrics.ascent; fontRecord->horizontalMetrics.descent= horizontalMetrics.descent; fontRecord->horizontalMetrics.leading= horizontalMetrics.leading; fontRecord->horizontalMetrics.avgAdvanceWidth= horizontalMetrics.avgAdvanceWidth; fontRecord->horizontalMetrics.minLeftSideBearing= horizontalMetrics.minLeftSideBearing; fontRecord->horizontalMetrics.minRightSideBearing= horizontalMetrics.minRightSideBearing; fontRecord->horizontalMetrics.stemWidth= horizontalMetrics.stemWidth; fontRecord->horizontalMetrics.stemHeight= horizontalMetrics.stemHeight; fontRecord->horizontalMetrics.capHeight= horizontalMetrics.capHeight; fontRecord->horizontalMetrics.xHeight= horizontalMetrics.xHeight; fontRecord->horizontalMetrics.italicAngle= horizontalMetrics.italicAngle; fontRecord->horizontalMetrics.underlinePosition= horizontalMetrics.underlinePosition; fontRecord->horizontalMetrics.underlineThickness= horizontalMetrics.underlineThickness; fontRecord->horizontalMetrics.underlineThickness= horizontalMetrics.underlineThickness; //vertical fontRecord->verticalMetrics.ascent= verticalMetrics.ascent; fontRecord->verticalMetrics.descent= verticalMetrics.descent; fontRecord->verticalMetrics.leading= verticalMetrics.leading; fontRecord->verticalMetrics.avgAdvanceWidth= verticalMetrics.avgAdvanceWidth; fontRecord->verticalMetrics.minLeftSideBearing= verticalMetrics.minLeftSideBearing; fontRecord->verticalMetrics.minRightSideBearing= verticalMetrics.minRightSideBearing; fontRecord->verticalMetrics.stemWidth= verticalMetrics.stemWidth; fontRecord->verticalMetrics.stemHeight= verticalMetrics.stemHeight; fontRecord->verticalMetrics.capHeight= verticalMetrics.capHeight; fontRecord->verticalMetrics.xHeight= verticalMetrics.xHeight; fontRecord->verticalMetrics.italicAngle= verticalMetrics.italicAngle; fontRecord->verticalMetrics.underlinePosition= verticalMetrics.underlinePosition; fontRecord->verticalMetrics.underlineThickness= verticalMetrics.underlineThickness; fontRecord->verticalMetrics.underlineThickness= verticalMetrics.underlineThickness; // On 32-Bit use Font Manager to get the FM font family name font style. // This has been already done above for 64-Bit: #ifndef __LP64__ fmStatus=FMGetFontFamilyName(fontRecord->fontFamilyFMRef, fmFontFamilyNamePString); if(fmStatus!=noErr){ if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: In font initialization: Failed to get the fontFMFamilyName for font %s. Defective font?!? Skipped this entry...\n", fontRecord->fontFMName); trouble = TRUE; continue; } CopyPascalStringToC(fmFontFamilyNamePString, (char*) fontRecord->fontFMFamilyName); #endif fontRecord->fontFMStyle=fmStyle; fontRecord->fontFMNumStyles=PsychFindNumFMFontStylesFromStyle(fmStyle); fontRecord->fontFMNumStyles= fontRecord->fontFMNumStyles ? fontRecord->fontFMNumStyles : 1; //because the name is "normal" even if there are no styles. // Get the locale info which is a property of the font family: // No error checking is done here, because many (most?) fonts miss the information, // so we would error-out all the time and this is non-critical for us: textEncoding=ATSFontFamilyGetEncoding(fontRecord->fontFamilyATSRef); scriptInfoOK=RevertTextEncodingToScriptInfo(textEncoding, &scriptCode, &languageCode, NULL); localOK=LocaleRefFromLangOrRegionCode(languageCode, kTextRegionDontCare, &locale); localOK |= LocaleRefGetPartString(locale, kLocaleLanguageMask, 255, (char*) fontRecord->locale.language); fontRecord->locale.language[255]='\0'; localOK |= LocaleRefGetPartString(locale, kLocaleLanguageVariantMask, 255, (char*) fontRecord->locale.languageVariant); fontRecord->locale.languageVariant[255]='\0'; localOK |= LocaleRefGetPartString(locale, kLocaleRegionMask, 255, (char*) fontRecord->locale.region); fontRecord->locale.region[255]='\0'; localOK |= LocaleRefGetPartString(locale, kLocaleRegionVariantMask, 255, (char*) fontRecord->locale.regionVariant); fontRecord->locale.regionVariant[255]='\0'; localOK |= LocaleRefGetPartString(locale, kLocaleAllPartsMask, 255, (char*) fontRecord->locale.fullName); fontRecord->locale.fullName[255]='\0'; // Init for fontRecord (nearly) finished. // Set this fontRecord as head of font-list, or enqueue it in existing list: if(i==0) { PsychFontListHeadKeeper(TRUE, fontRecord); } else { previousFontRecord->next=fontRecord; } // Set the font number field of the struct fontRecord->fontNumber=i+1; // Increment the font index and update the next font pointer ++i; previousFontRecord=fontRecord; }else if(halt == kATSIterationScopeModified){ //exit because the font database changed during this loop. PsychFreeFontList(); if (fontIterator) ATSFontIteratorRelease(&fontIterator); PsychErrorExitMsg(PsychError_system, "The system font database was modified during font list setup. Please 'clear all' and restart your script."); } // Next parse iteration in system font database... } if (fontIterator) ATSFontIteratorRelease(&fontIterator); if(halt != kATSIterationCompleted){ PsychFreeFontList(); trouble = TRUE; if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR: Font iteration during enumeration terminated prematurely. OS-X Font database corrupted?!?"); } // Did we get a hand on at least one font? if (i==0) { PsychFreeFontList(); trouble = TRUE; if (PsychPrefStateGet_Verbosity() > 0) { printf("PTB-ERROR: In font initialization: Could not even retrieve one valid font from the system! The OS-X font database must be corrupt.\n"); printf("PTB-ERROR: Will try to continue but will likely abort if your code tries to call any of the font handling or text drawing functions.\n"); } } if (trouble && PsychPrefStateGet_Verbosity() > 0) { printf("PTB-HINT: ========================================================================================================================\n"); printf("PTB-HINT: Go to the Application folder and open the 'Font Book' application. It allows you to check and repair your font database.\n"); printf("PTB-HINT: Run its 'Validate' function on all installed fonts. Another thing you could try is downloading and running the free\n"); printf("PTB-HINT: FontNuke application (Google will find it for you) to regenerate corrupt OSX font caches. Good luck!\n"); printf("PTB-HINT: ========================================================================================================================\n"); } // Font database ready for use. return; }