Rewrite font system to cache fonts in a plist and support nfont bundles.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@25717 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Isaiah Beerbower 2007-12-11 00:14:01 +00:00
parent 2cc8536f04
commit 2d50c93089
5 changed files with 781 additions and 164 deletions

View file

@ -1,3 +1,19 @@
2007-12-10 Isaiah Beerbower <public@ipaqah.com>
* Source/cairo/CairoFontEnumerator.m (-enumerateFontsAndFamilies, cacheFolder,
bundleModificationDate, cacheFont, cacheNFontBundle, mergeFontInfo):
Rewrite to cache fonts in a plist and support nfont bundles.
(-defaultSystemFontName, -defaultBoldSystemFontName,
-defaultFixedPitchFontName):
Added actual PostScript name for Bitstream Vera fonts.
* Source/cairo/CairoFaceInfo.m (-fontFace,
-initWithfamilyName:fullName:weight:italicAngle:traits:files:index:,
-setFullName:, -fullName, -setItalicAngle:, -italicAngle, -setIndex:, -index):
Update to reflect changes in CairoFontEnumerator.
* Headers/cairo/CairoFaceInfo.m: Same.
* Source/cairo/CairoFontInfo.m (-setupAttributes): Take italicAngle & fullName
from CairoFaceInfo.
2007-12-10 Fred Kiefer <FredKiefer@gmx.de>
* Source/xlib/GSXftFontInfo.m:

View file

@ -39,28 +39,47 @@
@interface CairoFaceInfo : NSObject
{
int _weight;
float _italicAngle;
unsigned int _traits;
FT_Library _ftlibrary;
FT_Face _ftface;
cairo_font_face_t *_fontFace;
FcPattern *_pattern;
cairo_font_face_t *_fontFace;
NSArray *_filePaths;
int _indexInFile;
NSString *_familyName;
NSString *_fullName;
}
- (id) initWithfamilyName: (NSString *)familyName
- (id) initWithfamilyName: (NSString *)familyName
fullName: (NSString *)fullName
weight: (int)weight
italicAngle: (float)italicAngle
traits: (unsigned int)traits
pattern: (FcPattern *)pattern;
files: (NSArray *)paths
index: (int)index;
- (unsigned int) cacheSize;
- (int) weight;
- (void) setWeight: (int)weight;
- (int) italicAngle;
- (void) setItalicAngle: (float)italicAngle;
- (unsigned int) traits;
- (void) setTraits: (unsigned int)traits;
- (NSString *) familyName;
- (void) setFamilyName: (NSString *)name;
- (NSString *)fullName;
- (void) setFullName: (NSString *)name;
- (void) setFiles: (NSArray *)path;
- (NSArray *)files;
- (void) setIndex: (int)index;
- (int)index;
- (cairo_font_face_t *)fontFace;

View file

@ -32,21 +32,27 @@
#include <cairo-ft.h>
#include <AppKit/NSFontManager.h>
@ implementation CairoFaceInfo
@implementation CairoFaceInfo
- (id) initWithfamilyName: (NSString *)familyName
- (id) initWithfamilyName: (NSString *)familyName
fullName: (NSString *)fullName
weight: (int)weight
italicAngle: (float)italicAngle
traits: (unsigned int)traits
pattern: (FcPattern *)pattern
files: (NSArray *)paths
index: (int)index
{
_pattern = pattern;
FcPatternReference(_pattern);
[super init];
[self setFamilyName: familyName];
[self setFullName: fullName];
[self setWeight: weight];
[self setItalicAngle: italicAngle];
[self setTraits: traits];
return self;
[self setFiles: paths];
[self setIndex: index];
return self;
}
- (void) dealloc
@ -55,20 +61,38 @@
{
cairo_font_face_destroy(_fontFace);
}
FcPatternDestroy(_pattern);
if (_ftface)
{
FT_Done_Face(_ftface);
}
if (_ftlibrary)
{
FT_Done_FreeType(_ftlibrary);
}
RELEASE(_familyName);
RELEASE(_filePaths);
[super dealloc];
}
- (NSString *)familyName
{
return _familyName;
}
- (void) setFamilyName: (NSString *)name
{
ASSIGN(_familyName, name);
}
- (NSString *)familyName
- (NSString *)fullName
{
return _familyName;
return _fullName;
}
- (void) setFullName: (NSString *)name
{
ASSIGN(_fullName, name);
}
- (int) weight
@ -81,6 +105,16 @@
_weight = weight;
}
- (int) italicAngle
{
return _italicAngle;
}
- (void) setItalicAngle: (float)italicAngle
{
_italicAngle = italicAngle;
}
- (unsigned int) traits
{
return _traits;
@ -96,26 +130,79 @@
return 257;
}
- (void) setFiles: (NSArray *)paths
{
ASSIGN(_filePaths, paths);
}
- (NSArray *)files
{
return _filePaths;
}
- (void) setIndex: (int)index
{
_indexInFile = index;
}
- (int)index
{
return _indexInFile;
}
- (cairo_font_face_t *)fontFace
{
if (!_fontFace)
{
FcResult result;
FcPattern *resolved;
FcConfigSubstitute (NULL, _pattern, FcMatchPattern);
FcDefaultSubstitute(_pattern);
resolved = FcFontMatch(NULL, _pattern, &result);
_fontFace = cairo_ft_font_face_create_for_pattern(resolved);
FcPatternDestroy(resolved);
const char *cPath;
int i;
int count;
/* FIXME: There should only be one FT_Library for all faces. */
if (!_ftlibrary)
{
FT_Init_FreeType(&_ftlibrary);
}
if (! _ftface)
{
count = [_filePaths count];
for (i = 0; i < count; i++)
{
cPath = [[_filePaths objectAtIndex: i] UTF8String];
if (i > 0)
{
if (FT_Attach_File(_ftface, cPath) != 0)
NSLog(@"Could not attach %@ to font face.",
[_filePaths objectAtIndex: i]);
}
else
{
if (FT_New_Face(_ftlibrary, cPath, _indexInFile, &_ftface) != 0)
{
NSLog(@"Creating a font face failed %@", _familyName);
_ftface = NULL;
return NULL;
}
}
}
}
_fontFace =
cairo_ft_font_face_create_for_ft_face(_ftface, FT_LOAD_DEFAULT);
if ((!_fontFace)
|| (cairo_font_face_status(_fontFace) != CAIRO_STATUS_SUCCESS))
{
NSLog(@"Creating a font face failed %@", _familyName);
cairo_font_face_destroy(_fontFace);
FT_Done_Face(_ftface);
FT_Done_FreeType(_ftlibrary);
_fontFace = NULL;
_ftface = NULL;
_ftlibrary = NULL;
return NULL;
}
}

View file

@ -8,6 +8,8 @@
Base on original code of Alex Malmberg
Rewrite: Fred Kiefer <fredkiefer@gmx.de>
Date: Jan 2006
Rewrite: Isaiah Beerbower <public@ipaqah.com>
Date: Dec 2007
This file is part of GNUstep.
@ -46,10 +48,631 @@
#include "cairo/CairoFontEnumerator.h"
#include "cairo/CairoFontInfo.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_TRUETYPE_TABLES_H
#include FT_BDF_H
#include FT_SFNT_NAMES_H
#include FT_TRUETYPE_IDS_H
@implementation CairoFontEnumerator
NSMutableDictionary * __allFonts;
void mergeFontInfo(NSMutableDictionary *fontInfo, NSMutableArray *fontCache)
{
NSString *primaryFile;
int i;
int count = [fontCache count];
primaryFile = [[fontInfo objectForKey: @"Files"] objectAtIndex: 0];
for (i = 0; i < count; i++)
{
NSDictionary *prevFontInfo = [fontCache objectAtIndex: i];
NSArray *files = [prevFontInfo objectForKey: @"Files"];
if (files != nil && [files count] > 0)
{
int f_i;
int f_count = [files count];
for (f_i = 0; f_i < f_count; f_i++)
{
if ([[[files objectAtIndex: f_i] stringByExpandingTildeInPath]
isEqual: primaryFile])
{
[fontInfo addEntriesFromDictionary: prevFontInfo];
[fontCache replaceObjectAtIndex: i withObject: fontInfo];
return;
}
}
}
}
[fontCache addObject: fontInfo];
}
BOOL cacheNFontBundle(NSString *path,
NSMutableArray *fontCache,
BOOL mergeCache)
{
NSFileManager *fm = [NSFileManager defaultManager];
NSString *fontInfoPath =
[path stringByAppendingPathComponent: @"FontInfo.plist"];
NSDictionary *fontInfo;
NSArray *faces;
if (! [fm fileExistsAtPath: fontInfoPath])
return NO;
fontInfo = [NSDictionary dictionaryWithContentsOfFile: fontInfoPath];
if (fontInfo == nil)
return NO;
faces = [fontInfo objectForKey: @"Faces"];
if (faces == nil || [faces isKindOfClass: [NSArray class]] == NO)
return NO;
int i;
int count = [faces count];
for (i = 0; i < count; i++)
{
NSMutableDictionary *face = [faces objectAtIndex: i];
NSMutableArray *files = [face objectForKey: @"Files"];
if (files == nil || [files count] == 0)
continue;
int f_i;
int f_count = [files count];
for (f_i = 0; f_i < f_count; f_i++)
{
NSString *fontFilePath =
[path stringByAppendingPathComponent: [files objectAtIndex: f_i]];
[files replaceObjectAtIndex: f_i withObject: fontFilePath];
}
if ([fontInfo objectForKey: @"Family"] == nil)
{
NSString *familyName =
[[path lastPathComponent] stringByDeletingPathExtension];
[face setObject: familyName forKey: @"Family"];
}
else
{
[face setObject: [fontInfo objectForKey: @"Family"] forKey: @"Family"];
}
if ([fontInfo objectForKey: @"Foundry"] != nil)
{
[face setObject: [fontInfo objectForKey: @"Foundry"] forKey: @"Foundry"];
}
if ([fontInfo objectForKey: @"FontLicense"] != nil)
{
[face setObject: [fontInfo objectForKey: @"FontLicense"]
forKey: @"FontLicense"];
}
if ([fontInfo objectForKey: @"FontCopyright"] != nil)
{
[face setObject: [fontInfo objectForKey: @"FontCopyright"]
forKey: @"FontCopyright"];
}
if (mergeCache)
mergeFontInfo(face, fontCache);
else
[fontCache addObject: face];
}
return YES;
}
void cacheFont(NSString *path,
NSMutableArray *fontCache,
BOOL mergeCache,
FT_Library library)
{
const char *cPath;
int i;
int facesCount;
path = [path stringByExpandingTildeInPath];
cPath = [path UTF8String];
facesCount = 1;
for (i = 0; i < facesCount; ++i)
{
FT_Face face;
PS_FontInfoRec PSInfo;
TT_Postscript *TTPSTable;
TT_OS2 *TTOS2Table;
int weight = 5;
NSFontTraitMask traits = 0;
NSMutableString *style;
NSMutableArray *files;
if (FT_New_Face(library, cPath, 0, &face) == 0)
{
facesCount = face->num_faces;
if (!FT_IS_SCALABLE(face))
{
FT_Done_Face(face);
continue;
}
NSMutableDictionary *faceInfo = [[NSMutableDictionary alloc] init];
const char *cString;
files = [NSMutableArray arrayWithObject: path];
[faceInfo setObject: files forKey: @"Files"];
NSArray *f_extensions = [[NSArray alloc]
initWithObjects: @"pfa", @"PFA", @"pfb", @"PFB", nil];
if ([f_extensions containsObject: [path pathExtension]]
/*FIXME: This would be a better way to check the
font type, but it requires a later version of
FreeType than I currently have installed - ipaqah*/
/*strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0*/)
{
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *extensions = [[NSArray alloc]
initWithObjects: @"afm", @"AFM", @"pfm", @"PFM", nil];
int m_i;
int m_count = [extensions count];
for (m_i = 0; m_i < m_count; ++m_i)
{
NSString *metricsPath;
metricsPath = [[path stringByDeletingPathExtension]
stringByAppendingPathExtension: [extensions objectAtIndex: m_i]];
cString = [metricsPath UTF8String];
if ([fm fileExistsAtPath: metricsPath] == NO)
continue;
if (FT_Attach_File(face, cString) == 0)
{
[files addObject: metricsPath];
}
}
}
[faceInfo setObject: [NSNumber numberWithInt: i]
forKey: @"Index"];
[faceInfo setObject: [NSString stringWithUTF8String: face->family_name]
forKey: @"Family"];
if ((face->style_flags | FT_STYLE_FLAG_ITALIC) == face->style_flags)
traits |= NSItalicFontMask;
if ((face->style_flags | FT_STYLE_FLAG_BOLD) == face->style_flags)
{
traits |= NSBoldFontMask;
weight = 8;
}
if (FT_Get_PS_Font_Info(face, &PSInfo) == 0)
{
[faceInfo setObject: [NSString stringWithUTF8String: PSInfo.full_name]
forKey: @"FullName"];
[faceInfo setObject:
[NSNumber numberWithFloat: (float)(PSInfo.italic_angle)]
forKey: @"ItalicAngle"];
if (PSInfo.is_fixed_pitch)
traits |= NSFixedPitchFontMask;
}
if ((TTOS2Table = FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != 0 &&
TTOS2Table->version != 0xFFFF)
{
[faceInfo setObject:
[NSString stringWithCString: (char *)TTOS2Table->achVendID
length: 4]
forKey: @"Foundry"];
if (TTOS2Table->usWeightClass == 0)
weight = 5;
else
weight = (TTOS2Table->usWeightClass / 100) + 1;
if (TTOS2Table->usWidthClass > 0 && TTOS2Table->usWidthClass < 5)
traits |= NSCondensedFontMask;
else if (TTOS2Table->usWidthClass > 5)
traits |= NSExpandedFontMask;
}
if ((TTPSTable = FT_Get_Sfnt_Table(face, ft_sfnt_post)) != 0)
{
[faceInfo setObject: [NSNumber numberWithFloat:
((float)(TTPSTable->italicAngle) / 65536.0)]
forKey: @"ItalicAngle"];
if (TTPSTable->isFixedPitch)
traits |= NSFixedPitchFontMask;
}
if (face->style_name != NULL)
{
style = [NSString stringWithUTF8String: face->style_name];
}
else
{
style = [[NSMutableString alloc] init];
if ((traits | NSCondensedFontMask) == traits)
{
if ([style length] > 0)
[style appendString: @" "];
[style appendString: @"Condensed"];
}
else if ((traits | NSExpandedFontMask) == traits)
{
if ([style length] > 0)
[style appendString: @" "];
[style appendString: @"Expanded"];
}
if ((traits | NSBoldFontMask) == traits)
{
if ([style length] > 0)
[style appendString: @" "];
[style appendString: @"Bold"];
}
if ((traits | NSItalicFontMask) == traits)
{
if ([style length] > 0)
[style appendString: @" "];
[style appendString: @"Italic"];
}
if (!([style length] > 0))
[style appendString: @"Regular"];
}
[faceInfo setObject: style forKey: @"Name"];
if ((cString = FT_Get_Postscript_Name(face)) != NULL)
[faceInfo setObject: [NSString stringWithUTF8String: cString]
forKey: @"PostScriptName"];
else
[faceInfo setObject: [NSString stringWithFormat: @"%s-%@",
face->family_name,
style]
forKey: @"PostScriptName"];
[faceInfo setObject: [NSNumber numberWithInt: weight]
forKey: @"Weight"];
[faceInfo setObject: [NSNumber numberWithUnsignedLong: traits]
forKey: @"Traits"];
FT_Done_Face(face);
if (mergeCache)
mergeFontInfo(faceInfo, fontCache);
else
[fontCache addObject: faceInfo];
}
}
}
NSDate *bundleModificationDate(NSString *path)
{
NSDate *date;
NSFileManager *fm = [NSFileManager defaultManager];
BOOL isDir;
NSArray *ls = [fm directoryContentsAtPath: path];
int i;
int count = [ls count];
date = [[fm fileAttributesAtPath: path
traverseLink: YES] fileModificationDate];
for (i = 0; i < count; i++)
{
NSString *subPath =
[path stringByAppendingPathComponent: [ls objectAtIndex: i]];
if ([fm fileExistsAtPath: subPath isDirectory: &isDir] && isDir == YES)
{
date = [date laterDate: bundleModificationDate(subPath)];
}
}
return date;
}
void cacheFolder(NSString *path,
NSMutableArray *fontCache,
NSMutableDictionary *cachedDirs,
BOOL mergeCache,
FT_Library library)
{
NSFileManager *fm = [NSFileManager defaultManager];
BOOL isDir;
if (! ([fm fileExistsAtPath: path isDirectory: &isDir] && isDir == YES))
return;
NSDate *dateLastCached;
NSDate *modificationDate;
dateLastCached = [cachedDirs objectForKey: path];
if (dateLastCached == nil)
dateLastCached = [NSDate distantPast];
if (mergeCache)
modificationDate = [[fm fileAttributesAtPath: path
traverseLink: YES] fileModificationDate];
else
modificationDate = [NSDate distantFuture];
int i;
NSArray *ls = [fm directoryContentsAtPath: path];
int count = [ls count];
for (i = 0; i < count; i++)
{
NSString *fontPath =
[path stringByAppendingPathComponent: [ls objectAtIndex: i]];
if ([fm fileExistsAtPath: fontPath isDirectory: &isDir] && isDir == YES)
{
if ([[fontPath pathExtension] isEqual: @"nfont"])
{
if ([dateLastCached earlierDate: bundleModificationDate(fontPath)] ==
dateLastCached)
{
cacheNFontBundle(fontPath, fontCache, mergeCache);
}
}
else
{
cacheFolder(fontPath,
fontCache,
cachedDirs,
mergeCache,
library);
}
}
else if ([dateLastCached earlierDate: modificationDate] ==
dateLastCached)
{
cacheFont(fontPath, fontCache, mergeCache, library);
}
}
[cachedDirs setObject: [NSDate date] forKey: path];
}
- (void) enumerateFontsAndFamilies
{
int i;
NSFileManager *fm = [NSFileManager defaultManager];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSMutableArray *fontCache;
NSMutableDictionary *cachedDirs;
BOOL mergeCache = YES;
/*
* Open font cache:
*/
NSString *cachePath =
[[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask,
YES) objectAtIndex: 0]
stringByAppendingPathComponent: @"FontInfo/FontCache.plist"];
switch ([fm fileExistsAtPath: cachePath])
{
case YES:
if (!(fontCache = [NSMutableArray arrayWithContentsOfFile: cachePath]))
{
NSLog(@"Couldn't open font cache: %@", cachePath);
return;
}
break;
default:
fontCache = [[NSMutableArray alloc] init];
mergeCache = NO;
}
NSString *dirsPath =
[[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask,
YES) objectAtIndex: 0]
stringByAppendingPathComponent: @"FontInfo/CachedDirs.plist"];
switch ([fm fileExistsAtPath: cachePath])
{
case YES:
if ((cachedDirs =
[NSMutableDictionary dictionaryWithContentsOfFile: dirsPath]))
break;
default:
cachedDirs = [[NSMutableDictionary alloc] init];
}
/*
* Make sure all fonts are cached:
*/
NSMutableArray *searchPaths = [[NSMutableArray alloc] initWithArray:
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSAllDomainsMask,
YES)];
int count = [searchPaths count];
for (i = 0; i < count; i++)
{
NSString *path = [[searchPaths objectAtIndex: i]
stringByAppendingPathComponent: @"Fonts"];
[searchPaths replaceObjectAtIndex: i withObject: path];
}
if ([ud objectForKey: @"GSAdditionalFontPaths"] != nil)
[searchPaths addObjectsFromArray:
[ud objectForKey: @"GSAdditionalFontPaths"]];
FT_Library library;
FT_Init_FreeType(&library);
count = [searchPaths count];
for (i = 0; i < count; i++)
{
cacheFolder([searchPaths objectAtIndex: i],
fontCache,
cachedDirs,
mergeCache,
library);
}
FT_Done_FreeType(library);
/*
* Enumerate fonts and families:
*/
NSMutableDictionary *mutableAllFonts = [[NSMutableDictionary alloc] init];
NSMutableArray *mutableAllFontNames = [[NSMutableArray alloc] init];
NSMutableDictionary *mutableAllFontFamilies =
[[NSMutableDictionary alloc] init];
count = [fontCache count];
for (i = 0; i < count; i++)
{
NSDictionary *face = [fontCache objectAtIndex: i];
CairoFaceInfo *faceInfo = [CairoFaceInfo alloc];
NSString *family;
NSString *postScriptName;
NSString *name;
NSString *fullName;
NSArray *files;
int weight;
int index;
NSFontTraitMask traits;
float italicAngle;
if ([face objectForKey: @"Family"] == nil ||
[face objectForKey: @"PostScriptName"] == nil ||
[face objectForKey: @"Name"] == nil ||
[face objectForKey: @"Files"] == nil ||
[[face objectForKey: @"Files"] count] < 1)
continue;
family = [face objectForKey: @"Family"];
postScriptName = [face objectForKey: @"PostScriptName"];
name = [face objectForKey: @"Name"];
files = [face objectForKey: @"Files"];
if ([mutableAllFontNames containsObject: postScriptName])
continue;
else
[mutableAllFontNames addObject: postScriptName];
if ([face objectForKey: @"Index"] == nil)
index = 0;
else
index = [[face objectForKey: @"Index"] intValue];
if ([face objectForKey: @"FullName"] == nil)
fullName = [NSString stringWithFormat: @"%@ %@", family, name];
else
fullName = [face objectForKey: @"FullName"];
if ([face objectForKey: @"Weight"] == nil)
weight = 5;
else
weight = [[face objectForKey: @"Weight"] intValue];
if ([face objectForKey: @"Traits"] == nil)
traits = 0;
else
traits = [[face objectForKey: @"Traits"] unsignedIntValue];
if ([face objectForKey: @"ItalicAngle"] == nil)
italicAngle = 0.0;
else
italicAngle = [[face objectForKey: @"ItalicAngle"] floatValue];
faceInfo = [faceInfo initWithfamilyName: family
fullName: fullName
weight: weight
italicAngle: italicAngle
traits: traits
files: files
index: index];
[mutableAllFonts setObject: faceInfo forKey: postScriptName];
NSArray *familyFace = [[NSArray alloc]
initWithObjects: postScriptName,
name,
[NSNumber numberWithInt: weight],
[NSNumber numberWithUnsignedInt: traits], nil];
NSMutableArray *familyFaceArray =
[mutableAllFontFamilies objectForKey: family];
if (familyFaceArray == nil)
{
familyFaceArray = [[NSMutableArray alloc] init];
[mutableAllFontFamilies setObject: familyFaceArray forKey: family];
}
[familyFaceArray addObject: familyFace];
}
allFontNames = mutableAllFontNames;
allFontFamilies = mutableAllFontFamilies;
__allFonts = mutableAllFonts;
/*
* Write cache back to file:
*/
NSString * fontInfoDir = [cachePath stringByDeletingLastPathComponent];
if (! [fm fileExistsAtPath: fontInfoDir])
{
[fm createDirectoryAtPath: fontInfoDir attributes: nil];
}
if ([fontCache writeToFile: cachePath atomically: YES] == NO)
{
NSLog(@"Couldn't write font cache.");
}
if ([cachedDirs writeToFile: dirsPath atomically: YES] == NO)
{
NSLog(@"Couldn't write cached directory info.");
}
}
+ (CairoFaceInfo *) fontWithName: (NSString *) name
{
CairoFaceInfo *face;
@ -62,149 +685,12 @@ NSMutableDictionary * __allFonts;
return face;
}
// Make a GNUStep style font descriptor from a FcPattern
static NSArray *faFromFc(FcPattern *pat)
{
int weight, slant, spacing, nsweight;
unsigned int nstraits = 0;
char *family;
NSMutableString *name, *style;
if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &weight) != FcResultMatch
|| FcPatternGetInteger(pat, FC_SLANT, 0, &slant) != FcResultMatch
|| FcPatternGetString(pat, FC_FAMILY, 0, (FcChar8 **)&family)
!= FcResultMatch)
return nil;
if (FcPatternGetInteger(pat, FC_SPACING, 0, &spacing) == FcResultMatch)
if (spacing==FC_MONO || spacing==FC_CHARCELL)
nstraits |= NSFixedPitchFontMask;
name = [NSMutableString stringWithCapacity: 100];
style = [NSMutableString stringWithCapacity: 100];
[name appendString: [NSString stringWithUTF8String: family]];
switch (weight)
{
case FC_WEIGHT_LIGHT:
[style appendString: @"Light"];
nsweight = 3;
break;
case FC_WEIGHT_MEDIUM:
nsweight = 6;
break;
case FC_WEIGHT_DEMIBOLD:
[style appendString: @"Demibold"];
nsweight = 7;
break;
case FC_WEIGHT_BOLD:
[style appendString: @"Bold"];
nsweight = 9;
nstraits |= NSBoldFontMask;
break;
case FC_WEIGHT_BLACK:
[style appendString: @"Black"];
nsweight = 12;
nstraits |= NSBoldFontMask;
break;
default:
nsweight = 6;
}
switch (slant)
{
case FC_SLANT_ROMAN:
break;
case FC_SLANT_ITALIC:
[style appendString: @"Italic"];
nstraits |= NSItalicFontMask;
break;
case FC_SLANT_OBLIQUE:
[style appendString: @"Oblique"];
nstraits |= NSItalicFontMask;
break;
}
if ([style length] > 0)
{
[name appendString: @"-"];
[name appendString: style];
}
else
{
[style appendString: @"Roman"];
}
return [NSArray arrayWithObjects: name,
style,
[NSNumber numberWithInt: nsweight],
[NSNumber numberWithUnsignedInt: nstraits],
nil];
}
- (void) enumerateFontsAndFamilies
{
int i;
NSMutableDictionary *fcxft_allFontFamilies = [NSMutableDictionary new];
NSMutableDictionary *fcxft_allFonts = [NSMutableDictionary new];
NSMutableArray *fcxft_allFontNames = [NSMutableArray new];
FcPattern *pat = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT, NULL);
FcFontSet *fs = FcFontList(NULL, pat, os);
FcPatternDestroy(pat);
FcObjectSetDestroy(os);
for (i = 0; i < fs->nfont; i++)
{
char *family;
if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, (FcChar8 **)&family)
== FcResultMatch)
{
NSArray *fontArray;
if ((fontArray = faFromFc(fs->fonts[i])))
{
NSString *familyString;
NSMutableArray *familyArray;
CairoFaceInfo *aFont;
NSString *name = [fontArray objectAtIndex: 0];
familyString = [NSString stringWithUTF8String: family];
familyArray = [fcxft_allFontFamilies objectForKey: familyString];
if (familyArray == nil)
{
NSDebugLog(@"Found font family %@", familyString);
familyArray = [[NSMutableArray alloc] init];
[fcxft_allFontFamilies setObject: familyArray
forKey: familyString];
RELEASE(familyArray);
}
NSDebugLog(@"fc enumerator: adding font: %@", name);
[familyArray addObject: fontArray];
[fcxft_allFontNames addObject: name];
aFont = [[CairoFaceInfo alloc] initWithfamilyName: familyString
weight: [[fontArray objectAtIndex: 2] intValue]
traits: [[fontArray objectAtIndex: 3] unsignedIntValue]
pattern: fs->fonts[i]];
[fcxft_allFonts setObject: aFont forKey: name];
RELEASE(aFont);
}
}
}
FcFontSetDestroy (fs);
allFontNames = fcxft_allFontNames;
allFontFamilies = fcxft_allFontFamilies;
__allFonts = fcxft_allFonts;
}
- (NSString *) defaultSystemFontName
{
if ([allFontNames containsObject: @"Bitstream Vera Sans"])
return @"Bitstream Vera Sans";
if ([allFontNames containsObject: @"BitstreamVeraSans-Roman"])
return @"BitstreamVeraSans-Roman";
if ([allFontNames containsObject: @"FreeSans"])
return @"FreeSans";
return @"Helvetica";
@ -214,6 +700,8 @@ static NSArray *faFromFc(FcPattern *pat)
{
if ([allFontNames containsObject: @"Bitstream Vera Sans-Bold"])
return @"Bitstream Vera Sans-Bold";
if ([allFontNames containsObject: @"BitstreamVeraSans-Bold"])
return @"BitstreamVeraSans-Bold";
if ([allFontNames containsObject: @"FreeSans-Bold"])
return @"FreeSans-Bold";
return @"Helvetica-Bold";
@ -223,6 +711,8 @@ static NSArray *faFromFc(FcPattern *pat)
{
if ([allFontNames containsObject: @"Bitstream Vera Sans Mono"])
return @"Bitstream Vera Sans Mono";
if ([allFontNames containsObject: @"BitstreamVeraSansMono-Roman"])
return @"BitstreamVeraSansMono-Roman";
if ([allFontNames containsObject: @"FreeMono"])
return @"FreeMono";
return @"Courier";

View file

@ -75,13 +75,18 @@
[self setCacheSize: [_faceInfo cacheSize]];
/* setting GSFontInfo:
* weight, traits, familyName,
* weight, italicAngle, traits, familyName, fullName
* mostCompatibleStringEncoding, encodingScheme,
*/
weight = [_faceInfo weight];
italicAngle = [_faceInfo italicAngle];
traits = [_faceInfo traits];
familyName = [[_faceInfo familyName] copy];
/* FIXME: GSFontInfo doesn't have full name yet.
* NSfont also needs to be changed.
* fullName = [[_faceInfo fullName] copy];
*/
mostCompatibleStringEncoding = NSUTF8StringEncoding;
encodingScheme = @"iso10646-1";