libs-back/Source/xlib/XGFontSetFontInfo.m
Adam Fedor 85bf065924 Add/fix copyright and licenses.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@21392 72102866-910b-0410-8b05-ffd578937521
2005-07-01 20:43:10 +00:00

524 lines
13 KiB
Objective-C

/* <title>XGFontSetFontInfo</title>
<abstract>NSFont helper for GNUstep X/GPS Backend</abstract>
Copyright (C) 2003-2005 Free Software Foundation, Inc.
Author: Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
Date: July 2003
This file is part of the GNU Objective C User Interface library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#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