mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 07:21:02 +00:00
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:
parent
31ff3e1ba1
commit
5dd127aec9
15 changed files with 1459 additions and 1058 deletions
37
ChangeLog
37
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
72
Headers/fontconfig/FCFaceInfo.h
Normal file
72
Headers/fontconfig/FCFaceInfo.h
Normal 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
|
70
Headers/fontconfig/FCFontEnumerator.h
Normal file
70
Headers/fontconfig/FCFontEnumerator.h
Normal 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
|
51
Headers/fontconfig/FCFontInfo.h
Normal file
51
Headers/fontconfig/FCFontInfo.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
141
Source/fontconfig/FCFaceInfo.m
Normal file
141
Source/fontconfig/FCFaceInfo.m
Normal 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
|
884
Source/fontconfig/FCFontEnumerator.m
Normal file
884
Source/fontconfig/FCFontEnumerator.m
Normal 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
|
||||
|
181
Source/fontconfig/FCFontInfo.m
Normal file
181
Source/fontconfig/FCFontInfo.m
Normal 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
|
Loading…
Reference in a new issue