mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 07:21:02 +00:00
back/cairo: use Fontconfig for descriptor matching
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@32864 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a86d338afc
commit
b1b61ab926
3 changed files with 576 additions and 0 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2011-04-14 Eric Wasylishen <ewasylishen@gmail.com>
|
||||
|
||||
* Source/cairo/CairoFontEnumerator.m:
|
||||
* Headers/cairo/CairoFontEnumerator.h: Override
|
||||
-matchingFontDescriptorsFor: to delegate the matching to Fontconfig
|
||||
|
||||
This uses two utility classes which map Fontconfig patterns
|
||||
to and from NSFontDescriptor attributes dictionaries, preserving
|
||||
as much detail as possible.
|
||||
|
||||
2011-04-14 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Version: Bump version
|
||||
|
|
|
@ -37,6 +37,22 @@
|
|||
+ (CairoFaceInfo *) fontWithName: (NSString *)name;
|
||||
@end
|
||||
|
||||
@interface FontconfigPatternGenerator : NSObject
|
||||
{
|
||||
NSDictionary *_attributes;
|
||||
FcPattern *_pat;
|
||||
}
|
||||
- (FcPattern *)createPatternWithAttributes: (NSDictionary *)attributes;
|
||||
@end
|
||||
|
||||
@interface FontconfigPatternParser : NSObject
|
||||
{
|
||||
NSMutableDictionary *_attributes;
|
||||
FcPattern *_pat;
|
||||
}
|
||||
- (NSDictionary*)attributesFromPattern: (FcPattern *)pat;
|
||||
@end
|
||||
|
||||
@interface FontconfigCharacterSet : NSCharacterSet
|
||||
{
|
||||
FcCharSet *_charset;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <GNUstepGUI/GSFontInfo.h>
|
||||
#include <AppKit/NSAffineTransform.h>
|
||||
#include <AppKit/NSBezierPath.h>
|
||||
#include <AppKit/NSFontDescriptor.h>
|
||||
|
||||
#include "gsc/GSGState.h"
|
||||
#include "cairo/CairoFontEnumerator.h"
|
||||
|
@ -235,8 +236,556 @@ static NSArray *faFromFc(FcPattern *pat)
|
|||
return @"Courier";
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the implementation in GSFontInfo, and delegates the
|
||||
* matching to Fontconfig.
|
||||
*/
|
||||
- (NSArray *) matchingFontDescriptorsFor: (NSDictionary *)attributes
|
||||
{
|
||||
NSMutableArray *descriptors;
|
||||
FcResult result;
|
||||
FcPattern *matchedpat, *pat;
|
||||
FontconfigPatternGenerator *generator;
|
||||
|
||||
descriptors = [NSMutableArray array];
|
||||
|
||||
generator = [[FontconfigPatternGenerator alloc] init];
|
||||
pat = [generator createPatternWithAttributes: attributes];
|
||||
DESTROY(generator);
|
||||
|
||||
FcConfigSubstitute(NULL, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
result = FcResultMatch;
|
||||
matchedpat = FcFontMatch(NULL, pat, &result);
|
||||
if (result != FcResultMatch)
|
||||
{
|
||||
NSLog(@"Warning, FcFontMatch failed with code: %d", result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FcResultMatch;
|
||||
FcFontSet *fontSet = FcFontSort(NULL, matchedpat, FcFalse, NULL, &result);
|
||||
if (result == FcResultMatch)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<fontSet->nfont; i++)
|
||||
{
|
||||
FontconfigPatternParser *parser = [[FontconfigPatternParser alloc] init];
|
||||
// FIXME: do we need to match this pattern?
|
||||
FcPattern *matchingpat = fontSet->fonts[i];
|
||||
NSDictionary *attribs = [parser attributesFromPattern: matchingpat];
|
||||
[parser release];
|
||||
|
||||
[descriptors addObject: [NSFontDescriptor fontDescriptorWithFontAttributes: attribs]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"ERROR! FcFontSort failed");
|
||||
}
|
||||
|
||||
FcFontSetDestroy(fontSet);
|
||||
FcPatternDestroy(matchedpat);
|
||||
}
|
||||
|
||||
FcPatternDestroy(pat);
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation FontconfigPatternGenerator
|
||||
|
||||
- (void)addName: (NSString*)name
|
||||
{
|
||||
// FIXME: Fontconfig ignores PostScript names of fonts; we need
|
||||
// https://bugs.freedesktop.org/show_bug.cgi?id=18095 fixed.
|
||||
|
||||
// This is a heuristic to try to 'parse' a PostScript font name,
|
||||
// however, since they are just unique identifiers for fonts and
|
||||
// don't need to follow any naming convention, this may fail
|
||||
|
||||
NSRange dash = [name rangeOfString: @"-"];
|
||||
if (dash.location == NSNotFound)
|
||||
{
|
||||
FcPatternAddString(_pat, FC_FAMILY, (const FcChar8 *)[name UTF8String]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *weightAndSlant = [name substringFromIndex: dash.location + 1];
|
||||
NSString *family = [name substringToIndex: dash.location];
|
||||
|
||||
FcPatternAddString(_pat, FC_FAMILY, (const FcChar8 *)[family UTF8String]);
|
||||
|
||||
if (NSNotFound != [weightAndSlant rangeOfString: @"Light"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_LIGHT);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Medium"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_MEDIUM);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Demibold"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_DEMIBOLD);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Bold"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_BOLD);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Black"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_BLACK);
|
||||
}
|
||||
|
||||
if (NSNotFound != [weightAndSlant rangeOfString: @"Italic"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_SLANT, FC_SLANT_ITALIC);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Oblique"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_SLANT, FC_SLANT_OBLIQUE);
|
||||
}
|
||||
|
||||
if (NSNotFound != [weightAndSlant rangeOfString: @"Condensed"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_CONDENSED);
|
||||
}
|
||||
else if (NSNotFound != [weightAndSlant rangeOfString: @"Expanded"].location)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_EXPANDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addVisibleName: (NSString*)name
|
||||
{
|
||||
FcPatternAddString(_pat, FC_FULLNAME, (const FcChar8 *)[name UTF8String]);
|
||||
}
|
||||
|
||||
- (void)addFamilyName: (NSString*)name
|
||||
{
|
||||
FcPatternAddString(_pat, FC_FAMILY, (const FcChar8 *)[name UTF8String]);
|
||||
}
|
||||
|
||||
- (void)addStyleName: (NSString*)style
|
||||
{
|
||||
FcPatternAddString(_pat, FC_STYLE, (const FcChar8 *)[style UTF8String]);
|
||||
}
|
||||
|
||||
- (void)addTraits: (NSDictionary*)traits
|
||||
{
|
||||
if ([traits objectForKey: NSFontSymbolicTrait])
|
||||
{
|
||||
NSFontSymbolicTraits symTraits = [[traits objectForKey: NSFontSymbolicTrait] intValue];
|
||||
|
||||
if (symTraits & NSFontItalicTrait)
|
||||
{
|
||||
// NOTE: May be overridden by NSFontSlantTrait
|
||||
FcPatternAddInteger(_pat, FC_SLANT, FC_SLANT_ITALIC);
|
||||
}
|
||||
if (symTraits & NSFontBoldTrait)
|
||||
{
|
||||
// NOTE: May be overridden by NSFontWeightTrait
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, FC_WEIGHT_BOLD);
|
||||
}
|
||||
if (symTraits & NSFontExpandedTrait)
|
||||
{
|
||||
// NOTE: May be overridden by NSFontWidthTrait
|
||||
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_EXPANDED);
|
||||
}
|
||||
if (symTraits & NSFontCondensedTrait)
|
||||
{
|
||||
// NOTE: May be overridden by NSFontWidthTrait
|
||||
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_CONDENSED);
|
||||
}
|
||||
if (symTraits & NSFontMonoSpaceTrait)
|
||||
{
|
||||
// If you run "fc-match :spacing=100", you get "DejaVu Sans" even though you would
|
||||
// expect to get "DejaVu Sans Mono". So, we also add "monospace" as a weak family
|
||||
// name to fix the problem.
|
||||
FcPatternAddInteger(_pat, FC_SPACING, FC_MONO);
|
||||
|
||||
FcValue value;
|
||||
value.type = FcTypeString;
|
||||
value.u.s = (FcChar8*)"monospace";
|
||||
FcPatternAddWeak(_pat, FC_FAMILY, value, FcTrue);
|
||||
}
|
||||
if (symTraits & NSFontVerticalTrait)
|
||||
{
|
||||
// FIXME: What is this supposed to mean?
|
||||
}
|
||||
if (symTraits & NSFontUIOptimizedTrait)
|
||||
{
|
||||
// NOTE: Fontconfig can't express this
|
||||
}
|
||||
|
||||
NSFontFamilyClass class = symTraits & NSFontFamilyClassMask;
|
||||
char *addWeakFamilyName = NULL;
|
||||
switch (class)
|
||||
{
|
||||
default:
|
||||
case NSFontUnknownClass:
|
||||
case NSFontOrnamentalsClass:
|
||||
case NSFontScriptsClass:
|
||||
case NSFontSymbolicClass:
|
||||
// FIXME: Is there some way to convey these to Fontconfig?
|
||||
break;
|
||||
case NSFontOldStyleSerifsClass:
|
||||
case NSFontTransitionalSerifsClass:
|
||||
case NSFontModernSerifsClass:
|
||||
case NSFontClarendonSerifsClass:
|
||||
case NSFontSlabSerifsClass:
|
||||
case NSFontFreeformSerifsClass:
|
||||
addWeakFamilyName = "serif";
|
||||
break;
|
||||
case NSFontSansSerifClass:
|
||||
addWeakFamilyName = "sans";
|
||||
break;
|
||||
}
|
||||
if (addWeakFamilyName)
|
||||
{
|
||||
FcValue value;
|
||||
value.type = FcTypeString;
|
||||
value.u.s = (const FcChar8 *)addWeakFamilyName;
|
||||
FcPatternAddWeak(_pat, FC_FAMILY, value, FcTrue);
|
||||
}
|
||||
}
|
||||
|
||||
if ([traits objectForKey: NSFontWeightTrait])
|
||||
{
|
||||
/**
|
||||
* Scale: -1 is thinnest, 0 is normal, 1 is heaviest
|
||||
*/
|
||||
double weight = [[traits objectForKey: NSFontWeightTrait] doubleValue];
|
||||
weight = MAX(-1, MIN(1, weight));
|
||||
int fcWeight;
|
||||
if (weight <= 0)
|
||||
{
|
||||
fcWeight = FC_WEIGHT_THIN + ((weight + 1.0) * (FC_WEIGHT_NORMAL - FC_WEIGHT_THIN));
|
||||
}
|
||||
else
|
||||
{
|
||||
fcWeight = FC_WEIGHT_NORMAL + (weight * (FC_WEIGHT_ULTRABLACK - FC_WEIGHT_NORMAL));
|
||||
}
|
||||
FcPatternAddInteger(_pat, FC_WEIGHT, fcWeight);
|
||||
}
|
||||
|
||||
if ([traits objectForKey: NSFontWidthTrait])
|
||||
{
|
||||
/**
|
||||
* Scale: -1 is most condensed, 0 is normal, 1 is most spread apart
|
||||
*/
|
||||
double width = [[traits objectForKey: NSFontWidthTrait] doubleValue];
|
||||
width = MAX(-1, MIN(1, width));
|
||||
int fcWidth;
|
||||
if (width <= 0)
|
||||
{
|
||||
fcWidth = FC_WIDTH_ULTRACONDENSED + ((width + 1.0) * (FC_WIDTH_NORMAL - FC_WIDTH_ULTRACONDENSED));
|
||||
}
|
||||
else
|
||||
{
|
||||
fcWidth = FC_WIDTH_NORMAL + (width * (FC_WIDTH_ULTRAEXPANDED - FC_WIDTH_NORMAL));
|
||||
}
|
||||
FcPatternAddInteger(_pat, FC_WIDTH, fcWidth);
|
||||
}
|
||||
|
||||
if ([traits objectForKey: NSFontSlantTrait])
|
||||
{
|
||||
/**
|
||||
* Scale: -1 is 30 degree counterclockwise slant, 0 is no slant, 1
|
||||
* is 30 degree clockwise slant
|
||||
*/
|
||||
double slant = [[traits objectForKey: NSFontSlantTrait] doubleValue];
|
||||
|
||||
// NOTE: Fontconfig can't express this as a scale
|
||||
if (slant > 0)
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_SLANT, FC_SLANT_ITALIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
FcPatternAddInteger(_pat, FC_SLANT, FC_SLANT_ROMAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addSize: (NSNumber*)size
|
||||
{
|
||||
FcPatternAddDouble(_pat, FC_SIZE, [size doubleValue]);
|
||||
}
|
||||
|
||||
- (void)addCharacterSet: (NSCharacterSet*)characterSet
|
||||
{
|
||||
if ([characterSet isKindOfClass: [FontconfigCharacterSet class]])
|
||||
{
|
||||
// Fast case
|
||||
FcPatternAddCharSet(_pat, FC_CHARSET, [(FontconfigCharacterSet*)characterSet fontconfigCharSet]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slow case
|
||||
FcCharSet *fcSet = FcCharSetCreate();
|
||||
uint32_t plane;
|
||||
for (plane=0; plane<=16; plane++)
|
||||
{
|
||||
if ([characterSet hasMemberInPlane: plane])
|
||||
{
|
||||
uint32_t codePoint;
|
||||
for (codePoint = plane<<16; codePoint <= 0xffff + (plane<<16); codePoint++)
|
||||
{
|
||||
if ([characterSet longCharacterIsMember: codePoint])
|
||||
{
|
||||
FcCharSetAddChar(fcSet, codePoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FcPatternAddCharSet(_pat, FC_CHARSET, fcSet);
|
||||
FcCharSetDestroy(fcSet);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleKey: (NSString*)key selector: (SEL)selector valueClass: (Class)valueClass
|
||||
{
|
||||
id value = [_attributes objectForKey: key];
|
||||
if (value)
|
||||
{
|
||||
if ([value isKindOfClass: valueClass])
|
||||
{
|
||||
if ([self respondsToSelector: selector])
|
||||
{
|
||||
[self performSelector: selector withObject: value];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"NSFontDescriptor: Ignoring invalid value %@ for attribute %@", value, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addAttributes
|
||||
{
|
||||
[self handleKey: NSFontNameAttribute selector: @selector(addName:) valueClass: [NSString class]];
|
||||
[self handleKey: NSFontVisibleNameAttribute selector: @selector(addVisibleName:) valueClass: [NSString class]];
|
||||
[self handleKey: NSFontFamilyAttribute selector: @selector(addFamilyName:) valueClass: [NSString class]];
|
||||
[self handleKey: NSFontFaceAttribute selector: @selector(addStyleName:) valueClass: [NSString class]];
|
||||
[self handleKey: NSFontTraitsAttribute selector: @selector(addTraits:) valueClass: [NSDictionary class]];
|
||||
[self handleKey: NSFontSizeAttribute selector: @selector(addSize:) valueClass: [NSNumber class]];
|
||||
[self handleKey: NSFontCharacterSetAttribute selector: @selector(addCharacterSet:) valueClass: [NSCharacterSet class]];
|
||||
}
|
||||
|
||||
- (FcPattern *)createPatternWithAttributes: (NSDictionary *)attributes
|
||||
{
|
||||
_attributes = attributes;
|
||||
_pat = FcPatternCreate();
|
||||
[self addAttributes];
|
||||
|
||||
return _pat;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation FontconfigPatternParser
|
||||
|
||||
- (NSString*)readFontconfigString: (const char *)key fromPattern: (FcPattern*)pat
|
||||
{
|
||||
unsigned char *string = NULL;
|
||||
if (FcResultMatch == FcPatternGetString(pat, key, 0, &string))
|
||||
{
|
||||
if (string)
|
||||
{
|
||||
return [NSString stringWithUTF8String: (const char *)string];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSNumber*)readFontconfigInteger: (const char *)key fromPattern: (FcPattern*)pat
|
||||
{
|
||||
int value;
|
||||
if (FcResultMatch == FcPatternGetInteger(pat, key, 0, &value))
|
||||
{
|
||||
return [NSNumber numberWithInt: value];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSNumber*)readFontconfigDouble: (const char *)key fromPattern: (FcPattern*)pat
|
||||
{
|
||||
double value;
|
||||
if (FcResultMatch == FcPatternGetDouble(pat, key, 0, &value))
|
||||
{
|
||||
return [NSNumber numberWithDouble: value];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (NSString*)readNameFromPattern: (FcPattern*)pat
|
||||
{
|
||||
// FIXME: Hack which generates a PostScript-style name from the
|
||||
// family name and style
|
||||
|
||||
NSString *family = [self readFontconfigString: FC_FAMILY fromPattern: pat];
|
||||
NSString *style = [self readFontconfigString: FC_STYLE fromPattern: pat];
|
||||
if (style)
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@-%@", family, style];
|
||||
}
|
||||
else
|
||||
{
|
||||
return family;
|
||||
}
|
||||
}
|
||||
- (NSString*)readVisibleNameFromPattern: (FcPattern*)pat
|
||||
{
|
||||
// FIXME: try to get the localized one
|
||||
return [self readFontconfigString: FC_FULLNAME fromPattern: pat];
|
||||
}
|
||||
- (NSString*)readFamilyNameFromPattern: (FcPattern*)pat
|
||||
{
|
||||
// FIXME: try to get the localized one
|
||||
return [self readFontconfigString: FC_FAMILY fromPattern: pat];
|
||||
}
|
||||
- (NSString*)readStyleNameFromPattern: (FcPattern*)pat
|
||||
{
|
||||
// FIXME: try to get the localized one
|
||||
return [self readFontconfigString: FC_STYLE fromPattern: pat];
|
||||
}
|
||||
- (NSDictionary*)readTraitsFromPattern: (FcPattern*)pat
|
||||
{
|
||||
NSMutableDictionary *traits = [NSMutableDictionary dictionary];
|
||||
|
||||
NSFontSymbolicTraits symTraits = 0;
|
||||
|
||||
int value;
|
||||
if (FcResultMatch == FcPatternGetInteger(pat, FC_SLANT, 0, &value))
|
||||
{
|
||||
if (value == FC_SLANT_ITALIC)
|
||||
{
|
||||
symTraits |= NSFontItalicTrait;
|
||||
}
|
||||
}
|
||||
if (FcResultMatch == FcPatternGetInteger(pat, FC_WEIGHT, 0, &value))
|
||||
{
|
||||
if (value >= FC_WEIGHT_BOLD)
|
||||
{
|
||||
symTraits |= NSFontBoldTrait;
|
||||
}
|
||||
|
||||
double weight;
|
||||
if (value <= FC_WEIGHT_NORMAL)
|
||||
{
|
||||
weight = ((value - FC_WEIGHT_THIN) / (double)(FC_WEIGHT_NORMAL - FC_WEIGHT_THIN)) - 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = (value - FC_WEIGHT_NORMAL) / (double)(FC_WEIGHT_ULTRABLACK - FC_WEIGHT_NORMAL);
|
||||
}
|
||||
|
||||
[traits setObject: [NSNumber numberWithDouble: weight]
|
||||
forKey: NSFontWeightTrait];
|
||||
}
|
||||
if (FcResultMatch == FcPatternGetInteger(pat, FC_WIDTH, 0, &value))
|
||||
{
|
||||
if (value >= FC_WIDTH_EXPANDED)
|
||||
{
|
||||
symTraits |= NSFontExpandedTrait;
|
||||
}
|
||||
if (value <= FC_WIDTH_CONDENSED)
|
||||
{
|
||||
symTraits |= NSFontCondensedTrait;
|
||||
}
|
||||
|
||||
double width;
|
||||
if (value <= FC_WIDTH_NORMAL)
|
||||
{
|
||||
width = ((value - FC_WIDTH_ULTRACONDENSED) / (double)(FC_WIDTH_NORMAL - FC_WIDTH_ULTRACONDENSED)) - 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = (value - FC_WIDTH_NORMAL) / (double)(FC_WIDTH_ULTRAEXPANDED - FC_WIDTH_NORMAL);
|
||||
}
|
||||
|
||||
[traits setObject: [NSNumber numberWithDouble: width]
|
||||
forKey: NSFontWidthTrait];
|
||||
}
|
||||
if (FcResultMatch == FcPatternGetInteger(pat, FC_SPACING, 0, &value))
|
||||
{
|
||||
if (value == FC_MONO || value == FC_CHARCELL)
|
||||
{
|
||||
symTraits |= NSFontMonoSpaceTrait;
|
||||
}
|
||||
}
|
||||
|
||||
if (symTraits != 0)
|
||||
{
|
||||
[traits setObject: [NSNumber numberWithUnsignedInt: symTraits]
|
||||
forKey: NSFontSymbolicTrait];
|
||||
}
|
||||
|
||||
return traits;
|
||||
}
|
||||
|
||||
- (NSNumber*)readSizeFromPattern: (FcPattern*)pat
|
||||
{
|
||||
return [self readFontconfigDouble: FC_SIZE fromPattern: pat];
|
||||
}
|
||||
|
||||
- (NSCharacterSet*)readCharacterSetFromPattern: (FcPattern*)pat
|
||||
{
|
||||
FcCharSet *value;
|
||||
if (FcResultMatch == FcPatternGetCharSet(pat, FC_CHARSET, 0, &value))
|
||||
{
|
||||
return [[[FontconfigCharacterSet alloc] initWithFontconfigCharSet: value] autorelease];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)handleKey: (NSString*)key selector: (SEL)sel
|
||||
{
|
||||
if ([self respondsToSelector: sel])
|
||||
{
|
||||
id (*readMethod)(id, SEL, FcPattern*) = (id (*)(id, SEL, FcPattern*))[self methodForSelector: sel];
|
||||
id result = readMethod(self, sel, _pat);
|
||||
if (result != nil)
|
||||
{
|
||||
[_attributes setObject: result
|
||||
forKey: key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)parseAttributes
|
||||
{
|
||||
[self handleKey: NSFontNameAttribute selector: @selector(readNameFromPattern:)];
|
||||
[self handleKey: NSFontVisibleNameAttribute selector: @selector(readVisibleNameFromPattern:)];
|
||||
[self handleKey: NSFontFamilyAttribute selector: @selector(readFamilyNameFromPattern:)];
|
||||
[self handleKey: NSFontFaceAttribute selector: @selector(readStyleNameFromPattern:)];
|
||||
[self handleKey: NSFontTraitsAttribute selector: @selector(readTraitsFromPattern:)];
|
||||
[self handleKey: NSFontSizeAttribute selector: @selector(readSizeFromPattern:)];
|
||||
[self handleKey: NSFontCharacterSetAttribute selector: @selector(readCharacterSetFromPattern:)];
|
||||
}
|
||||
|
||||
- (NSDictionary*)attributesFromPattern: (FcPattern *)pat
|
||||
{
|
||||
_attributes = [NSMutableDictionary dictionary];
|
||||
_pat = pat;
|
||||
[self parseAttributes];
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation FontconfigCharacterSet
|
||||
|
||||
- (id)initWithFontconfigCharSet: (FcCharSet*)charset
|
||||
|
@ -281,3 +830,4 @@ static NSArray *faFromFc(FcPattern *pat)
|
|||
//}
|
||||
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in a new issue