mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-24 04:11:28 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@17322 72102866-910b-0410-8b05-ffd578937521
508 lines
12 KiB
Objective-C
508 lines
12 KiB
Objective-C
/*
|
|
XGFontSetFontInfo.m
|
|
|
|
NSFont helper for GNUstep X/GPS Backend
|
|
|
|
Author: Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
|
|
Date: July 2003
|
|
|
|
*/
|
|
|
|
#include "x11/XGServer.h"
|
|
#include "xlib/XGPrivate.h"
|
|
#include "xlib/XGFontSetFontInfo.h"
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
#define XSERVER [XGServer currentXDisplay]
|
|
|
|
typedef struct _UTF8Str {
|
|
char *data;
|
|
int size;
|
|
} UTF8Str;
|
|
|
|
#define UTF8StrData(x) ((x)->data)
|
|
#define UTF8StrSize(x) ((x)->size)
|
|
#define UTF8StrFree(x) \
|
|
do { \
|
|
if ((x)->data) \
|
|
{ \
|
|
free((x)->data); \
|
|
(x)->data = NULL; \
|
|
(x)->size = 0; \
|
|
} \
|
|
} while (0)
|
|
#define UTF8StrAlloc(x, length) \
|
|
do { (x)->data = malloc(6 * (length)); } while (0)
|
|
#define UTF8StrUsable(x) ((x)->data != NULL)
|
|
|
|
|
|
// Forward declarations
|
|
static BOOL load_font_set(Display *dpy, const char *given_font_name,
|
|
XFontSet *font_set,
|
|
XFontStruct ***fonts, int *num_fonts);
|
|
static BOOL glyphs2utf8(const NSGlyph* glyphs, int length, UTF8Str* ustr);
|
|
static BOOL char_struct_for_glyph(NSGlyph glyph, XFontSet font_set,
|
|
XFontStruct **fonts, int num_fonts,
|
|
XCharStruct *cs);
|
|
|
|
|
|
#if 0 // Commented out till the implementation completes.
|
|
// ----------------------------------------------------------------------------
|
|
// XGFontSetEnumerator
|
|
// ----------------------------------------------------------------------------
|
|
@implementation XGFontSetEnumerator : GSFontEnumerator
|
|
|
|
- (void) enumerateFontsAndFamilies
|
|
{ }
|
|
|
|
@end // XGFontSetEnumerator : GSFontEnumerator
|
|
#endif // #if 0
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// XGFontSetFontInfo
|
|
// ----------------------------------------------------------------------------
|
|
@implementation XGFontSetFontInfo : GSFontInfo
|
|
|
|
- (id) initWithFontName: (NSString *)name
|
|
matrix: (const float *)fmatrix
|
|
screenFont: (BOOL)screenFont
|
|
{
|
|
Display *dpy;
|
|
XFontSet font_set;
|
|
XFontStruct **fonts;
|
|
XFontStruct *base;
|
|
int num_fonts;
|
|
|
|
if (screenFont)
|
|
{
|
|
RELEASE(self);
|
|
return nil;
|
|
}
|
|
if (!name || [name length] == 0 || (dpy = XSERVER) == NULL)
|
|
{
|
|
RELEASE(self);
|
|
return nil;
|
|
}
|
|
|
|
if (!load_font_set(dpy, [XGXFontName(name, fmatrix[0]) cString],
|
|
&font_set, &fonts, &num_fonts))
|
|
{
|
|
RELEASE(self);
|
|
return nil;
|
|
}
|
|
base = fonts[0];
|
|
|
|
// GSFontInfo part
|
|
[super init];
|
|
ASSIGN(fontName, name);
|
|
ASSIGN(familyName, XGFontFamily(dpy, base));
|
|
memcpy(matrix, fmatrix, sizeof(matrix));
|
|
italicAngle = 0;
|
|
underlinePosition = 0;
|
|
underlineThickness = 0;
|
|
capHeight = 0;
|
|
xHeight = 0;
|
|
descender = -base->descent;
|
|
ascender = base->ascent;
|
|
maximumAdvancement =
|
|
NSMakeSize(base->max_bounds.width,
|
|
base->max_bounds.ascent + base->max_bounds.descent);
|
|
minimumAdvancement = NSMakeSize(0, 0);
|
|
ASSIGN(encodingScheme, @"");
|
|
mostCompatibleStringEncoding = NSASCIIStringEncoding;
|
|
fontBBox =
|
|
NSMakeRect(base->min_bounds.lbearing,
|
|
-base->max_bounds.ascent,
|
|
base->max_bounds.rbearing - base->max_bounds.lbearing,
|
|
base->max_bounds.ascent + base->max_bounds.descent);
|
|
isFixedPitch = XGFontIsFixedPitch(dpy, base);
|
|
isBaseFont = NO;
|
|
weight = XGWeightOfFont(dpy, base);
|
|
traits = XGTraitsOfFont(dpy, base);
|
|
|
|
// XGFontSetFontInfo part
|
|
_font_set = font_set;
|
|
_fonts = fonts;
|
|
_num_fonts = num_fonts;
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
if (_font_set)
|
|
{
|
|
XFreeFontSet(XSERVER, _font_set);
|
|
_font_set = NULL;
|
|
}
|
|
}
|
|
|
|
- (NSSize) advancementForGlyph: (NSGlyph)glyph
|
|
{
|
|
XCharStruct cs;
|
|
|
|
if (!char_struct_for_glyph(glyph, _font_set, _fonts, _num_fonts, &cs))
|
|
{
|
|
cs.width = _fonts[0]->max_bounds.width;
|
|
}
|
|
return NSMakeSize((float)cs.width, 0);
|
|
}
|
|
|
|
- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
|
|
{
|
|
XCharStruct cs;
|
|
|
|
if (!char_struct_for_glyph(glyph, _font_set, _fonts, _num_fonts, &cs))
|
|
{
|
|
return fontBBox;
|
|
}
|
|
return NSMakeRect((float)cs.lbearing, (float)-cs.descent,
|
|
(float)(cs.rbearing - cs.lbearing),
|
|
(float)(cs.ascent + cs.descent));
|
|
}
|
|
|
|
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
|
|
{
|
|
XCharStruct cs;
|
|
|
|
return char_struct_for_glyph(glyph, _font_set, _fonts, _num_fonts, &cs);
|
|
}
|
|
|
|
- (NSGlyph) glyphWithName: (NSString *)glyphName
|
|
{
|
|
KeySym k;
|
|
|
|
k = XStringToKeysym([glyphName cString]);
|
|
if (k == NoSymbol)
|
|
return 0;
|
|
else
|
|
return (NSGlyph)k;
|
|
}
|
|
|
|
- (void) drawGlyphs: (const NSGlyph *)glyphs
|
|
lenght: (int)len
|
|
onDisplay: (Display *)dpy
|
|
drawable: (Drawable)win
|
|
with: (GC)gc
|
|
at: (XPoint)xp
|
|
{
|
|
UTF8Str ustr;
|
|
|
|
if (glyphs2utf8(glyphs, len, &ustr))
|
|
{
|
|
Xutf8DrawString(dpy, win, _font_set, gc, xp.x, xp.y,
|
|
UTF8StrData(&ustr), UTF8StrSize(&ustr));
|
|
UTF8StrFree(&ustr);
|
|
}
|
|
}
|
|
|
|
- (float) widthOfGlyphs: (const NSGlyph *)glyphs
|
|
lenght: (int)len
|
|
{
|
|
UTF8Str ustr;
|
|
float val;
|
|
|
|
if (glyphs2utf8(glyphs, len, &ustr))
|
|
{
|
|
XRectangle logical;
|
|
|
|
Xutf8TextExtents(_font_set, UTF8StrData(&ustr), UTF8StrSize(&ustr),
|
|
NULL, &logical);
|
|
UTF8StrFree(&ustr);
|
|
val = logical.width;
|
|
}
|
|
else
|
|
{
|
|
val = 0.0;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
- (void) setActiveFor: (Display *)dpy
|
|
gc: (GC)gc
|
|
{
|
|
// Do nothing.
|
|
}
|
|
|
|
@end // XGFontSetFontInfo : GSFontInfo
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Static Functions
|
|
// ----------------------------------------------------------------------------
|
|
static BOOL
|
|
load_font_set(Display *dpy, const char *given_font_name,
|
|
XFontSet *font_set, XFontStruct ***fonts, int *num_fonts)
|
|
{
|
|
int i;
|
|
char xlfd[256];
|
|
#ifndef STATIC_BUFFER_IS_RELIABLE
|
|
char *p;
|
|
#endif
|
|
int xlfd_num_elms;
|
|
BOOL has_add_style;
|
|
char *xlfd_elms[14];
|
|
char base_font_name[256];
|
|
|
|
char **missing_charsets;
|
|
int num_missing_charsets;
|
|
char *def_string;
|
|
|
|
char **font_names;
|
|
int num_font_names;
|
|
XFontStruct **font_structs;
|
|
|
|
if (!dpy || !given_font_name)
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
strcpy(xlfd, given_font_name);
|
|
xlfd_num_elms = 14;
|
|
has_add_style = YES;
|
|
// Both of the following compilation branches, based on the switch
|
|
// 'STATIC_BUFFER_IS_RELIABLE', basically do the same thing. Because some
|
|
// people worry about making use of strtok(), the latter branch is used
|
|
// primarily unless the switch is explicitly defined somewhere. The former
|
|
// branch should document what the latter one does.
|
|
#ifdef STATIC_BUFFER_IS_RELIABLE
|
|
if (strstr(xlfd, "--"))
|
|
{
|
|
--xlfd_num_elms;
|
|
has_add_style = NO;
|
|
}
|
|
|
|
i = 0;
|
|
xlfd_elms[i++] = strtok(xlfd, "-");
|
|
while (i < xlfd_num_elms)
|
|
{
|
|
xlfd_elms[i++] = strtok(NULL, "-");
|
|
}
|
|
#else // 'STATIC_BUFFER_IS_RELIABLE' not defined
|
|
i = 0;
|
|
p = xlfd;
|
|
do
|
|
{
|
|
while (*p != '-')
|
|
++p;
|
|
*p = '\0';
|
|
if (*++p == '-') // The token is in the form of '--'.
|
|
{
|
|
*p++ = '\0';
|
|
--xlfd_num_elms;
|
|
has_add_style = NO;
|
|
}
|
|
xlfd_elms[i] = p;
|
|
}
|
|
while (++i < xlfd_num_elms && *p != '\0');
|
|
#endif // 'STATIC_BUFFER_IS_RELIABLE' not defined
|
|
|
|
// To let the X server determine a font set automatically, some elements
|
|
// of the XLFD should be replaced with the wild card.
|
|
//
|
|
// N.B. Rigorously speaking, to make use of proportional fonts, we need to
|
|
// define a mapping from NSGlyph to the XFontStruct's field 'per_char'.
|
|
// The property 'spacing' is set to "*" until such a mapping is given.
|
|
// (see also char_struct_for_glyph()).
|
|
if (has_add_style)
|
|
{
|
|
sprintf(base_font_name,
|
|
"-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
|
|
xlfd_elms[0], // foundry
|
|
"*", // family
|
|
xlfd_elms[2], // weight
|
|
xlfd_elms[3], // slant
|
|
xlfd_elms[4], // set width
|
|
xlfd_elms[5], // add style
|
|
xlfd_elms[6], // pixel size
|
|
xlfd_elms[7], // point size
|
|
xlfd_elms[8], // resolutionX
|
|
xlfd_elms[9], // resolutionY
|
|
"*", // spacing
|
|
xlfd_elms[11], // avg width
|
|
"*", // registry
|
|
"*" // encoding
|
|
);
|
|
}
|
|
else
|
|
{
|
|
sprintf(base_font_name,
|
|
"-%s-%s-%s-%s-%s--%s-%s-%s-%s-%s-%s-%s-%s",
|
|
xlfd_elms[0], // foundry
|
|
"*", // family
|
|
xlfd_elms[2], // weight
|
|
xlfd_elms[3], // slant
|
|
xlfd_elms[4], // set width
|
|
xlfd_elms[5], // pixel size
|
|
xlfd_elms[6], // point size
|
|
xlfd_elms[7], // resolutionX
|
|
xlfd_elms[8], // resolutionY
|
|
"*", // spacing
|
|
xlfd_elms[10], // avg width
|
|
"*", // registry
|
|
"*" // encoding
|
|
);
|
|
}
|
|
|
|
// N.B. def_string is owned by the X server: Don't release it.
|
|
missing_charsets = NULL;
|
|
num_missing_charsets = 0;
|
|
def_string = NULL;
|
|
*font_set = NULL;
|
|
*font_set = XCreateFontSet(dpy, base_font_name,
|
|
&missing_charsets,
|
|
&num_missing_charsets,
|
|
&def_string);
|
|
if (!*font_set)
|
|
{
|
|
NSLog(@"XGFontSetFontInfo: Can't create a font set\n");
|
|
return NO;
|
|
}
|
|
if (num_missing_charsets > 0)
|
|
{
|
|
for (i = 0; i < num_missing_charsets; ++i)
|
|
{
|
|
NSLog(@"XGFontSetFontInfo: Charset %s is not available\n",
|
|
missing_charsets[i]);
|
|
}
|
|
XFreeStringList(missing_charsets);
|
|
missing_charsets = NULL;
|
|
num_missing_charsets = 0;
|
|
}
|
|
|
|
// N.B. font_structs and font_names are owned by the X server: Don't
|
|
// release them.
|
|
num_font_names = 0;
|
|
font_structs = NULL;
|
|
font_names = NULL;
|
|
num_font_names = XFontsOfFontSet(*font_set, &font_structs, &font_names);
|
|
if (!num_font_names)
|
|
{
|
|
NSLog(@"XGFontSetFontInfo: "
|
|
@"Can't get any information from the font set\n");
|
|
return NO;
|
|
}
|
|
|
|
*fonts = font_structs;
|
|
*num_fonts = num_font_names;
|
|
|
|
return YES;
|
|
}
|
|
|
|
// N.B. Use UTF8StrFree() to release the space pointed to by 'ustr'.
|
|
static BOOL
|
|
glyphs2utf8(const NSGlyph* glyphs, int length, UTF8Str* ustr)
|
|
{
|
|
int i;
|
|
NSGlyph *g;
|
|
NSGlyph *end;
|
|
char *p;
|
|
|
|
if (!glyphs || !length)
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
UTF8StrAlloc(ustr, length);
|
|
if (!UTF8StrUsable(ustr))
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
p = UTF8StrData(ustr);
|
|
i = 0;
|
|
for (g = (NSGlyph *)glyphs, end = (NSGlyph *)glyphs + length; g < end; ++g)
|
|
{
|
|
if (*g < 0x00000080)
|
|
{
|
|
p[i++] = *g;
|
|
}
|
|
else if (*g < 0x00000800)
|
|
{
|
|
p[i++] = 0xc0 | ((*g >> 6) & 0x1f);
|
|
p[i++] = 0x80 | ( *g & 0x3f);
|
|
}
|
|
else if (*g < 0x00010000)
|
|
{
|
|
p[i++] = 0xe0 | ((*g >> 12) & 0x0f);
|
|
p[i++] = 0x80 | ((*g >> 6) & 0x3f);
|
|
p[i++] = 0x80 | ( *g & 0x3f);
|
|
}
|
|
else if (*g < 0x00200000)
|
|
{
|
|
p[i++] = 0xf0 | ((*g >> 18) & 0x07);
|
|
p[i++] = 0x80 | ((*g >> 12) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 6) & 0x3f);
|
|
p[i++] = 0x80 | ( *g & 0x3f);
|
|
}
|
|
else if (*g < 0x04000000)
|
|
{
|
|
p[i++] = 0xf8 | ((*g >> 24) & 0x03);
|
|
p[i++] = 0x80 | ((*g >> 18) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 12) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 6) & 0x3f);
|
|
p[i++] = 0x80 | ( *g & 0x3f);
|
|
}
|
|
else if (*g < 0x80000000)
|
|
{
|
|
p[i++] = 0xfc | ((*g >> 30) & 0x01);
|
|
p[i++] = 0x80 | ((*g >> 24) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 18) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 12) & 0x3f);
|
|
p[i++] = 0x80 | ((*g >> 6) & 0x3f);
|
|
p[i++] = 0x80 | ( *g & 0x3f);
|
|
}
|
|
else
|
|
{
|
|
// Out of range
|
|
UTF8StrFree(ustr);
|
|
return NO;
|
|
}
|
|
}
|
|
UTF8StrSize(ustr) = i;
|
|
|
|
return YES;
|
|
}
|
|
|
|
static BOOL
|
|
char_struct_for_glyph(NSGlyph glyph, XFontSet font_set,
|
|
XFontStruct **fonts, int num_fonts,
|
|
XCharStruct *cs)
|
|
{
|
|
UTF8Str utf8char;
|
|
|
|
if (glyphs2utf8(&glyph, 1, &utf8char))
|
|
{
|
|
XRectangle ink, logical;
|
|
int num_chars;
|
|
|
|
Xutf8TextPerCharExtents(font_set,
|
|
UTF8StrData(&utf8char), UTF8StrSize(&utf8char),
|
|
&ink, &logical, 1, &num_chars, NULL, NULL);
|
|
UTF8StrFree(&utf8char);
|
|
|
|
if (num_chars != 1)
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
// When the font in use is proportional, the following variables should
|
|
// be tuned finer based on the the XFontStruct's field 'per_char'.
|
|
cs->lbearing = 0;
|
|
cs->rbearing = 0;
|
|
cs->width = logical.width;
|
|
cs->ascent = fonts[0]->max_bounds.ascent;
|
|
cs->descent = fonts[0]->max_bounds.descent;
|
|
cs->attributes = 0;
|
|
|
|
return YES;
|
|
}
|
|
else
|
|
{
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
#endif // X_HAVE_UTF8_STRING defined
|