mirror of
https://github.com/gnustep/libs-back.git
synced 2025-06-01 17:52:33 +00:00
Added fontconfig specific code.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@16083 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
25cf5be89d
commit
92f46e994f
1 changed files with 319 additions and 64 deletions
|
@ -39,10 +39,180 @@
|
||||||
|
|
||||||
#include "xlib/GSXftFontInfo.h"
|
#include "xlib/GSXftFontInfo.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_FC
|
||||||
|
#include <fontconfig/fontconfig.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class global dictionary of existing fonts
|
* class global dictionary of existing fonts
|
||||||
*/
|
*/
|
||||||
static NSMutableDictionary *_globalFontDictionary = nil;
|
static NSMutableDictionary *allFonts = nil;
|
||||||
|
|
||||||
|
// just a warpper around a FcPattern, to make it a NSObject
|
||||||
|
@interface FcFont : NSObject
|
||||||
|
{
|
||||||
|
FcPattern *aFont;
|
||||||
|
}
|
||||||
|
- initWithPattern:(FcPattern *)aFace;
|
||||||
|
- (FcPattern *)font;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FcFont
|
||||||
|
|
||||||
|
- initWithPattern:(FcPattern *)aFace
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
aFont = aFace;
|
||||||
|
FcPatternReference(aFace);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (FcPattern *)font
|
||||||
|
{
|
||||||
|
return aFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
FcPatternDestroy(aFont);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FcFontEnumerator
|
||||||
|
|
||||||
|
// 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 stringWithCString: 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 alloc] init];
|
||||||
|
NSMutableDictionary *fcxft_allFonts = [[NSMutableDictionary alloc] init];
|
||||||
|
NSMutableArray *fcxft_allFontNames = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
FcPattern *pat = FcPatternCreate();
|
||||||
|
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT, 0);
|
||||||
|
FcFontSet *fs = FcFontList(0, 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;
|
||||||
|
FcFont *aFont;
|
||||||
|
NSString *name = [fontArray objectAtIndex: 0];
|
||||||
|
|
||||||
|
familyString = [NSString stringWithCString: family];
|
||||||
|
if (!(familyArray = [fcxft_allFontFamilies objectForKey: familyString]))
|
||||||
|
{
|
||||||
|
familyArray = [[NSMutableArray alloc] init];
|
||||||
|
[fcxft_allFontFamilies setObject: familyArray forKey: familyString];
|
||||||
|
RELEASE(familyArray);
|
||||||
|
}
|
||||||
|
NSDebugLog(@"fc enumerator: adding font: %@", name);
|
||||||
|
[familyArray addObject: fontArray];
|
||||||
|
[fcxft_allFontNames addObject: name];
|
||||||
|
aFont = [[FcFont alloc] initWithPattern: fs->fonts[i]];
|
||||||
|
[fcxft_allFonts setObject: aFont forKey: name];
|
||||||
|
RELEASE(aFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FcFontSetDestroy (fs);
|
||||||
|
|
||||||
|
allFontNames = fcxft_allFontNames;
|
||||||
|
allFontFamilies = fcxft_allFontFamilies;
|
||||||
|
allFonts = fcxft_allFonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
#endif
|
||||||
|
|
||||||
@interface GSXftFontInfo (Private)
|
@interface GSXftFontInfo (Private)
|
||||||
|
|
||||||
|
@ -394,13 +564,107 @@ static NSMutableDictionary *_globalFontDictionary = nil;
|
||||||
{
|
{
|
||||||
Display *xdpy = [XGServer currentXDisplay];
|
Display *xdpy = [XGServer currentXDisplay];
|
||||||
int defaultScreen = DefaultScreen(xdpy);
|
int defaultScreen = DefaultScreen(xdpy);
|
||||||
NSString *weightString;
|
NSString *weightString = nil;
|
||||||
|
|
||||||
|
#ifdef HAVE_FC
|
||||||
|
FcFont *realFont = [allFonts objectForKey: fontName];
|
||||||
|
FcPattern *fontPattern;
|
||||||
|
FcPattern *pattern;
|
||||||
|
FcResult fc_result;
|
||||||
|
char *family;
|
||||||
|
int fcspacing, fcweight, fcslant;
|
||||||
|
|
||||||
|
if (!realFont)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xdpy)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
fontPattern = FcPatternDuplicate([realFont font]);
|
||||||
|
|
||||||
|
// the only thing needs customization here is the size
|
||||||
|
FcPatternAddDouble(fontPattern, FC_SIZE, (double)(matrix[0]));
|
||||||
|
// Should do this only when size > 8
|
||||||
|
FcPatternAddBool(fontPattern, FC_AUTOHINT, FcTrue);
|
||||||
|
pattern = XftFontMatch(xdpy, DefaultScreen(xdpy), fontPattern, &fc_result);
|
||||||
|
// tide up
|
||||||
|
FcPatternDestroy(fontPattern);
|
||||||
|
|
||||||
|
if ((font_info = XftFontOpenPattern(xdpy, pattern)))
|
||||||
|
{
|
||||||
|
NSDebugLog(@"Loaded font: %@", fontName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSDebugLog(@"Cannot load font: %@", fontName);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
|
||||||
|
{
|
||||||
|
ASSIGN(familyName, [NSString stringWithCString: (const char*)family]);
|
||||||
|
}
|
||||||
|
if (FcPatternGetInteger(pattern, FC_SPACING, 0, &fcspacing) == FcResultMatch)
|
||||||
|
{
|
||||||
|
isFixedPitch = (fcspacing == FC_MONO || fcspacing == FC_CHARCELL);
|
||||||
|
}
|
||||||
|
if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &fcweight) == FcResultMatch)
|
||||||
|
{
|
||||||
|
switch (fcweight)
|
||||||
|
{
|
||||||
|
case FC_WEIGHT_LIGHT:
|
||||||
|
weight = 3;
|
||||||
|
weightString = @"light";
|
||||||
|
break;
|
||||||
|
case FC_WEIGHT_MEDIUM:
|
||||||
|
weight = 6;
|
||||||
|
weightString = @"medium";
|
||||||
|
break;
|
||||||
|
case FC_WEIGHT_DEMIBOLD:
|
||||||
|
weight = 7;
|
||||||
|
weightString = @"demibold";
|
||||||
|
break;
|
||||||
|
case FC_WEIGHT_BOLD:
|
||||||
|
weight = 9;
|
||||||
|
weightString = @"bold";
|
||||||
|
break;
|
||||||
|
case FC_WEIGHT_BLACK:
|
||||||
|
weight = 12;
|
||||||
|
weightString = @"black";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Don't know
|
||||||
|
weight = 6;
|
||||||
|
weightString = @"medium";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcPatternGetInteger(pattern, FC_SLANT, 0, &fcslant) == FcResultMatch)
|
||||||
|
{
|
||||||
|
switch (fcslant)
|
||||||
|
{
|
||||||
|
case FC_SLANT_ROMAN:
|
||||||
|
traits |= NSUnitalicFontMask;
|
||||||
|
break;
|
||||||
|
case FC_SLANT_ITALIC:
|
||||||
|
traits |= NSItalicFontMask;
|
||||||
|
break;
|
||||||
|
case FC_SLANT_OBLIQUE:
|
||||||
|
traits |= NSItalicFontMask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: somehow make gnustep-gui send unicode our way. utf8? ugly, but it works */
|
||||||
|
mostCompatibleStringEncoding = NSUTF8StringEncoding;
|
||||||
|
encodingScheme = @"iso10646-1";
|
||||||
|
#else
|
||||||
NSString *reg;
|
NSString *reg;
|
||||||
long height;
|
|
||||||
XftPattern *pattern;
|
XftPattern *pattern;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
NSString *xfontname;
|
NSString *xfontname;
|
||||||
|
|
||||||
char *xftTypeString;
|
char *xftTypeString;
|
||||||
int xftTypeInt;
|
int xftTypeInt;
|
||||||
NSArray *encoding;
|
NSArray *encoding;
|
||||||
|
@ -414,52 +678,26 @@ static NSMutableDictionary *_globalFontDictionary = nil;
|
||||||
// Load Xft font and get font info structure.
|
// Load Xft font and get font info structure.
|
||||||
if ((xfontname == nil) ||
|
if ((xfontname == nil) ||
|
||||||
(font_info = XftFontOpenXlfd(xdpy, defaultScreen, [xfontname cString])) == NULL)
|
(font_info = XftFontOpenXlfd(xdpy, defaultScreen, [xfontname cString])) == NULL)
|
||||||
{
|
|
||||||
NSLog(@"Selected font: %@ (%@) is not available.\n"
|
|
||||||
@"Using system default font instead", fontName, xfontname);
|
|
||||||
|
|
||||||
if ((font_info = XftFontOpen(xdpy, defaultScreen, 0)) == NULL)
|
|
||||||
{
|
{
|
||||||
NSLog(@"Unable to open fixed font");
|
NSLog(@"Unable to open fixed font");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
NSDebugLog(@"Loaded font: %@", xfontname);
|
NSDebugLog(@"Loaded font: %@", xfontname);
|
||||||
|
|
||||||
// Fill the afmDitionary and ivars
|
|
||||||
[fontDictionary setObject: fontName forKey: NSAFMFontName];
|
|
||||||
|
|
||||||
pattern = font_info->pattern;
|
pattern = font_info->pattern;
|
||||||
result = XftPatternGetString(pattern, XFT_FAMILY, 0, &xftTypeString);
|
result = XftPatternGetString(pattern, XFT_FAMILY, 0, &xftTypeString);
|
||||||
if (result != XftResultTypeMismatch)
|
if (result != XftResultTypeMismatch)
|
||||||
{
|
{
|
||||||
ASSIGN(familyName,
|
ASSIGN(familyName,
|
||||||
[NSString stringWithCString: (const char*)xftTypeString]);
|
[NSString stringWithCString: (const char*)xftTypeString]);
|
||||||
[fontDictionary setObject: familyName forKey: NSAFMFamilyName];
|
|
||||||
}
|
}
|
||||||
result = XftPatternGetInteger(pattern, XFT_SPACING, 0, &xftTypeInt);
|
result = XftPatternGetInteger(pattern, XFT_SPACING, 0, &xftTypeInt);
|
||||||
if (result != XftResultTypeMismatch)
|
if (result != XftResultTypeMismatch)
|
||||||
{
|
{
|
||||||
isFixedPitch = (weight != 0);
|
isFixedPitch = (xftTypeInt != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
isBaseFont = NO;
|
|
||||||
ascender = font_info->ascent;
|
|
||||||
[fontDictionary setObject: [NSNumber numberWithFloat: ascender]
|
|
||||||
forKey: NSAFMAscender];
|
|
||||||
descender = -(font_info->descent);
|
|
||||||
[fontDictionary setObject: [NSNumber numberWithFloat: descender]
|
|
||||||
forKey: NSAFMDescender];
|
|
||||||
fontBBox = NSMakeRect(
|
|
||||||
(float)(0),
|
|
||||||
(float)(0 - font_info->ascent),
|
|
||||||
(float)(font_info->max_advance_width),
|
|
||||||
(float)(font_info->ascent + font_info->descent));
|
|
||||||
maximumAdvancement = NSMakeSize(font_info->max_advance_width,
|
|
||||||
(font_info->ascent + font_info->descent));
|
|
||||||
minimumAdvancement = NSMakeSize(0,0);
|
|
||||||
|
|
||||||
result = XftPatternGetInteger(pattern, XFT_WEIGHT, 0, &xftTypeInt);
|
result = XftPatternGetInteger(pattern, XFT_WEIGHT, 0, &xftTypeInt);
|
||||||
if (result != XftResultTypeMismatch)
|
if (result != XftResultTypeMismatch)
|
||||||
{
|
{
|
||||||
|
@ -489,19 +727,7 @@ static NSMutableDictionary *_globalFontDictionary = nil;
|
||||||
// Don't know
|
// Don't know
|
||||||
weight = 6;;
|
weight = 6;;
|
||||||
}
|
}
|
||||||
if (weightString != nil)
|
|
||||||
{
|
|
||||||
[fontDictionary setObject: weightString forKey: NSAFMWeight];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (weight >= 9)
|
|
||||||
traits |= NSBoldFontMask;
|
|
||||||
else
|
|
||||||
traits |= NSUnboldFontMask;
|
|
||||||
|
|
||||||
if (isFixedPitch)
|
|
||||||
traits |= NSFixedPitchFontMask;
|
|
||||||
|
|
||||||
result = XftPatternGetInteger(pattern, XFT_SLANT, 0, &xftTypeInt);
|
result = XftPatternGetInteger(pattern, XFT_SLANT, 0, &xftTypeInt);
|
||||||
if (result != XftResultTypeMismatch)
|
if (result != XftResultTypeMismatch)
|
||||||
|
@ -512,7 +738,7 @@ static NSMutableDictionary *_globalFontDictionary = nil;
|
||||||
traits |= NSUnitalicFontMask;
|
traits |= NSUnitalicFontMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
XftPatternGetString (pattern, XFT_ENCODING, 0, &xftTypeString);
|
XftPatternGetString(pattern, XFT_ENCODING, 0, &xftTypeString);
|
||||||
encodingScheme = [NSString stringWithCString: xftTypeString];
|
encodingScheme = [NSString stringWithCString: xftTypeString];
|
||||||
encoding = [encodingScheme componentsSeparatedByString: @"-"];
|
encoding = [encodingScheme componentsSeparatedByString: @"-"];
|
||||||
reg = [encoding objectAtIndex: 0];
|
reg = [encoding objectAtIndex: 0];
|
||||||
|
@ -533,25 +759,54 @@ static NSMutableDictionary *_globalFontDictionary = nil;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
encodingScheme = nil;
|
encodingScheme = nil;
|
||||||
/*
|
|
||||||
height = XGFontPropULong(xdpy, font_info, XA_X_HEIGHT);
|
|
||||||
if (height != 0)
|
|
||||||
{
|
|
||||||
xHeight = (float)height;
|
|
||||||
[fontDictionary setObject: [NSNumber numberWithFloat: xHeight]
|
|
||||||
forKey: NSAFMXHeight];
|
|
||||||
}
|
|
||||||
|
|
||||||
height = XGFontPropULong(xdpy, font_info, XA_CAP_HEIGHT);
|
|
||||||
if (height != 0)
|
|
||||||
{
|
|
||||||
capHeight = (float)height;
|
|
||||||
[fontDictionary setObject: [NSNumber numberWithFloat: capHeight]
|
|
||||||
forKey: NSAFMCapHeight];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// FIXME: italicAngle, underlinePosition, underlineThickness are not set.
|
// FIXME: italicAngle, underlinePosition, underlineThickness are not set.
|
||||||
// Should use XA_ITALIC_ANGLE, XA_UNDERLINE_POSITION, XA_UNDERLINE_THICKNESS
|
// Should use XA_ITALIC_ANGLE, XA_UNDERLINE_POSITION, XA_UNDERLINE_THICKNESS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fill the afmDitionary and ivars
|
||||||
|
[fontDictionary setObject: fontName forKey: NSAFMFontName];
|
||||||
|
|
||||||
|
if (familyName != nil)
|
||||||
|
{
|
||||||
|
[fontDictionary setObject: familyName forKey: NSAFMFamilyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weightString != nil)
|
||||||
|
{
|
||||||
|
[fontDictionary setObject: weightString forKey: NSAFMWeight];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weight >= 9)
|
||||||
|
traits |= NSBoldFontMask;
|
||||||
|
else
|
||||||
|
traits |= NSUnboldFontMask;
|
||||||
|
|
||||||
|
if (isFixedPitch)
|
||||||
|
traits |= NSFixedPitchFontMask;
|
||||||
|
|
||||||
|
isBaseFont = NO;
|
||||||
|
ascender = font_info->ascent;
|
||||||
|
[fontDictionary setObject: [NSNumber numberWithFloat: ascender]
|
||||||
|
forKey: NSAFMAscender];
|
||||||
|
descender = -(font_info->descent);
|
||||||
|
[fontDictionary setObject: [NSNumber numberWithFloat: descender]
|
||||||
|
forKey: NSAFMDescender];
|
||||||
|
capHeight = ascender - descender; // TODO
|
||||||
|
xHeight = capHeight*0.6; //Errr... TODO
|
||||||
|
fontBBox = NSMakeRect(
|
||||||
|
(float)(0),
|
||||||
|
(float)(0 - font_info->ascent),
|
||||||
|
(float)(font_info->max_advance_width),
|
||||||
|
(float)(font_info->ascent + font_info->descent));
|
||||||
|
maximumAdvancement = NSMakeSize(font_info->max_advance_width,
|
||||||
|
(font_info->ascent + font_info->descent));
|
||||||
|
minimumAdvancement = NSMakeSize(0,0);
|
||||||
|
// printf("h=%g a=%g d=%g max=(%g %g) (%g %g)+(%g %g)\n",
|
||||||
|
// xHeight, ascender, descender,
|
||||||
|
// maximumAdvancement.width, maximumAdvancement.height,
|
||||||
|
// fontBBox.origin.x, fontBBox.origin.y,
|
||||||
|
// fontBBox.size.width, fontBBox.size.height);
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue