/* get the macos name for the font instance and mangle it into a PS fontname */ static char *makePSFontName(FMFontFamily Family, FMFontStyle Style) { Str255 Name; OSStatus result; int length; char *stylename, *fontname; char *psname; result = FMGetFontFamilyName(Family, Name); if (result != noErr) return NULL; fontname = MacStr2c(Name); if (fontname == NULL) return NULL; strip_char(fontname, strlen(fontname), ' '); switch (Style) { case 0: stylename=""; break;; case 1: stylename="Bold"; break;; case 2: stylename="Italic"; break;; case 3: stylename="BoldItalic"; break;; default: stylename="Unknown"; break;; } length = strlen(fontname) + strlen(stylename) + 2; psname = malloc(length); if (Style != 0) snprintf(psname, length, "%s-%s", fontname, stylename); else snprintf(psname, length, "%s", fontname); free(fontname); return psname; }
/*! Returns an ATSUFontID */ quint32 QFont::macFontID() const // ### need 64-bit version { #ifdef QT_MAC_USE_COCOA return 0; #elif 1 QFontEngine *fe = d->engineForScript(QUnicodeTables::Common); if (fe && fe->type() == QFontEngine::Multi) return static_cast<QFontEngineMacMulti*>(fe)->macFontID(); #else Str255 name; if(FMGetFontFamilyName((FMFontFamily)((UInt32)handle()), name) == noErr) { short fnum; GetFNum(name, &fnum); return fnum; } #endif return 0; }
FT_GetFile_From_Mac_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) { OptionBits options = kFMUseGlobalScopeOption; FMFontFamilyIterator famIter; OSStatus status = FMCreateFontFamilyIterator( NULL, NULL, options, &famIter ); FMFont the_font = 0; FMFontFamily family = 0; if ( !fontName || !face_index ) return FT_THROW( Invalid_Argument ); *face_index = 0; while ( status == 0 && !the_font ) { status = FMGetNextFontFamily( &famIter, &family ); if ( status == 0 ) { int stat2; FMFontFamilyInstanceIterator instIter; Str255 famNameStr; char famName[256]; /* get the family name */ FMGetFontFamilyName( family, famNameStr ); CopyPascalStringToC( famNameStr, famName ); /* iterate through the styles */ FMCreateFontFamilyInstanceIterator( family, &instIter ); *face_index = 0; stat2 = 0; while ( stat2 == 0 && !the_font ) { FMFontStyle style; FMFontSize size; FMFont font; stat2 = FMGetNextFontFamilyInstance( &instIter, &font, &style, &size ); if ( stat2 == 0 && size == 0 ) { char fullName[256]; /* build up a complete face name */ ft_strcpy( fullName, famName ); if ( style & bold ) ft_strcat( fullName, " Bold" ); if ( style & italic ) ft_strcat( fullName, " Italic" ); /* compare with the name we are looking for */ if ( ft_strcmp( fullName, fontName ) == 0 ) { /* found it! */ the_font = font; } else ++(*face_index); } } FMDisposeFontFamilyInstanceIterator( &instIter ); } } FMDisposeFontFamilyIterator( &famIter ); if ( the_font ) { FMGetFontContainer( the_font, pathSpec ); return FT_Err_Ok; } else return FT_THROW( Unknown_File_Format ); }
/* 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; }
void QFontDatabase::createDatabase() { if(db) return; db = new QFontDatabasePrivate; qfontdatabase_cleanup.set(&db); FMFontFamilyIterator it; QString foundry_name = "Mac"; if(!FMCreateFontFamilyIterator(NULL, NULL, kFMUseGlobalScopeOption, &it)) { FMFontFamily fam; QString fam_name; while(!FMGetNextFontFamily(&it, &fam)) { static Str255 n; if(FMGetFontFamilyName(fam, n) != noErr) qDebug("Qt: internal: WH0A, %s %d", __FILE__, __LINE__); if(!n[0] || n[1] == '.') //throw out ones starting with a . continue; { short fnum; ATSUFontID fond; GetFNum(n, &fnum); if(ATSUFONDtoFontID(fnum, 0, &fond) != noErr) continue; } TextEncoding encoding; FMGetFontFamilyTextEncoding(fam, &encoding); TextToUnicodeInfo uni_info; CreateTextToUnicodeInfoByEncoding(encoding, &uni_info); unsigned long len = n[0] * 2; unsigned char *buff = (unsigned char *)malloc(len); ConvertFromPStringToUnicode(uni_info, n, len, &len, (UniCharArrayPtr)buff); fam_name = ""; for(unsigned long x = 0; x < len; x+=2) { #if defined(__i386__) fam_name += QChar(buff[x], buff[x+1]); #else fam_name += QChar(buff[x+1], buff[x]); #endif } free(buff); DisposeTextToUnicodeInfo(&uni_info); QtFontFamily *family = db->family( fam_name, TRUE ); family->macFamily = fam; for(int script = 0; script < QFont::LastPrivateScript; ++script) family->scripts[script] = QtFontFamily::Supported; QtFontFoundry *foundry = family->foundry( foundry_name, TRUE ); FMFontFamilyInstanceIterator fit; if(!FMCreateFontFamilyInstanceIterator(fam, &fit)) { FMFont font; FMFontStyle font_style; FMFontSize font_size; while(!FMGetNextFontFamilyInstance(&fit, &font, &font_style, &font_size)) { bool italic = (bool)(font_style & ::italic); int weight = ((font_style & ::bold) ? QFont::Bold : QFont::Normal); QtFontStyle::Key styleKey; styleKey.italic = italic; styleKey.oblique = false; styleKey.weight = weight; QtFontStyle *style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; if( !italic ) { styleKey.oblique = TRUE; style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; styleKey.oblique = FALSE; } if(weight < QFont::DemiBold) { // Can make bolder styleKey.weight = QFont::Bold; if(italic) { style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; } else { styleKey.oblique = TRUE; style = foundry->style( styleKey, TRUE ); style->smoothScalable = TRUE; } } } FMDisposeFontFamilyInstanceIterator(&fit); } } FMDisposeFontFamilyIterator(&it); } }
static gx_xfont * mac_lookup_font(gx_device *dev, const byte *fname, uint len, int encoding_index, const gs_uid *puid, const gs_matrix *pmat, gs_memory_t *mem) { #pragma unused(encoding_index,puid) mac_xfont *macxf; CGrafPort *currentPort; int txFont, txSize, txMode; StyleField txFace; Fixed spExtra; /* are XFonts enabled? */ if (((gx_device_macos*) dev)->useXFonts == false) return NULL; /* we can handle only requests from these encodings */ if (encoding_index != ENCODING_INDEX_MACROMAN && encoding_index != ENCODING_INDEX_ISOLATIN1 && encoding_index != ENCODING_INDEX_STANDARD) return NULL; /* Don't render very small fonts */ if (fabs(pmat->xx * 1000.0) < 3.0) return NULL; /* Only handle simple cases for now (no transformations). */ if (fabs(pmat->xy) > 0.0001 || fabs(pmat->yx) > 0.0001 || pmat->xx <= 0) return NULL; /* allocate memory for gx_xfont */ macxf = gs_alloc_struct(mem, mac_xfont, &st_mac_xfont, "mac_lookup_font"); if (macxf == NULL) { return NULL; } /* set default values */ macxf->common.procs = &mac_xfont_procs; macxf->dev = dev; /* find the specified font */ mac_find_font_family(fname, len, &(macxf->fontID), &(macxf->fontFace)); /* no font found */ if (macxf->fontID == 0) return NULL; FMGetFontFamilyName(macxf->fontID, macxf->fontName); macxf->fontSize = (short)(pmat->xx * 1000.0); macxf->fontEncoding = mac_get_font_encoding(macxf); /* we can handle only fonts with these encodings for now (all original Mac fonts have MacRoman encoding!) */ if (macxf->fontEncoding != ENCODING_INDEX_MACROMAN && macxf->fontEncoding != ENCODING_INDEX_ISOLATIN1) return NULL; /* get font metrics */ /* save current GrafPort's font information */ GetPort(&((GrafPort*) currentPort)); txFont = currentPort->txFont; txSize = currentPort->txSize; txFace = currentPort->txFace; txMode = currentPort->txMode; spExtra = currentPort->spExtra; /* set values for measuring */ TextFont(macxf->fontID); TextSize(macxf->fontSize); TextFace(macxf->fontFace); TextMode(srcOr); SpaceExtra(0); /* measure font */ FontMetrics(&(macxf->fontMetrics)); /* restore current GrafPort's font information */ currentPort->txFont = txFont; currentPort->txSize = txSize; currentPort->txFace = txFace; currentPort->txMode = txMode; currentPort->spExtra = spExtra; return (gx_xfont*) macxf; }
/* 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; }