In preparation for reusing this code in the Opal backend, moved fontconfig code to a dedicated set of classes that are now superclasses of Cairo backend's font classes.

Fixed a bug in CairoGState: a NSDebugMLLog() had this obvious mistake in its format (as was printed out by the compiler): @"%self"



git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37066 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
ivucica 2013-09-10 21:07:03 +00:00
parent 31ff3e1ba1
commit 5dd127aec9
15 changed files with 1459 additions and 1058 deletions

View file

@ -1,7 +1,40 @@
2013-09-10 Ivan Vucica <ivan@vucica.net>
* Source/fontconfig/FCFontInfo.m:
* Source/fontconfig/FCFontEnumerator.m:
* Source/fontconfig/FCFaceInfo.m:
* Headers/fontconfig/FCFontInfo.h:
* Headers/fontconfig/FCFontEnumerator.h:
* Headers/fontconfig/FCFaceInfo.h:
* Source/cairo/CairoFontEnumerator.m:
* Source/cairo/CairoFaceInfo.m:
* Source/cairo/CairoFontInfo.m:
* Headers/cairo/CairoFontInfo.h:
* Headers/cairo/CairoFontEnumerator.h:
* Headers/cairo/CairoFaceInfo.h:
In preparation for reusing this code in the Opal backend,
moved fontconfig code to a dedicated set of classes that are now
superclasses of Cairo backend's font classes.
* Source/cairo/GNUmakefile:
Added fontconfig font classes directly to GNUmakefile for Cairo
backend.
It would be better if these had something like their own distinct
GNUmakefile that produces a static library which would then be
linked into Cairo. But the only backends that will use this are,
for now, Cairo and Opal. So the ugliness and extra maintenance
in case more classes are added should be, for now, acceptable.
* Source/cairo/CairoGState.m:
Fixed a mistake in a NSDebugMLLog() call's format. A percentage
symbol was placed before word "self", resulting in compiler's
interpretation as "%s".
2013-09-10 Eric Wasylishen <ewasylishen@gmail.com>
* Source/x11/XIMInputServer.m: If the requested XIM style
(the GSXIMInputMethodStyle user default) is not available,
* Source/x11/XIMInputServer.m: If the requested XIM
style (the GSXIMInputMethodStyle user default) is not available,
fall back to using a stlye that both the X server and
GNUstep support, if any. Also, add support for NoneStyle, which
is for simple input methods that don't have any visualization.

View file

@ -31,44 +31,17 @@
#ifndef CAIROFACEINFO_H
#define CAIROFACEINFO_H
#include <Foundation/Foundation.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "fontconfig/FCFaceInfo.h"
#define id cairo_id
#include <cairo-ft.h>
#undef id
@interface CairoFaceInfo : NSObject
@interface CairoFaceInfo : FCFaceInfo
{
int _weight;
unsigned int _traits;
cairo_font_face_t *_fontFace;
FcPattern *_pattern;
NSString *_familyName;
NSCharacterSet *_characterSet;
BOOL _hasNoCharacterSet;
}
- (id) initWithfamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits
pattern: (FcPattern *)pattern;
- (unsigned int) cacheSize;
- (int) weight;
- (void) setWeight: (int)weight;
- (unsigned int) traits;
- (void) setTraits: (unsigned int)traits;
- (NSString *) familyName;
- (void) setFamilyName: (NSString *)name;
- (cairo_font_face_t *)fontFace;
- (NSCharacterSet*)characterSet;
- (void *)fontFace;
@end
#endif

View file

@ -28,41 +28,16 @@
#ifndef CairoFontEnumerator_h
#define CairoFontEnumerator_h
#include <GNUstepGUI/GSFontInfo.h>
#include "fontconfig/FCFontEnumerator.h"
#include <cairo.h>
#define id fontconfig_id
#include <fontconfig/fontconfig.h>
#undef id
#include "cairo/CairoFaceInfo.h"
@interface CairoFontEnumerator : GSFontEnumerator
@class CairoFaceInfo;
@interface CairoFontEnumerator : FCFontEnumerator
{
}
+ (Class) faceInfoClass;
+ (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;
}
- (id)initWithFontconfigCharSet: (FcCharSet*)charset;
- (FcCharSet*)fontconfigCharSet;
@end
#endif

View file

@ -28,24 +28,16 @@
#ifndef CairoFontInfo_h
#define CairoFontInfo_h
#include <GNUstepGUI/GSFontInfo.h>
#include "fontconfig/FCFontInfo.h"
#include "cairo/CairoFaceInfo.h"
#include <cairo.h>
@interface CairoFontInfo : GSFontInfo
@interface CairoFontInfo : FCFontInfo
{
@public
cairo_scaled_font_t *_scaled;
CairoFaceInfo *_faceInfo;
BOOL _screenFont;
CGFloat lineHeight;
unsigned int _cacheSize;
unsigned int *_cachedGlyphs;
NSSize *_cachedSizes;
}
- (void) setCacheSize:(unsigned int)size;
- (void) drawGlyphs: (const NSGlyph*)glyphs
length: (int)length
on: (cairo_t*)ct;

View file

@ -0,0 +1,72 @@
/*
FCFaceInfo.h
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
Base on code by Alexander Malmberg <alexander@malmberg.org>
Rewrite: Fred Kiefer <fredkiefer@gmx.de>
Date: Jan 2006
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef FCFACEINFO_H
#define FCFACEINFO_H
#include <Foundation/Foundation.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <fontconfig/fontconfig.h>
@interface FCFaceInfo : NSObject
{
int _weight;
unsigned int _traits;
FcPattern *_pattern;
NSString *_familyName;
NSCharacterSet *_characterSet;
BOOL _hasNoCharacterSet;
}
- (id) initWithfamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits
pattern: (FcPattern *)pattern;
- (unsigned int) cacheSize;
- (int) weight;
- (void) setWeight: (int)weight;
- (unsigned int) traits;
- (void) setTraits: (unsigned int)traits;
- (NSString *) familyName;
- (void) setFamilyName: (NSString *)name;
- (void *) fontFace;
- (FcPattern *) matchedPattern;
- (NSCharacterSet*)characterSet;
@end
#endif

View file

@ -0,0 +1,70 @@
/*
FCFontEnumerator.h
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef FCFontEnumerator_h
#define FCFontEnumerator_h
#include <GNUstepGUI/GSFontInfo.h>
#define id fontconfig_id
#include <fontconfig/fontconfig.h>
#undef id
#include "fontconfig/FCFaceInfo.h"
@interface FCFontEnumerator : GSFontEnumerator
{
}
+ (Class) faceInfoClass;
+ (FCFaceInfo *) 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;
}
- (id)initWithFontconfigCharSet: (FcCharSet*)charset;
- (FcCharSet*)fontconfigCharSet;
@end
#endif

View file

@ -0,0 +1,51 @@
/*
FCFontInfo.h
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef FCFontInfo_h
#define FCFontInfo_h
#include <GNUstepGUI/GSFontInfo.h>
#include "fontconfig/FCFaceInfo.h"
#include <cairo.h>
@interface FCFontInfo : GSFontInfo
{
@public
FCFaceInfo *_faceInfo;
BOOL _screenFont;
CGFloat lineHeight;
unsigned int _cacheSize;
unsigned int *_cachedGlyphs;
NSSize *_cachedSizes;
}
- (void) setCacheSize:(unsigned int)size;
- (BOOL) setupAttributes;
@end
#endif

View file

@ -29,84 +29,26 @@
*/
#include "cairo/CairoFaceInfo.h"
#include "cairo/CairoFontEnumerator.h"
#include <cairo-ft.h>
#include <AppKit/NSFontManager.h>
@implementation CairoFaceInfo
- (id) initWithfamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits
pattern: (FcPattern *)pattern
{
_pattern = pattern;
FcPatternReference(_pattern);
[self setFamilyName: familyName];
[self setWeight: weight];
[self setTraits: traits];
return self;
}
- (void) dealloc
{
if (_fontFace)
{
cairo_font_face_destroy(_fontFace);
}
FcPatternDestroy(_pattern);
RELEASE(_familyName);
RELEASE(_characterSet);
[super dealloc];
}
- (void) setFamilyName: (NSString *)name
{
ASSIGN(_familyName, name);
}
- (NSString *)familyName
{
return _familyName;
}
- (int) weight
{
return _weight;
}
- (void) setWeight: (int)weight
{
_weight = weight;
}
- (unsigned int) traits
{
return _traits;
}
- (void) setTraits: (unsigned int)traits
{
_traits = traits;
}
- (unsigned int) cacheSize
{
return 257;
}
- (cairo_font_face_t *)fontFace
- (void *)fontFace
{
if (!_fontFace)
{
FcResult result;
FcPattern *resolved;
FcConfigSubstitute(NULL, _pattern, FcMatchPattern);
FcDefaultSubstitute(_pattern);
resolved = FcFontMatch(NULL, _pattern, &result);
resolved = [self matchedPattern];
_fontFace = cairo_ft_font_face_create_for_pattern(resolved);
FcPatternDestroy(resolved);
@ -123,32 +65,4 @@
return _fontFace;
}
- (NSCharacterSet*)characterSet
{
if (_characterSet == nil && !_hasNoCharacterSet)
{
FcResult result;
FcPattern *resolved;
FcCharSet *charset;
FcConfigSubstitute(NULL, _pattern, FcMatchPattern);
FcDefaultSubstitute(_pattern);
resolved = FcFontMatch(NULL, _pattern, &result);
if (FcResultMatch == FcPatternGetCharSet(resolved, FC_CHARSET, 0, &charset))
{
_characterSet = [[FontconfigCharacterSet alloc] initWithFontconfigCharSet: charset];
}
/* Only try to get the character set once because FcFontMatch is expensive */
if (_characterSet == nil)
{
_hasNoCharacterSet = YES;
}
FcPatternDestroy(resolved);
}
return _characterSet;
}
@end

View file

@ -28,850 +28,20 @@
Boston, MA 02110-1301, USA.
*/
#include <Foundation/NSObject.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSSet.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDebug.h>
#include <GNUstepGUI/GSFontInfo.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
#include <AppKit/NSFontDescriptor.h>
#include "gsc/GSGState.h"
#include "cairo/CairoFontEnumerator.h"
#include "cairo/CairoFontInfo.h"
// Old versions of fontconfig don't have FC_WEIGHT_ULTRABLACK defined.
// Use the maximal value instead.
#ifndef FC_WEIGHT_ULTRABLACK
#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_BLACK
#endif
@implementation CairoFontEnumerator
NSMutableDictionary * __allFonts;
+ (Class) faceInfoClass
{
return [CairoFaceInfo class];
}
+ (CairoFaceInfo *) fontWithName: (NSString *) name
{
CairoFaceInfo *face;
face = [__allFonts objectForKey: name];
if (!face)
{
NSDebugLLog(@"NSFont", @"Font not found %@", name);
}
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,
FC_SPACING, 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)
{
NSDebugLLog(@"NSFont", @"Found font family %@", familyString);
familyArray = [[NSMutableArray alloc] init];
[fcxft_allFontFamilies setObject: familyArray
forKey: familyString];
RELEASE(familyArray);
}
NSDebugLLog(@"NSFont", @"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: @"FreeSans"])
{
return @"FreeSans";
}
if ([allFontNames containsObject: @"DejaVu Sans"])
{
return @"DejaVu Sans";
}
if ([allFontNames containsObject: @"Tahoma"])
{
return @"Tahoma";
}
if ([allFontNames containsObject: @"Arial"])
{
return @"Arial";
}
return @"Helvetica";
}
- (NSString *) defaultBoldSystemFontName
{
if ([allFontNames containsObject: @"Bitstream Vera Sans-Bold"])
{
return @"Bitstream Vera Sans-Bold";
}
if ([allFontNames containsObject: @"FreeSans-Bold"])
{
return @"FreeSans-Bold";
}
if ([allFontNames containsObject: @"DejaVu Sans-Bold"])
{
return @"DejaVu Sans-Bold";
}
if ([allFontNames containsObject: @"Tahoma-Bold"])
{
return @"Tahoma-Bold";
}
if ([allFontNames containsObject: @"Arial-Bold"])
{
return @"Arial-Bold";
}
return @"Helvetica-Bold";
}
- (NSString *) defaultFixedPitchFontName
{
if ([allFontNames containsObject: @"Bitstream Vera Sans Mono"])
{
return @"Bitstream Vera Sans Mono";
}
if ([allFontNames containsObject: @"FreeMono"])
{
return @"FreeMono";
}
if ([allFontNames containsObject: @"DejaVu Sans Mono"])
{
return @"DejaVu Sans Mono";
}
if ([allFontNames containsObject: @"Courier New"])
{
return @"Courier New";
}
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
{
FcFontSet *fontSet;
result = FcResultMatch;
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;
return (CairoFaceInfo *) [super fontWithName: name];
}
@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)
{
FcValue value;
// 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);
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];
int fcWeight;
weight = MAX(-1, MIN(1, weight));
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];
int fcWidth;
width = MAX(-1, MIN(1, width));
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);
}
}
#define ADD_TO_PATTERN(key, handlerMethod, valueClass) \
do { \
id value = [_attributes objectForKey: key]; \
if (value) \
{ \
if ([value isKindOfClass: valueClass]) \
{ \
[self handlerMethod value]; \
} \
else \
{ \
NSLog(@"NSFontDescriptor: Ignoring invalid value %@ for attribute %@", value, key); \
} \
} \
} while (0);
- (void)addAttributes
{
ADD_TO_PATTERN(NSFontNameAttribute, addName:, [NSString class]);
ADD_TO_PATTERN(NSFontVisibleNameAttribute, addVisibleName:, [NSString class]);
ADD_TO_PATTERN(NSFontFamilyAttribute, addFamilyName:, [NSString class]);
ADD_TO_PATTERN(NSFontFaceAttribute, addStyleName:, [NSString class]);
ADD_TO_PATTERN(NSFontTraitsAttribute, addTraits:, [NSDictionary class]);
ADD_TO_PATTERN(NSFontSizeAttribute, addSize:, [NSNumber class]);
ADD_TO_PATTERN(NSFontCharacterSetAttribute, addCharacterSet:, [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))
{
double weight;
if (value >= FC_WEIGHT_BOLD)
{
symTraits |= NSFontBoldTrait;
}
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))
{
double width;
if (value >= FC_WIDTH_EXPANDED)
{
symTraits |= NSFontExpandedTrait;
}
if (value <= FC_WIDTH_CONDENSED)
{
symTraits |= NSFontCondensedTrait;
}
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;
}
#define READ_FROM_PATTERN(key, readMethod) \
do { \
id result = [self readMethod _pat]; \
if (result != nil) \
{ \
[_attributes setObject: result \
forKey: key]; \
} \
} while (0);
- (void)parseAttributes
{
READ_FROM_PATTERN(NSFontNameAttribute, readNameFromPattern:);
READ_FROM_PATTERN(NSFontVisibleNameAttribute, readVisibleNameFromPattern:);
READ_FROM_PATTERN(NSFontFamilyAttribute, readFamilyNameFromPattern:);
READ_FROM_PATTERN(NSFontFaceAttribute, readStyleNameFromPattern:);
READ_FROM_PATTERN(NSFontTraitsAttribute, readTraitsFromPattern:);
READ_FROM_PATTERN(NSFontSizeAttribute, readSizeFromPattern:);
READ_FROM_PATTERN(NSFontCharacterSetAttribute, readCharacterSetFromPattern:);
}
- (NSDictionary*)attributesFromPattern: (FcPattern *)pat
{
_attributes = [NSMutableDictionary dictionary];
_pat = pat;
[self parseAttributes];
return _attributes;
}
@end
@implementation FontconfigCharacterSet
- (id)initWithFontconfigCharSet: (FcCharSet*)charset
{
if ((self = [super init]))
{
_charset = FcCharSetCopy(charset);
}
return self;
}
- (id)mutableCopyWithZone: (NSZone*)aZone
{
return [[NSMutableCharacterSet characterSetWithBitmapRepresentation:
[self bitmapRepresentation]] retain];
}
- (void)dealloc
{
FcCharSetDestroy(_charset);
[super dealloc];
}
- (FcCharSet*)fontconfigCharSet
{
return _charset;
}
- (BOOL)characterIsMember: (unichar)c
{
return FcCharSetHasChar(_charset, c);
}
- (BOOL)longCharacterIsMember: (UTF32Char)c
{
return FcCharSetHasChar(_charset, c);
}
// FIXME: Implement for better performance
//- (NSData *)bitmapRepresentation
//{
//}
@end

View file

@ -37,29 +37,6 @@
@implementation CairoFontInfo
- (void) setCacheSize: (unsigned int)size
{
_cacheSize = size;
if (_cachedSizes)
{
free(_cachedSizes);
}
if (_cachedGlyphs)
{
free(_cachedGlyphs);
}
_cachedSizes = malloc(sizeof(NSSize) * size);
if (_cachedSizes)
{
memset(_cachedSizes, 0, sizeof(NSSize) * size);
}
_cachedGlyphs = malloc(sizeof(unsigned int) * size);
if (_cachedGlyphs)
{
memset(_cachedGlyphs, 0, sizeof(unsigned int) * size);
}
}
- (BOOL) setupAttributes
{
cairo_font_extents_t font_extents;
@ -68,28 +45,11 @@
cairo_matrix_t ctm;
cairo_font_options_t *options;
ASSIGN(_faceInfo, [CairoFontEnumerator fontWithName: fontName]);
if (!_faceInfo)
if (![super setupAttributes])
{
return NO;
}
// check for font specific cache size from face info
[self setCacheSize: [_faceInfo cacheSize]];
/* setting GSFontInfo:
* weight, traits, familyName,
* mostCompatibleStringEncoding, encodingScheme, coveredCharacterSet
*/
weight = [_faceInfo weight];
traits = [_faceInfo traits];
familyName = [[_faceInfo familyName] copy];
mostCompatibleStringEncoding = NSUTF8StringEncoding;
encodingScheme = @"iso10646-1";
coveredCharacterSet = [[_faceInfo characterSet] retain];
/* setting GSFontInfo:
* xHeight, pix_width, pix_height
*/
@ -190,23 +150,13 @@
- (void) dealloc
{
RELEASE(_faceInfo);
if (_scaled)
{
cairo_scaled_font_destroy(_scaled);
}
if (_cachedSizes)
free(_cachedSizes);
if (_cachedGlyphs)
free(_cachedGlyphs);
[super dealloc];
}
- (CGFloat) defaultLineHeightForFont
{
return lineHeight;
}
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
{
/* FIXME: There is no proper way to determine with the toy font API,
@ -309,15 +259,6 @@ BOOL _cairo_extents_for_NSGlyph(cairo_scaled_font_t *scaled_font, NSGlyph glyph,
return 0.0;
}
- (NSGlyph) glyphWithName: (NSString *) glyphName
{
/* subclass should override */
/* terrible! FIXME */
NSGlyph g = [glyphName cString][0];
return g;
}
- (void) appendBezierPathWithGlyphs: (NSGlyph *)glyphs
count: (int)length
toBezierPath: (NSBezierPath *)path

View file

@ -1261,7 +1261,7 @@ _set_op(cairo_t *ct, NSCompositingOperation op)
cairo_pattern_t *cpattern;
cairo_matrix_t source_matrix;
NSDebugMLLog(@"CairoGState", @"%self: %@\n", self);
NSDebugMLLog(@"CairoGState", @"self: %@\n", self);
if (!_ct || !source->_ct)
{

View file

@ -37,6 +37,10 @@ cairo_OBJC_FILES = CairoSurface.m \
CairoFaceInfo.m \
CairoPSSurface.m \
CairoPDFSurface.m \
../fontconfig/FCFaceInfo.m \
../fontconfig/FCFontEnumerator.m \
../fontconfig/FCFontInfo.m \
ifeq ($(BUILD_SERVER),x11)
ifeq ($(WITH_GLITZ),yes)

View file

@ -0,0 +1,141 @@
/*
FCFaceInfo.m
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
Base on original code of Alex Malmberg
Rewrite: Fred Kiefer <fredkiefer@gmx.de>
Date: Jan 2006
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "fontconfig/FCFaceInfo.h"
#include "fontconfig/FCFontEnumerator.h"
#include <AppKit/NSFontManager.h>
@implementation FCFaceInfo
- (id) initWithfamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits
pattern: (FcPattern *)pattern
{
_pattern = pattern;
FcPatternReference(_pattern);
[self setFamilyName: familyName];
[self setWeight: weight];
[self setTraits: traits];
return self;
}
- (void) dealloc
{
FcPatternDestroy(_pattern);
RELEASE(_familyName);
RELEASE(_characterSet);
[super dealloc];
}
- (void) setFamilyName: (NSString *)name
{
ASSIGN(_familyName, name);
}
- (NSString *)familyName
{
return _familyName;
}
- (int) weight
{
return _weight;
}
- (void) setWeight: (int)weight
{
_weight = weight;
}
- (unsigned int) traits
{
return _traits;
}
- (void) setTraits: (unsigned int)traits
{
_traits = traits;
}
- (unsigned int) cacheSize
{
return 257;
}
- (void *) fontFace
{
[self subclassResponsibility: _cmd];
return NULL;
}
- (FcPattern *) matchedPattern
{
FcResult result;
FcPattern *resolved;
FcConfigSubstitute(NULL, _pattern, FcMatchPattern);
FcDefaultSubstitute(_pattern);
resolved = FcFontMatch(NULL, _pattern, &result);
return resolved;
}
- (NSCharacterSet*)characterSet
{
if (_characterSet == nil && !_hasNoCharacterSet)
{
FcResult result;
FcPattern *resolved;
FcCharSet *charset;
FcConfigSubstitute(NULL, _pattern, FcMatchPattern);
FcDefaultSubstitute(_pattern);
resolved = FcFontMatch(NULL, _pattern, &result);
if (FcResultMatch == FcPatternGetCharSet(resolved, FC_CHARSET, 0, &charset))
{
_characterSet = [[FontconfigCharacterSet alloc] initWithFontconfigCharSet: charset];
}
/* Only try to get the character set once because FcFontMatch is expensive */
if (_characterSet == nil)
{
_hasNoCharacterSet = YES;
}
FcPatternDestroy(resolved);
}
return _characterSet;
}
@end

View file

@ -0,0 +1,884 @@
/*
FCFontEnumerator.m
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
Base on original code of Alex Malmberg
Rewrite: Fred Kiefer <fredkiefer@gmx.de>
Date: Jan 2006
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <Foundation/NSObject.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSSet.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDebug.h>
#include <GNUstepGUI/GSFontInfo.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
#include <AppKit/NSFontDescriptor.h>
#include "gsc/GSGState.h"
#include "fontconfig/FCFontEnumerator.h"
#include "fontconfig/FCFontInfo.h"
// Old versions of fontconfig don't have FC_WEIGHT_ULTRABLACK defined.
// Use the maximal value instead.
#ifndef FC_WEIGHT_ULTRABLACK
#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_BLACK
#endif
@implementation FCFontEnumerator
NSMutableDictionary * __allFonts;
+ (FCFaceInfo *) fontWithName: (NSString *) name
{
FCFaceInfo *face;
face = [__allFonts objectForKey: name];
if (!face)
{
NSDebugLLog(@"NSFont", @"Font not found %@", name);
}
return face;
}
+ (Class) faceInfoClass
{
[self subclassResponsibility: _cmd];
return nil;
}
// 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];
Class faceInfoClass = [[self class] faceInfoClass];
FcPattern *pat = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT,
FC_SPACING, 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;
FCFaceInfo *aFont;
NSString *name = [fontArray objectAtIndex: 0];
familyString = [NSString stringWithUTF8String: family];
familyArray = [fcxft_allFontFamilies objectForKey: familyString];
if (familyArray == nil)
{
NSDebugLLog(@"NSFont", @"Found font family %@", familyString);
familyArray = [[NSMutableArray alloc] init];
[fcxft_allFontFamilies setObject: familyArray
forKey: familyString];
RELEASE(familyArray);
}
NSDebugLLog(@"NSFont", @"fc enumerator: adding font: %@", name);
[familyArray addObject: fontArray];
[fcxft_allFontNames addObject: name];
aFont = [[faceInfoClass 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: @"FreeSans"])
{
return @"FreeSans";
}
if ([allFontNames containsObject: @"DejaVu Sans"])
{
return @"DejaVu Sans";
}
if ([allFontNames containsObject: @"Tahoma"])
{
return @"Tahoma";
}
if ([allFontNames containsObject: @"Arial"])
{
return @"Arial";
}
return @"Helvetica";
}
- (NSString *) defaultBoldSystemFontName
{
if ([allFontNames containsObject: @"Bitstream Vera Sans-Bold"])
{
return @"Bitstream Vera Sans-Bold";
}
if ([allFontNames containsObject: @"FreeSans-Bold"])
{
return @"FreeSans-Bold";
}
if ([allFontNames containsObject: @"DejaVu Sans-Bold"])
{
return @"DejaVu Sans-Bold";
}
if ([allFontNames containsObject: @"Tahoma-Bold"])
{
return @"Tahoma-Bold";
}
if ([allFontNames containsObject: @"Arial-Bold"])
{
return @"Arial-Bold";
}
return @"Helvetica-Bold";
}
- (NSString *) defaultFixedPitchFontName
{
if ([allFontNames containsObject: @"Bitstream Vera Sans Mono"])
{
return @"Bitstream Vera Sans Mono";
}
if ([allFontNames containsObject: @"FreeMono"])
{
return @"FreeMono";
}
if ([allFontNames containsObject: @"DejaVu Sans Mono"])
{
return @"DejaVu Sans Mono";
}
if ([allFontNames containsObject: @"Courier New"])
{
return @"Courier New";
}
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
{
FcFontSet *fontSet;
result = FcResultMatch;
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)
{
FcValue value;
// 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);
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];
int fcWeight;
weight = MAX(-1, MIN(1, weight));
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];
int fcWidth;
width = MAX(-1, MIN(1, width));
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);
}
}
#define ADD_TO_PATTERN(key, handlerMethod, valueClass) \
do { \
id value = [_attributes objectForKey: key]; \
if (value) \
{ \
if ([value isKindOfClass: valueClass]) \
{ \
[self handlerMethod value]; \
} \
else \
{ \
NSLog(@"NSFontDescriptor: Ignoring invalid value %@ for attribute %@", value, key); \
} \
} \
} while (0);
- (void)addAttributes
{
ADD_TO_PATTERN(NSFontNameAttribute, addName:, [NSString class]);
ADD_TO_PATTERN(NSFontVisibleNameAttribute, addVisibleName:, [NSString class]);
ADD_TO_PATTERN(NSFontFamilyAttribute, addFamilyName:, [NSString class]);
ADD_TO_PATTERN(NSFontFaceAttribute, addStyleName:, [NSString class]);
ADD_TO_PATTERN(NSFontTraitsAttribute, addTraits:, [NSDictionary class]);
ADD_TO_PATTERN(NSFontSizeAttribute, addSize:, [NSNumber class]);
ADD_TO_PATTERN(NSFontCharacterSetAttribute, addCharacterSet:, [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))
{
double weight;
if (value >= FC_WEIGHT_BOLD)
{
symTraits |= NSFontBoldTrait;
}
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))
{
double width;
if (value >= FC_WIDTH_EXPANDED)
{
symTraits |= NSFontExpandedTrait;
}
if (value <= FC_WIDTH_CONDENSED)
{
symTraits |= NSFontCondensedTrait;
}
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;
}
#define READ_FROM_PATTERN(key, readMethod) \
do { \
id result = [self readMethod _pat]; \
if (result != nil) \
{ \
[_attributes setObject: result \
forKey: key]; \
} \
} while (0);
- (void)parseAttributes
{
READ_FROM_PATTERN(NSFontNameAttribute, readNameFromPattern:);
READ_FROM_PATTERN(NSFontVisibleNameAttribute, readVisibleNameFromPattern:);
READ_FROM_PATTERN(NSFontFamilyAttribute, readFamilyNameFromPattern:);
READ_FROM_PATTERN(NSFontFaceAttribute, readStyleNameFromPattern:);
READ_FROM_PATTERN(NSFontTraitsAttribute, readTraitsFromPattern:);
READ_FROM_PATTERN(NSFontSizeAttribute, readSizeFromPattern:);
READ_FROM_PATTERN(NSFontCharacterSetAttribute, readCharacterSetFromPattern:);
}
- (NSDictionary*)attributesFromPattern: (FcPattern *)pat
{
_attributes = [NSMutableDictionary dictionary];
_pat = pat;
[self parseAttributes];
return _attributes;
}
@end
@implementation FontconfigCharacterSet
- (id)initWithFontconfigCharSet: (FcCharSet*)charset
{
if ((self = [super init]))
{
_charset = FcCharSetCopy(charset);
}
return self;
}
- (id)mutableCopyWithZone: (NSZone*)aZone
{
return [[NSMutableCharacterSet characterSetWithBitmapRepresentation:
[self bitmapRepresentation]] retain];
}
- (void)dealloc
{
FcCharSetDestroy(_charset);
[super dealloc];
}
- (FcCharSet*)fontconfigCharSet
{
return _charset;
}
- (BOOL)characterIsMember: (unichar)c
{
return FcCharSetHasChar(_charset, c);
}
- (BOOL)longCharacterIsMember: (UTF32Char)c
{
return FcCharSetHasChar(_charset, c);
}
// FIXME: Implement for better performance
//- (NSData *)bitmapRepresentation
//{
//}
@end

View file

@ -0,0 +1,181 @@
/*
FCFontInfo.m
Copyright (C) 2003 Free Software Foundation, Inc.
August 31, 2003
Written by Banlu Kemiyatorn <object at gmail dot com>
Base on original code of Alex Malmberg
This file is part of GNUstep.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "GNUstepBase/Unicode.h"
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
#include "fontconfig/FCFontInfo.h"
#include "fontconfig/FCFontEnumerator.h"
#include <math.h>
@implementation FCFontInfo
- (void) setCacheSize: (unsigned int)size
{
_cacheSize = size;
if (_cachedSizes)
{
free(_cachedSizes);
}
if (_cachedGlyphs)
{
free(_cachedGlyphs);
}
_cachedSizes = malloc(sizeof(NSSize) * size);
if (_cachedSizes)
{
memset(_cachedSizes, 0, sizeof(NSSize) * size);
}
_cachedGlyphs = malloc(sizeof(unsigned int) * size);
if (_cachedGlyphs)
{
memset(_cachedGlyphs, 0, sizeof(unsigned int) * size);
}
}
- (BOOL) setupAttributes
{
ASSIGN(_faceInfo, [FCFontEnumerator fontWithName: fontName]);
if (!_faceInfo)
{
return NO;
}
// check for font specific cache size from face info
[self setCacheSize: [_faceInfo cacheSize]];
/* setting GSFontInfo:
* weight, traits, familyName,
* mostCompatibleStringEncoding, encodingScheme, coveredCharacterSet
*/
weight = [_faceInfo weight];
traits = [_faceInfo traits];
familyName = [[_faceInfo familyName] copy];
mostCompatibleStringEncoding = NSUTF8StringEncoding;
encodingScheme = @"iso10646-1";
coveredCharacterSet = [[_faceInfo characterSet] retain];
return YES;
}
- (id) initWithFontName: (NSString *)name
matrix: (const CGFloat *)fmatrix
screenFont: (BOOL)p_screenFont
{
self = [super init];
if (!self)
return nil;
_screenFont = p_screenFont;
fontName = [name copy];
memcpy(matrix, fmatrix, sizeof(matrix));
if (_screenFont)
{
/* Round up; makes the text more legible. */
matrix[0] = ceil(matrix[0]);
if (matrix[3] < 0.0)
matrix[3] = floor(matrix[3]);
else
matrix[3] = ceil(matrix[3]);
}
if (![self setupAttributes])
{
RELEASE(self);
return nil;
}
return self;
}
- (void) dealloc
{
RELEASE(_faceInfo);
if (_cachedSizes)
free(_cachedSizes);
if (_cachedGlyphs)
free(_cachedGlyphs);
[super dealloc];
}
- (CGFloat) defaultLineHeightForFont
{
return lineHeight;
}
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
{
[self subclassResponsibility: _cmd];
return YES;
}
- (NSSize) advancementForGlyph: (NSGlyph)glyph
{
[self subclassResponsibility: _cmd];
return NSZeroSize;
}
- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
{
[self subclassResponsibility: _cmd];
return NSZeroRect;
}
- (CGFloat) widthOfString: (NSString *)string
{
[self subclassResponsibility: _cmd];
return 0.0;
}
- (NSGlyph) glyphWithName: (NSString *) glyphName
{
/* subclass should override */
/* terrible! FIXME */
NSGlyph g = [glyphName cString][0];
return g;
}
- (void) appendBezierPathWithGlyphs: (NSGlyph *)glyphs
count: (int)length
toBezierPath: (NSBezierPath *)path
{
[self subclassResponsibility: _cmd];
}
- (void) drawGlyphs: (const NSGlyph*)glyphs
length: (int)length
on: (cairo_t*)ct
{
[self subclassResponsibility: _cmd];
}
@end