/* Mac OS X 10.5 and later. */ static OSStatus FT_ATSFontGetFileReference( ATSFontRef ats_font_id, FSRef* ats_font_ref ) { #if defined( MAC_OS_X_VERSION_10_5 ) && \ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) OSStatus err; err = ATSFontGetFileReference( ats_font_id, ats_font_ref ); return err; #elif __LP64__ /* No 64bit Carbon API on legacy platforms */ FT_UNUSED( ats_font_id ); FT_UNUSED( ats_font_ref ); return fnfErr; #else /* 32bit Carbon API on legacy platforms */ OSStatus err; FSSpec spec; err = ATSFontGetFileSpecification( ats_font_id, &spec ); if ( noErr == err ) err = FSpMakeFSRef( &spec, ats_font_ref ); return err; #endif }
FT_GetFile_From_Mac_ATS_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) { CFStringRef cf_fontName; ATSFontRef ats_font_id; *face_index = 0; cf_fontName = CFStringCreateWithCString( NULL, fontName, kCFStringEncodingMacRoman ); ats_font_id = ATSFontFindFromName( cf_fontName, kATSOptionFlagsUnRestrictedScope ); if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) return FT_Err_Unknown_File_Format; if ( 0 != ATSFontGetFileSpecification( ats_font_id, pathSpec ) ) return FT_Err_Unknown_File_Format; /* face_index calculation by searching preceding fontIDs */ /* with same FSRef */ { int i; FSSpec f; for ( i = 1; i < ats_font_id; i++ ) { if ( 0 != ATSFontGetFileSpecification( ats_font_id - i, &f ) || f.vRefNum != pathSpec->vRefNum || f.parID != pathSpec->parID || f.name[0] != pathSpec->name[0] || 0 != ft_strncmp( (char *)f.name + 1, (char *)pathSpec->name + 1, f.name[0] ) ) break; } *face_index = ( i - 1 ); } return FT_Err_Ok; }
/* Apple will provide one eventually. */ static OSStatus FT_ATSFontGetFileReference( ATSFontRef ats_font_id, FSRef* ats_font_ref ) { OSStatus err; FSSpec spec; err = ATSFontGetFileSpecification( ats_font_id, &spec ); if ( noErr == err ) err = FSpMakeFSRef( &spec, ats_font_ref ); return err; }
/* Mac OS X 10.5 and later. */ static OSStatus FT_ATSFontGetFileReference( ATSFontRef ats_font_id, FSRef* ats_font_ref ) { OSStatus err; #if !defined( MAC_OS_X_VERSION_10_5 ) || \ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 FSSpec spec; err = ATSFontGetFileSpecification( ats_font_id, &spec ); if ( noErr == err ) err = FSpMakeFSRef( &spec, ats_font_ref ); #else err = ATSFontGetFileReference( ats_font_id, ats_font_ref ); #endif return err; }
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) { FT_Error err = FT_Err_Cannot_Open_Resource; /* Get font reference from name. */ CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8); ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault); CFRelease(name); if (font == kInvalidFont) return err; /* Get a file system reference for the font. */ FSRef ref; OSStatus os_err = -1; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) if (MacOSVersionIsAtLeast(10, 5, 0)) { os_err = ATSFontGetFileReference(font, &ref); } else #endif { #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !defined(__LP64__) /* This type was introduced with the 10.5 SDK. */ #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) #define ATSFSSpec FSSpec #endif FSSpec spec; os_err = ATSFontGetFileSpecification(font, (ATSFSSpec *)&spec); if (os_err == noErr) os_err = FSpMakeFSRef(&spec, &ref); #endif } if (os_err == noErr) { /* Get unix path for file. */ UInt8 file_path[PATH_MAX]; if (FSRefMakePath(&ref, file_path, sizeof(file_path)) == noErr) { DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path); err = FT_New_Face(_library, (const char *)file_path, 0, face); } } return err; }
QFontEngine::FaceId QFontEngineMac::faceId() const { FaceId ret; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) FSRef ref; if (ATSFontGetFileReference(FMGetATSFontRefFromFont(fontID), &ref) != noErr) return ret; ret.filename = QByteArray(128, 0); ret.index = fontID; FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); #else FSSpec spec; if (ATSFontGetFileSpecification(FMGetATSFontRefFromFont(fontID), &spec) != noErr) return ret; FSRef ref; FSpMakeFSRef(&spec, &ref); ret.filename = QByteArray(128, 0); ret.index = fontID; FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); #endif return ret; }
/* 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; }
/* 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; }