/* PsychInitFontList() Build a list of records describing installed fonts. */ void PsychInitFontList(void) { ATSFontRef tempATSFontRef; CTFontRef tempCTFontRef; //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; psych_bool reportTrouble = TRUE; 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. 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... // However, allow user to suppress the hint, as this happens quite regularly on 32-Bit OSX: if (reportTrouble && trouble && PsychPrefStateGet_Verbosity() > 2) { reportTrouble = FALSE; // Only show this hint once, not for every invalid font. printf("\nPTB-HINT: =============================================================================================================================\n"); printf("PTB-HINT: At least one font on this system has issues and can not be accessed by Psychtoolbox. If you want to know which font(s) make\n"); printf("PTB-HINT: trouble, do a 'clear all' and rerun your script with Screen()'s verbosity level set to at least 4 for more diagnostic output.\n"); printf("PTB-HINT: The following tips may help you to resolve font issues:\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: You can suppress this hint by choosing a verbosity level for Screen() of 2 or lower.\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); // 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() > 3) 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() > 3) printf("PTB-WARNING: In font initialization: Failed to retrieve CTFontRef for font... Defective font?!? Skipped this entry...\n"); trouble = TRUE; continue; } //get the font name and set the the corresponding field of the struct if (ATSFontGetName(fontRecord->fontATSRef, kATSOptionFlagsDefault, &cfFontName)!=noErr) { if (PsychPrefStateGet_Verbosity() > 3) 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() > 3) 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() > 3) 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() > 3) 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); for (j = 0; j < fontFamilyQuickDrawNamePString[0]; j++) fontRecord->fontFamilyQuickDrawName[j] = fontFamilyQuickDrawNamePString[j+1]; fontRecord->fontFamilyQuickDrawName[j] = 0; osStatus = ATSFontGetFileReference(fontRecord->fontATSRef, &fontFileRef); if(osStatus != noErr) { if (PsychPrefStateGet_Verbosity() > 3) 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; } osStatus= FSRefMakePath(&fontFileRef, (UInt8*) fontRecord->fontFile, (UInt32)(kPsychMaxFontFileNameChars - 1)); if(osStatus!=noErr){ if (PsychPrefStateGet_Verbosity() > 3) 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; 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 there was some trouble and it wasn't reported yet, then report it now at the end if either // verbosity level is at least 3 (our default level), or if the error was especially serious and // lead to a premature abortion of font iteration or complete failure to find even a single valid // font. In the latter cases, we must report the trouble, regardless of verbosity level. In the // former case, probably only a few fonts had trouble, so we allow the user to suppress such messages // by lowering the verbosity to warning level or lower: if (reportTrouble && trouble && ((PsychPrefStateGet_Verbosity() > 2) || (halt != kATSIterationCompleted) || (i == 0))) { printf("PTB-HINT: =============================================================================================================================\n"); printf("PTB-HINT: At least one font on this system has issues and can not be accessed by Psychtoolbox. If you want to know which font(s) make\n"); printf("PTB-HINT: trouble, do a 'clear all' and rerun your script with Screen()'s verbosity level set to at least 4 for more diagnostic output.\n"); printf("PTB-HINT: The following tips may help you to resolve font issues:\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: In case of non-fatal errors, you can suppress this hint by choosing a verbosity level for Screen() of 2 or lower.\n"); printf("PTB-HINT: =============================================================================================================================\n"); } // Font database ready for use. return; }
/* 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; }