mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-23 11:51:27 +00:00
commit
8691c48537
8 changed files with 455 additions and 110 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -11,3 +11,6 @@ config.cache
|
||||||
config.make
|
config.make
|
||||||
back.make
|
back.make
|
||||||
Source/config.h
|
Source/config.h
|
||||||
|
Source/libgnustep*Info.plist
|
||||||
|
Tools/XGCommonFont.m
|
||||||
|
Tools/xdnd.c
|
||||||
|
|
|
@ -63,6 +63,8 @@
|
||||||
- (NSString *) familyName;
|
- (NSString *) familyName;
|
||||||
- (void) setFamilyName: (NSString *)name;
|
- (void) setFamilyName: (NSString *)name;
|
||||||
|
|
||||||
|
- (NSString *) displayName;
|
||||||
|
|
||||||
- (void *) fontFace;
|
- (void *) fontFace;
|
||||||
- (FcPattern *) matchedPattern;
|
- (FcPattern *) matchedPattern;
|
||||||
|
|
||||||
|
|
|
@ -245,8 +245,7 @@ static void add_face(NSString *family, int family_weight,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fi->displayName = [[family stringByAppendingString: @" "]
|
fi->displayName = [[NSString stringWithFormat: @"%@ %@", family, faceName] retain];
|
||||||
stringByAppendingString: faceName];
|
|
||||||
|
|
||||||
|
|
||||||
weight = family_weight;
|
weight = family_weight;
|
||||||
|
|
|
@ -352,6 +352,11 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib,
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString*) displayName
|
||||||
|
{
|
||||||
|
return face_info->displayName;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) set
|
- (void) set
|
||||||
{
|
{
|
||||||
NSLog(@"ignore -set method of font '%@'", fontName);
|
NSLog(@"ignore -set method of font '%@'", fontName);
|
||||||
|
|
|
@ -35,6 +35,13 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <cairo-ft.h>
|
#include <cairo-ft.h>
|
||||||
|
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_SFNT_NAMES_H
|
||||||
|
#include FT_TRUETYPE_TABLES_H
|
||||||
|
#include FT_TYPE1_TABLES_H
|
||||||
|
#include <fontconfig/fontconfig.h>
|
||||||
|
#include <fontconfig/fcfreetype.h>
|
||||||
|
|
||||||
@implementation CairoFontInfo
|
@implementation CairoFontInfo
|
||||||
|
|
||||||
- (BOOL) setupAttributes
|
- (BOOL) setupAttributes
|
||||||
|
@ -44,6 +51,10 @@
|
||||||
cairo_matrix_t font_matrix;
|
cairo_matrix_t font_matrix;
|
||||||
cairo_matrix_t ctm;
|
cairo_matrix_t ctm;
|
||||||
cairo_font_options_t *options;
|
cairo_font_options_t *options;
|
||||||
|
cairo_hint_metrics_t metrics = CAIRO_HINT_METRICS_ON;
|
||||||
|
cairo_hint_style_t style = CAIRO_HINT_STYLE_DEFAULT;
|
||||||
|
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||||
|
int hinting = 0, subpixel = 0;
|
||||||
|
|
||||||
if (![super setupAttributes])
|
if (![super setupAttributes])
|
||||||
{
|
{
|
||||||
|
@ -71,16 +82,48 @@
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must not leave the hinting settings as their defaults,
|
if ((hinting = [ud integerForKey: @"GSFontHinting"]))
|
||||||
// because if we did, that would mean using the surface defaults
|
{ /*
|
||||||
// which might or might not use hinting (xlib does by default.)
|
* This part is only here to debug disabling the use of hinting for
|
||||||
//
|
* metrics, because doing so causes menus to get cut off on the right.
|
||||||
// Since we make measurements outside of the context of a surface
|
*/
|
||||||
// (-advancementForGlyph:), we need to ensure that the same
|
switch (hinting >> 4)
|
||||||
// hinting settings are used there as when we draw. For now,
|
{
|
||||||
// just force hinting to be off.
|
case 1:
|
||||||
cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_ON);
|
metrics = CAIRO_HINT_METRICS_OFF;
|
||||||
cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
|
break;
|
||||||
|
case 2:
|
||||||
|
metrics = CAIRO_HINT_METRICS_ON;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (hinting & 0x0f)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
style = CAIRO_HINT_STYLE_NONE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
style = CAIRO_HINT_STYLE_SLIGHT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
style = CAIRO_HINT_STYLE_MEDIUM;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
style = CAIRO_HINT_STYLE_FULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cairo_font_options_set_hint_metrics(options, metrics);
|
||||||
|
cairo_font_options_set_hint_style(options, style);
|
||||||
|
|
||||||
|
if ((subpixel = [ud integerForKey: @"back-art-subpixel-text"]))
|
||||||
|
{
|
||||||
|
cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
|
||||||
|
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_RGB);
|
||||||
|
|
||||||
|
if (subpixel == 2)
|
||||||
|
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_BGR);
|
||||||
|
}
|
||||||
|
|
||||||
_scaled = cairo_scaled_font_create(face, &font_matrix, &ctm, options);
|
_scaled = cairo_scaled_font_create(face, &font_matrix, &ctm, options);
|
||||||
cairo_font_options_destroy(options);
|
cairo_font_options_destroy(options);
|
||||||
|
@ -159,15 +202,38 @@
|
||||||
|
|
||||||
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
|
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
|
||||||
{
|
{
|
||||||
/* FIXME: There is no proper way to determine with the toy font API,
|
BOOL val = NO;
|
||||||
whether a glyph is supported or not. We will just ignore ligatures
|
|
||||||
and report all other glyph as existing.
|
if (_scaled)
|
||||||
return !NSEqualSizes([self advancementForGlyph: glyph], NSZeroSize);
|
{
|
||||||
*/
|
FT_Face face = cairo_ft_scaled_font_lock_face(_scaled);
|
||||||
if ((glyph >= 0xFB00) && (glyph <= 0xFB05))
|
if (FT_Get_Char_Index (face, glyph) != 0)
|
||||||
return NO;
|
{
|
||||||
else
|
val = YES;
|
||||||
return YES;
|
}
|
||||||
|
|
||||||
|
cairo_ft_scaled_font_unlock_face(_scaled);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSGlyph) glyphWithName: (NSString *)glyphName
|
||||||
|
{
|
||||||
|
NSGlyph val = NSNullGlyph;
|
||||||
|
FT_String *name = (FT_String *)[glyphName UTF8String];
|
||||||
|
|
||||||
|
if (_scaled)
|
||||||
|
{
|
||||||
|
FT_Face face = cairo_ft_scaled_font_lock_face(_scaled);
|
||||||
|
if (FT_Has_PS_Glyph_Names(face))
|
||||||
|
{
|
||||||
|
val = (NSGlyph) FT_Get_Name_Index(face, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_ft_scaled_font_unlock_face(_scaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -241,6 +307,12 @@ BOOL _cairo_extents_for_NSGlyph(cairo_scaled_font_t *scaled_font, NSGlyph glyph,
|
||||||
return NSZeroRect;
|
return NSZeroRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) displayName
|
||||||
|
{
|
||||||
|
return [_faceInfo displayName];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (CGFloat) widthOfString: (NSString *)string
|
- (CGFloat) widthOfString: (NSString *)string
|
||||||
{
|
{
|
||||||
cairo_text_extents_t ctext;
|
cairo_text_extents_t ctext;
|
||||||
|
|
|
@ -67,6 +67,39 @@
|
||||||
return _familyName;
|
return _familyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) displayName
|
||||||
|
{
|
||||||
|
char *fcname;
|
||||||
|
|
||||||
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
|
char *fcpsname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
If fullname && fullname != psname, use fullname as displayname.
|
||||||
|
This works around some weird Adobe OpenType fonts which contain their
|
||||||
|
PostScript name in their "human-readable name" field.
|
||||||
|
|
||||||
|
So, set the fullname as displayName (now AKA VisibleName) only
|
||||||
|
if it's not the same as whatever the postscript name is.
|
||||||
|
*/
|
||||||
|
if (FcPatternGetString(_pattern, FC_FULLNAME, 0, (FcChar8 **)&fcname) == FcResultMatch
|
||||||
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
|
&& FcPatternGetString(_pattern, FC_POSTSCRIPT_NAME, 0, (FcChar8 **)&fcpsname) == FcResultMatch
|
||||||
|
&& strcmp (fcpsname, fcname)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return [NSString stringWithUTF8String: fcname];
|
||||||
|
}
|
||||||
|
else if (FcPatternGetString(_pattern, FC_STYLE, 0, (FcChar8 **)&fcname) == FcResultMatch)
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat: @"%@ %@", _familyName,
|
||||||
|
[NSString stringWithUTF8String: fcname]];
|
||||||
|
}
|
||||||
|
return _familyName;
|
||||||
|
}
|
||||||
|
|
||||||
- (int) weight
|
- (int) weight
|
||||||
{
|
{
|
||||||
return _weight;
|
return _weight;
|
||||||
|
|
|
@ -53,6 +53,87 @@
|
||||||
#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_BLACK
|
#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_BLACK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static float
|
||||||
|
convertWeight (int fcWeight, int bottomValue, int topValue)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This is the distance between topValue and bottomValue expressed as a
|
||||||
|
fraction between zero and one. We do this to express the range of
|
||||||
|
fontconfig font weights in a useful manner.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fcWeight <= bottomValue)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else if (fcWeight >= topValue)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (float) (fcWeight - bottomValue) * (1.0f / (topValue - bottomValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSComparisonResult
|
||||||
|
sortFontFacesArray(id fontArr1, id fontArr2, void *context)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Order of array:
|
||||||
|
0: Font name
|
||||||
|
1: Font style
|
||||||
|
2: Font weight
|
||||||
|
3: Font traits
|
||||||
|
*/
|
||||||
|
NSString *style1 = [fontArr1 objectAtIndex: 1];
|
||||||
|
NSString *style2 = [fontArr2 objectAtIndex: 1];
|
||||||
|
float weight1 = [[fontArr1 objectAtIndex: 2] floatValue];
|
||||||
|
float weight2 = [[fontArr2 objectAtIndex: 2] floatValue];
|
||||||
|
unsigned int traits1 = [[fontArr1 objectAtIndex: 3] unsignedIntValue];
|
||||||
|
unsigned int traits2 = [[fontArr2 objectAtIndex: 3] unsignedIntValue];
|
||||||
|
|
||||||
|
// order first by weight
|
||||||
|
if (weight1 < weight2)
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if (weight1 > weight2)
|
||||||
|
return NSOrderedDescending;
|
||||||
|
|
||||||
|
// Italic next
|
||||||
|
if ((traits1 & NSItalicFontMask) < (traits2 & NSItalicFontMask))
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ((traits1 & NSItalicFontMask) > (traits2 & NSItalicFontMask))
|
||||||
|
return NSOrderedDescending;
|
||||||
|
|
||||||
|
// now do condensed
|
||||||
|
if ((traits1 & NSCondensedFontMask) < (traits2 & NSCondensedFontMask))
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ((traits1 & NSCondensedFontMask) > (traits2 & NSCondensedFontMask))
|
||||||
|
return NSOrderedDescending;
|
||||||
|
// ...and expanded
|
||||||
|
if ((traits1 & NSExpandedFontMask) < (traits2 & NSExpandedFontMask))
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ((traits1 & NSExpandedFontMask) > (traits2 & NSExpandedFontMask))
|
||||||
|
return NSOrderedDescending;
|
||||||
|
|
||||||
|
// Special case: "Regular" sorts before non-Regular, for many reasons.
|
||||||
|
if ([style1 isEqualToString: @"Regular"] && ![style2 isEqualToString: @"Regular"])
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ([style2 isEqualToString: @"Regular"] && ![style1 isEqualToString: @"Regular"])
|
||||||
|
return NSOrderedDescending;
|
||||||
|
if ([style1 isEqualToString: @"Normal"] && ![style2 isEqualToString: @"Normal"])
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ([style2 isEqualToString: @"Normal"] && ![style1 isEqualToString: @"Normal"])
|
||||||
|
return NSOrderedDescending;
|
||||||
|
if ([style1 isEqualToString: @"Roman"] && ![style2 isEqualToString: @"Roman"])
|
||||||
|
return NSOrderedAscending;
|
||||||
|
if ([style2 isEqualToString: @"Roman"] && ![style1 isEqualToString: @"Roman"])
|
||||||
|
return NSOrderedDescending;
|
||||||
|
|
||||||
|
// Otherwise, alphabetize
|
||||||
|
return [style1 compare: style2];
|
||||||
|
}
|
||||||
|
|
||||||
@implementation FCFontEnumerator
|
@implementation FCFontEnumerator
|
||||||
|
|
||||||
NSMutableDictionary * __allFonts;
|
NSMutableDictionary * __allFonts;
|
||||||
|
@ -78,14 +159,21 @@ NSMutableDictionary * __allFonts;
|
||||||
// Make a GNUstep style font descriptor from a FcPattern
|
// Make a GNUstep style font descriptor from a FcPattern
|
||||||
static NSArray *faFromFc(FcPattern *pat)
|
static NSArray *faFromFc(FcPattern *pat)
|
||||||
{
|
{
|
||||||
int weight, slant, spacing, nsweight;
|
int weight, slant, spacing, width;
|
||||||
|
float nsweight;
|
||||||
unsigned int nstraits = 0;
|
unsigned int nstraits = 0;
|
||||||
char *family;
|
char *fcfamily, *fcstyle;
|
||||||
NSMutableString *name, *style;
|
NSMutableString *name, *family, *style;
|
||||||
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
|
char *fcname;
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
FT_Face ftface = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &weight) != FcResultMatch
|
if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &weight) != FcResultMatch
|
||||||
|| FcPatternGetInteger(pat, FC_SLANT, 0, &slant) != FcResultMatch
|
|| FcPatternGetInteger(pat, FC_SLANT, 0, &slant) != FcResultMatch
|
||||||
|| FcPatternGetString(pat, FC_FAMILY, 0, (FcChar8 **)&family)
|
|| FcPatternGetString(pat, FC_FAMILY, 0, (FcChar8 **)&fcfamily)
|
||||||
!= FcResultMatch)
|
!= FcResultMatch)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
|
@ -93,35 +181,135 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
if (spacing==FC_MONO || spacing==FC_CHARCELL)
|
if (spacing==FC_MONO || spacing==FC_CHARCELL)
|
||||||
nstraits |= NSFixedPitchFontMask;
|
nstraits |= NSFixedPitchFontMask;
|
||||||
|
|
||||||
name = [NSMutableString stringWithCapacity: 100];
|
/*
|
||||||
style = [NSMutableString stringWithCapacity: 100];
|
This code will allow us to access TrueType/OpenType font tables from
|
||||||
[name appendString: [NSString stringWithUTF8String: family]];
|
fontconfig. If we want to implement features like the so-called "OS/2"
|
||||||
|
table which contains typographic family info ("give me a list of 'script'
|
||||||
|
fonts with slab serifs") and stuff like the font's correct typographic
|
||||||
|
line height and its xHeight, this is where we get that info.
|
||||||
|
|
||||||
switch (weight)
|
For more information, see http://www.microsoft.com/typography/otspec/
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
if (FcPatternGetFTFace (pat, FC_FT_FACE, 0, &ftface) == FcResultMatch)
|
||||||
{
|
{
|
||||||
case FC_WEIGHT_LIGHT:
|
// we got a FreeType face now, mwahaha.
|
||||||
[style appendString: @"Light"];
|
TT_Header *head = FT_Get_Sfnt_Table (ftface, FT_SFNT_HEAD);
|
||||||
nsweight = 3;
|
TT_OS2 *os2 = FT_Get_Sfnt_Table (ftface, FT_SFNT_OS2);
|
||||||
break;
|
TT_HoriHeader *hhea = FT_Get_Sfnt_Table (ftface, FT_SFNT_HHEA);
|
||||||
case FC_WEIGHT_MEDIUM:
|
TT_Postscript *post = FT_Get_Sfnt_Table (ftface, FT_SFNT_POST);
|
||||||
nsweight = 6;
|
}
|
||||||
break;
|
#endif
|
||||||
case FC_WEIGHT_DEMIBOLD:
|
|
||||||
[style appendString: @"Demibold"];
|
name = [NSMutableString stringWithCapacity: 100];
|
||||||
nsweight = 7;
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
break;
|
if (FcPatternGetString(pat, FC_POSTSCRIPT_NAME, 0, (FcChar8 **)&fcname) == FcResultMatch)
|
||||||
case FC_WEIGHT_BOLD:
|
[name appendString: [NSMutableString stringWithUTF8String: fcname]];
|
||||||
[style appendString: @"Bold"];
|
#endif
|
||||||
nsweight = 9;
|
|
||||||
nstraits |= NSBoldFontMask;
|
family = [NSMutableString stringWithUTF8String: fcfamily];
|
||||||
break;
|
style = [NSMutableString stringWithCapacity: 100];
|
||||||
case FC_WEIGHT_BLACK:
|
|
||||||
[style appendString: @"Black"];
|
if (weight < FC_WEIGHT_ULTRALIGHT)
|
||||||
nsweight = 12;
|
{
|
||||||
nstraits |= NSBoldFontMask;
|
[style appendString: @"Thin"];
|
||||||
break;
|
nsweight = 1 + convertWeight (weight, FC_WEIGHT_THIN, FC_WEIGHT_ULTRALIGHT);
|
||||||
default:
|
}
|
||||||
nsweight = 6;
|
else if (weight < FC_WEIGHT_LIGHT)
|
||||||
|
{
|
||||||
|
[style appendString: @"Ultralight"];
|
||||||
|
nsweight = 2 + convertWeight (weight, FC_WEIGHT_ULTRALIGHT, FC_WEIGHT_LIGHT);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_BOOK)
|
||||||
|
{
|
||||||
|
[style appendString: @"Light"];
|
||||||
|
nsweight = 3 + convertWeight (weight, FC_WEIGHT_LIGHT, FC_WEIGHT_BOOK);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_REGULAR)
|
||||||
|
{
|
||||||
|
[style appendString: @"Book"];
|
||||||
|
nsweight = 4 + convertWeight (weight, FC_WEIGHT_BOOK, FC_WEIGHT_REGULAR);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_MEDIUM)
|
||||||
|
{
|
||||||
|
nsweight = 5 + convertWeight (weight, FC_WEIGHT_REGULAR, FC_WEIGHT_MEDIUM);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_DEMIBOLD)
|
||||||
|
{
|
||||||
|
[style appendString: @"Medium"];
|
||||||
|
nsweight = 6 + convertWeight (weight, FC_WEIGHT_MEDIUM, FC_WEIGHT_DEMIBOLD);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_BOLD)
|
||||||
|
{
|
||||||
|
[style appendString: @"Demibold"];
|
||||||
|
nsweight = 7 + convertWeight (weight, FC_WEIGHT_DEMIBOLD, FC_WEIGHT_BOLD);
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_ULTRABOLD)
|
||||||
|
{
|
||||||
|
[style appendString: @"Bold"];
|
||||||
|
nsweight = 9 + convertWeight (weight, FC_WEIGHT_BOLD, FC_WEIGHT_ULTRABOLD);
|
||||||
|
nstraits |= NSBoldFontMask;
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_BLACK)
|
||||||
|
{
|
||||||
|
[style appendString: @"Ultrabold"];
|
||||||
|
nsweight = 11 + convertWeight (weight, FC_WEIGHT_ULTRABOLD, FC_WEIGHT_BLACK);
|
||||||
|
nstraits |= NSBoldFontMask;
|
||||||
|
}
|
||||||
|
else if (weight < FC_WEIGHT_ULTRABLACK)
|
||||||
|
{
|
||||||
|
[style appendString: @"Black"];
|
||||||
|
nsweight = 12 + convertWeight (weight, FC_WEIGHT_BLACK, FC_WEIGHT_ULTRABLACK);
|
||||||
|
nstraits |= NSBoldFontMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[style appendString: @"Ultrablack"];
|
||||||
|
nsweight = 13 + convertWeight (weight, FC_WEIGHT_ULTRABLACK, FC_WEIGHT_ULTRABLACK + 20);
|
||||||
|
nstraits |= NSBoldFontMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcPatternGetInteger(pat, FC_WIDTH, 0, &width) == FcResultMatch)
|
||||||
|
{
|
||||||
|
if (width < FC_WIDTH_EXTRACONDENSED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Ultracondensed"];
|
||||||
|
nstraits |= NSCondensedFontMask;
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_CONDENSED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Extracondensed"];
|
||||||
|
nstraits |= NSCondensedFontMask;
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_SEMICONDENSED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Condensed"];
|
||||||
|
nstraits |= NSCondensedFontMask;
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_SEMIEXPANDED)
|
||||||
|
{
|
||||||
|
// do nothing, this is "regular"
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_EXPANDED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Semiexpanded"];
|
||||||
|
nstraits |= NSExpandedFontMask;
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_EXTRAEXPANDED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Expanded"];
|
||||||
|
nstraits |= NSExpandedFontMask;
|
||||||
|
}
|
||||||
|
else if (width < FC_WIDTH_ULTRAEXPANDED)
|
||||||
|
{
|
||||||
|
[style appendString: @"Extraexpanded"];
|
||||||
|
nstraits |= NSExpandedFontMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[style appendString: @"Ultraexpanded"];
|
||||||
|
nstraits |= NSExpandedFontMask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (slant)
|
switch (slant)
|
||||||
|
@ -138,19 +326,29 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([style length] > 0)
|
if (![name length]) // no psname
|
||||||
{
|
{
|
||||||
[name appendString: @"-"];
|
NSDebugLLog(@"NSFont", @"Warning: synthesizing PSName for '%@ %@'", family, style);
|
||||||
[name appendString: style];
|
[name appendString: family];
|
||||||
}
|
if ([style length] > 0)
|
||||||
else
|
{
|
||||||
{
|
[name appendString: @"-"];
|
||||||
[style appendString: @"Roman"];
|
[name appendString: style];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (![style length])
|
||||||
|
{
|
||||||
|
[style setString: @"Regular"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FcPatternGetString(pat, FC_STYLE, 0, (FcChar8 **)&fcstyle) == FcResultMatch)
|
||||||
|
style = [NSString stringWithUTF8String: fcstyle];
|
||||||
|
|
||||||
|
// NSLog (@"family: %@, style: %s/%@", name, fcstyle, style);
|
||||||
return [NSArray arrayWithObjects: name,
|
return [NSArray arrayWithObjects: name,
|
||||||
style,
|
style,
|
||||||
[NSNumber numberWithInt: nsweight],
|
[NSNumber numberWithFloat: nsweight],
|
||||||
[NSNumber numberWithUnsignedInt: nstraits],
|
[NSNumber numberWithUnsignedInt: nstraits],
|
||||||
nil];
|
nil];
|
||||||
}
|
}
|
||||||
|
@ -164,7 +362,11 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
Class faceInfoClass = [[self class] faceInfoClass];
|
Class faceInfoClass = [[self class] faceInfoClass];
|
||||||
|
|
||||||
FcPattern *pat = FcPatternCreate();
|
FcPattern *pat = FcPatternCreate();
|
||||||
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT,
|
FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FULLNAME,
|
||||||
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
|
FC_POSTSCRIPT_NAME,
|
||||||
|
#endif
|
||||||
|
FC_SLANT, FC_WEIGHT, FC_WIDTH,
|
||||||
FC_SPACING, NULL);
|
FC_SPACING, NULL);
|
||||||
FcFontSet *fs = FcFontList(NULL, pat, os);
|
FcFontSet *fs = FcFontList(NULL, pat, os);
|
||||||
|
|
||||||
|
@ -189,23 +391,27 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
|
|
||||||
familyString = [NSString stringWithUTF8String: family];
|
familyString = [NSString stringWithUTF8String: family];
|
||||||
familyArray = [fcxft_allFontFamilies objectForKey: familyString];
|
familyArray = [fcxft_allFontFamilies objectForKey: familyString];
|
||||||
|
|
||||||
if (familyArray == nil)
|
if (familyArray == nil)
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"NSFont", @"Found font family %@", familyString);
|
NSDebugLLog(@"NSFont", @"Found font family %@", familyString);
|
||||||
familyArray = [[NSMutableArray alloc] init];
|
familyArray = [NSMutableArray array];
|
||||||
[fcxft_allFontFamilies setObject: familyArray
|
[fcxft_allFontFamilies setObject: familyArray
|
||||||
forKey: familyString];
|
forKey: familyString];
|
||||||
RELEASE(familyArray);
|
|
||||||
}
|
}
|
||||||
NSDebugLLog(@"NSFont", @"fc enumerator: adding font: %@", name);
|
|
||||||
[familyArray addObject: fontArray];
|
if (![fcxft_allFontNames containsObject: name])
|
||||||
[fcxft_allFontNames addObject: name];
|
{
|
||||||
aFont = [[faceInfoClass alloc] initWithfamilyName: familyString
|
NSDebugLLog(@"NSFont", @"fc enumerator: adding font: %@", name);
|
||||||
weight: [[fontArray objectAtIndex: 2] intValue]
|
[familyArray addObject: fontArray];
|
||||||
traits: [[fontArray objectAtIndex: 3] unsignedIntValue]
|
[fcxft_allFontNames addObject: name];
|
||||||
pattern: fs->fonts[i]];
|
aFont = [[faceInfoClass alloc] initWithfamilyName: familyString
|
||||||
[fcxft_allFonts setObject: aFont forKey: name];
|
weight: [[fontArray objectAtIndex: 2] floatValue]
|
||||||
RELEASE(aFont);
|
traits: [[fontArray objectAtIndex: 3] unsignedIntValue]
|
||||||
|
pattern: fs->fonts[i]];
|
||||||
|
[fcxft_allFonts setObject: aFont forKey: name];
|
||||||
|
RELEASE(aFont);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,61 +420,76 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
allFontNames = fcxft_allFontNames;
|
allFontNames = fcxft_allFontNames;
|
||||||
allFontFamilies = fcxft_allFontFamilies;
|
allFontFamilies = fcxft_allFontFamilies;
|
||||||
__allFonts = fcxft_allFonts;
|
__allFonts = fcxft_allFonts;
|
||||||
|
|
||||||
|
// Sort font families
|
||||||
|
{
|
||||||
|
NSComparisonResult (*fontSort) (id, id, void *) = sortFontFacesArray;
|
||||||
|
NSEnumerator *e = [allFontFamilies keyEnumerator];
|
||||||
|
id key;
|
||||||
|
while ((key = [e nextObject]))
|
||||||
|
{
|
||||||
|
[[allFontFamilies objectForKey: key] sortUsingFunction:fontSort context:NULL];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) defaultSystemFontName
|
- (NSString *) defaultSystemFontName
|
||||||
{
|
{
|
||||||
if ([allFontNames containsObject: @"Bitstream Vera Sans"])
|
if ([allFontNames containsObject: @"DejaVuSans"])
|
||||||
{
|
{
|
||||||
return @"Bitstream Vera Sans";
|
return @"DejaVuSans";
|
||||||
|
}
|
||||||
|
if ([allFontNames containsObject: @"BitstreamVeraSans-Roman"])
|
||||||
|
{
|
||||||
|
return @"BitstreamVeraSans-Roman";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"FreeSans"])
|
if ([allFontNames containsObject: @"FreeSans"])
|
||||||
{
|
{
|
||||||
return @"FreeSans";
|
return @"FreeSans";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"DejaVu Sans"])
|
|
||||||
{
|
|
||||||
return @"DejaVu Sans";
|
|
||||||
}
|
|
||||||
if ([allFontNames containsObject: @"Tahoma"])
|
if ([allFontNames containsObject: @"Tahoma"])
|
||||||
{
|
{
|
||||||
return @"Tahoma";
|
return @"Tahoma";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"Arial"])
|
if ([allFontNames containsObject: @"ArialMT"])
|
||||||
{
|
{
|
||||||
return @"Arial";
|
return @"ArialMT";
|
||||||
}
|
}
|
||||||
return @"Helvetica";
|
return @"Helvetica";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) defaultBoldSystemFontName
|
- (NSString *) defaultBoldSystemFontName
|
||||||
{
|
{
|
||||||
if ([allFontNames containsObject: @"Bitstream Vera Sans-Bold"])
|
if ([allFontNames containsObject: @"DejaVuSans-Bold"])
|
||||||
{
|
{
|
||||||
return @"Bitstream Vera Sans-Bold";
|
return @"DejaVuSans-Bold";
|
||||||
|
}
|
||||||
|
if ([allFontNames containsObject: @"BitstreamVeraSans-Bold"])
|
||||||
|
{
|
||||||
|
return @"BitstreamVeraSans-Bold";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"FreeSans-Bold"])
|
if ([allFontNames containsObject: @"FreeSans-Bold"])
|
||||||
{
|
{
|
||||||
return @"FreeSans-Bold";
|
return @"FreeSans-Bold";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"DejaVu Sans-Bold"])
|
|
||||||
{
|
|
||||||
return @"DejaVu Sans-Bold";
|
|
||||||
}
|
|
||||||
if ([allFontNames containsObject: @"Tahoma-Bold"])
|
if ([allFontNames containsObject: @"Tahoma-Bold"])
|
||||||
{
|
{
|
||||||
return @"Tahoma-Bold";
|
return @"Tahoma-Bold";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"Arial-Bold"])
|
if ([allFontNames containsObject: @"Arial-BoldMT"])
|
||||||
{
|
{
|
||||||
return @"Arial-Bold";
|
return @"Arial-BoldMT";
|
||||||
}
|
}
|
||||||
return @"Helvetica-Bold";
|
return @"Helvetica-Bold";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) defaultFixedPitchFontName
|
- (NSString *) defaultFixedPitchFontName
|
||||||
{
|
{
|
||||||
if ([allFontNames containsObject: @"Bitstream Vera Sans Mono"])
|
if ([allFontNames containsObject: @"DejaVuSansMono"])
|
||||||
|
{
|
||||||
|
return @"DejaVuSansMono";
|
||||||
|
}
|
||||||
|
if ([allFontNames containsObject: @"BitstreamVeraSansMono-Roman"])
|
||||||
{
|
{
|
||||||
return @"Bitstream Vera Sans Mono";
|
return @"Bitstream Vera Sans Mono";
|
||||||
}
|
}
|
||||||
|
@ -276,13 +497,9 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
{
|
{
|
||||||
return @"FreeMono";
|
return @"FreeMono";
|
||||||
}
|
}
|
||||||
if ([allFontNames containsObject: @"DejaVu Sans Mono"])
|
if ([allFontNames containsObject: @"CourierNewPSMT"])
|
||||||
{
|
{
|
||||||
return @"DejaVu Sans Mono";
|
return @"CourierNewPSMT";
|
||||||
}
|
|
||||||
if ([allFontNames containsObject: @"Courier New"])
|
|
||||||
{
|
|
||||||
return @"Courier New";
|
|
||||||
}
|
}
|
||||||
return @"Courier";
|
return @"Courier";
|
||||||
}
|
}
|
||||||
|
@ -347,18 +564,19 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@implementation FontconfigPatternGenerator
|
@implementation FontconfigPatternGenerator
|
||||||
|
|
||||||
- (void)addName: (NSString*)name
|
- (void)addName: (NSString*)name
|
||||||
{
|
{
|
||||||
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
|
FcPatternAddString(_pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)[name UTF8String]);
|
||||||
|
#else
|
||||||
// FIXME: Fontconfig ignores PostScript names of fonts; we need
|
// FIXME: Fontconfig ignores PostScript names of fonts; we need
|
||||||
// https://bugs.freedesktop.org/show_bug.cgi?id=18095 fixed.
|
// https://bugs.freedesktop.org/show_bug.cgi?id=18095 fixed.
|
||||||
|
|
||||||
// This is a heuristic to try to 'parse' a PostScript font name,
|
// This is a heuristic to try to 'parse' a PostScript font name,
|
||||||
// however, since they are just unique identifiers for fonts and
|
// however, since they are just unique identifiers for fonts and
|
||||||
// don't need to follow any naming convention, this may fail
|
// don't need to follow any naming convention, this may fail
|
||||||
|
|
||||||
NSRange dash = [name rangeOfString: @"-"];
|
NSRange dash = [name rangeOfString: @"-"];
|
||||||
if (dash.location == NSNotFound)
|
if (dash.location == NSNotFound)
|
||||||
{
|
{
|
||||||
|
@ -410,6 +628,7 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_EXPANDED);
|
FcPatternAddInteger(_pat, FC_WIDTH, FC_WIDTH_EXPANDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addVisibleName: (NSString*)name
|
- (void)addVisibleName: (NSString*)name
|
||||||
|
@ -467,7 +686,7 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
}
|
}
|
||||||
if (symTraits & NSFontVerticalTrait)
|
if (symTraits & NSFontVerticalTrait)
|
||||||
{
|
{
|
||||||
// FIXME: What is this supposed to mean?
|
// Fontconfig can't express this (it means sideways letters)
|
||||||
}
|
}
|
||||||
if (symTraits & NSFontUIOptimizedTrait)
|
if (symTraits & NSFontUIOptimizedTrait)
|
||||||
{
|
{
|
||||||
|
@ -683,20 +902,27 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
|
|
||||||
- (NSString*)readNameFromPattern: (FcPattern*)pat
|
- (NSString*)readNameFromPattern: (FcPattern*)pat
|
||||||
{
|
{
|
||||||
// FIXME: Hack which generates a PostScript-style name from the
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
// family name and style
|
NSString *name = [self readFontconfigString: FC_POSTSCRIPT_NAME fromPattern: pat];
|
||||||
|
#endif
|
||||||
NSString *family = [self readFontconfigString: FC_FAMILY fromPattern: pat];
|
NSString *family = [self readFontconfigString: FC_FAMILY fromPattern: pat];
|
||||||
NSString *style = [self readFontconfigString: FC_STYLE fromPattern: pat];
|
NSString *style = [self readFontconfigString: FC_STYLE fromPattern: pat];
|
||||||
if (style)
|
|
||||||
{
|
#ifdef FC_POSTSCRIPT_NAME
|
||||||
return [NSString stringWithFormat: @"%@-%@", family, style];
|
if (name)
|
||||||
}
|
return name;
|
||||||
else
|
else
|
||||||
{
|
#endif
|
||||||
return family;
|
if (style)
|
||||||
}
|
{
|
||||||
|
return [NSString stringWithFormat: @"%@-%@", family, style];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return family;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)readVisibleNameFromPattern: (FcPattern*)pat
|
- (NSString*)readVisibleNameFromPattern: (FcPattern*)pat
|
||||||
{
|
{
|
||||||
// FIXME: try to get the localized one
|
// FIXME: try to get the localized one
|
||||||
|
@ -721,7 +947,7 @@ static NSArray *faFromFc(FcPattern *pat)
|
||||||
int value;
|
int value;
|
||||||
if (FcResultMatch == FcPatternGetInteger(pat, FC_SLANT, 0, &value))
|
if (FcResultMatch == FcPatternGetInteger(pat, FC_SLANT, 0, &value))
|
||||||
{
|
{
|
||||||
if (value == FC_SLANT_ITALIC)
|
if (value > FC_SLANT_ROMAN)
|
||||||
{
|
{
|
||||||
symTraits |= NSFontItalicTrait;
|
symTraits |= NSFontItalicTrait;
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,6 +149,11 @@
|
||||||
return NSZeroRect;
|
return NSZeroRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) displayName
|
||||||
|
{
|
||||||
|
return [_faceInfo displayName];
|
||||||
|
}
|
||||||
|
|
||||||
- (CGFloat) widthOfString: (NSString *)string
|
- (CGFloat) widthOfString: (NSString *)string
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
|
|
Loading…
Reference in a new issue