cave-story-solaris/DoConfig/fltk/src/xutf8/utf8Wrap.c
2019-05-02 18:20:47 +01:00

1028 lines
28 KiB
C

/* "$Id$"
*
* Author: Jean-Marc Lienher ( http://oksid.ch )
* Copyright 2000-2003 by O'ksi'D.
*
* This library is free software. Distribution and use rights are outlined in
* the file "COPYING" which should have been included with this file. If this
* file is missing or damaged, see the license at:
*
* http://www.fltk.org/COPYING.php
*
* Please report all bugs and problems on the following page:
*
* http://www.fltk.org/str.php
*/
/*
* X11 UTF-8 text drawing functions.
*/
#if !defined(WIN32) && !defined(__APPLE__)
#include "../Xutf8.h"
#include <X11/Xlib.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* External auto generated functions : */
#include "ucs2fontmap.c"
/*
* extern int ucs2fontmap(char *s, unsigned int ucs, int enc);
* extern int encoding_number(const char *enc);
* extern const char *encoding_name(int num);
*/
/* The ARM header files have a bug by not taking into account that ARM cpu
* likes pacing to 4 bytes. This little trick defines our own version of
* XChar2b which does not have this problem
*/
#if defined(__GNUC__) && defined(__arm__) && !defined(__ARM_EABI__)
typedef struct {
unsigned char byte1;
unsigned char byte2;
}
__attribute__ ((packed))
Fl_XChar2b;
#else
#define Fl_XChar2b XChar2b
#endif
/*********************************************************************/
/** extract a list of font from the base font name list **/
/*********************************************************************/
static int
get_font_list(
const char *base_font_name_list,
char ***flist) {
const char *ptr;
const char *p;
int nb;
int nb_name;
ptr = base_font_name_list;
p = NULL;
nb = 0;
nb_name = 1;
while (*ptr) {
if (*ptr == ',') nb_name++;
ptr++;
}
*flist = (char **) malloc(sizeof(char*) * nb_name);
ptr = base_font_name_list;
while (*ptr) {
int l = 0, i = 0;
while(isspace((int)(unsigned char)*ptr)) ptr++;
p = ptr;
while (*ptr && *ptr != ',') { ptr++; l++; }
if (l > 2) {
(*flist)[nb] = (char*) malloc((unsigned)l + 2);
while (p != ptr) { ((*flist)[nb])[i] = *p; i++; p++; }
(*flist)[nb][i] = '\0';
nb++;
}
if (*ptr) ptr++;
}
if (nb < 1) {
free(*flist);
*flist = (char**)NULL;
}
return nb;
}
/*********************************************************************/
/** get the font name used as encoding for "fontspecific" encoding **/
/** (mainly used for adobe-symbol and adobe-zapfdingbats) **/
/*********************************************************************/
static int
font_spec_enc(char *font) {
int ret;
char *enc;
char *end;
enc = font;
while (*enc != '-') enc++;
enc++;
while (*enc != '-') enc++;
enc++;
end = enc;
while (*end != '-') end++;
*end = '\0';
ret = encoding_number(enc);
*end = '-';
return ret;
}
/*********************************************************************/
/** get the sub range of a iso10646-1 font **/
/*********************************************************************/
static void
get_range(const char *enc,
int *min,
int *max) {
const char *ptr = enc;
const char *ptr1;
if (!enc) return;
while (*ptr && *ptr != '-') ptr++;
if (!*ptr) return;
while (*ptr && *ptr != '[') ptr++;
if (!*ptr) return;
*min = 0xFFFF;
*max = 0;
while (*ptr && *ptr != ']') {
int val;
ptr++;
ptr1 = ptr;
while (*ptr && *ptr != ']' && *ptr != ' ' && *ptr != '_') ptr++;
val = strtol(ptr1, NULL, 0);
if (val < *min) *min = val;
if (val > *max) *max = val;
}
}
/*********************************************************************/
/** get the internal encoding number of each fonts **/
/*********************************************************************/
static int *
get_encodings(char **font_name_list,
int *ranges,
int nb_font) {
int *font_encoding_list;
int i;
i = 0;
font_encoding_list = (int *) malloc(sizeof(int) * nb_font);
while (i < nb_font) {
char *ptr;
int ec;
ptr = font_name_list[i];
ec = 0;
font_encoding_list[i] = -1;
ranges[i * 2] = 0;
ranges[i * 2 + 1] = 0xFFFF;
if (ptr && strstr(ptr, "fontspecific")) {
font_encoding_list[i] = font_spec_enc(ptr);
ptr = NULL;
}
while (ptr && *ptr) {
if (*ptr == '-') {
ec++;
if (ec == 13) {
font_encoding_list[i] = encoding_number(ptr + 1);
if (font_encoding_list[i] == 0) {
get_range(ptr + 1,
ranges + i * 2,
ranges + i * 2 + 1);
}
break;
}
}
ptr++;
}
if (font_encoding_list[i] < 0) font_encoding_list[i] = 1;
i++;
}
return font_encoding_list;
}
/*********************************************************************/
/** find the first font which matches the name and load it. **/
/*********************************************************************/
static XFontStruct *
find_best_font(Display *dpy,
char **name) {
char **list;
int cnt;
XFontStruct *s;
list = XListFonts(dpy, *name, 1, &cnt);
if (cnt && list) {
free(*name);
*name = strdup(list[0]);
s = XLoadQueryFont(dpy, *name);
XFreeFontNames(list);
return s;
}
return NULL;
}
/*********************************************************************/
/** load all fonts **/
/*********************************************************************/
static void
load_fonts(Display *dpy,
XUtf8FontStruct *font_set) {
int i = 0;
font_set->fonts = (XFontStruct**) malloc(sizeof(XFontStruct*) *
font_set->nb_font);
font_set->ranges = (int*) malloc(sizeof(int) *
font_set->nb_font * 2);
font_set->descent = 0;
font_set->ascent = 0;
font_set->fid = 0;
while (i < font_set->nb_font) {
XFontStruct *fnt;
fnt = font_set->fonts[i] =
find_best_font(dpy, &(font_set->font_name_list[i]));
if (fnt) {
font_set->fid = fnt->fid;
if (fnt->ascent > font_set->ascent) {
font_set->ascent = fnt->ascent;
}
if (fnt->descent > font_set->descent) {
font_set->descent = fnt->descent;
}
} else {
free(font_set->font_name_list[i]);
font_set->font_name_list[i] = NULL;
}
i++;
}
font_set->encodings =
get_encodings(font_set->font_name_list,
font_set->ranges, font_set->nb_font);
/* unload fonts with same encoding */
for (i = 0; i < font_set->nb_font; i++) {
if (font_set->font_name_list[i]) {
int j;
for (j = 0; j < i; j++) {
if (font_set->font_name_list[j] &&
font_set->encodings[j] ==
font_set->encodings[i] &&
font_set->ranges[2*j] ==
font_set->ranges[2*i] &&
font_set->ranges[(2*j)+1] &&
font_set->ranges[(2*i)+1]) {
XFreeFont(dpy, font_set->fonts[i]);
free(font_set->font_name_list[i]);
font_set->font_name_list[i] = NULL;
font_set->fonts[i] = 0;
}
}
}
}
}
/*********************************************************************/
/** Creates an array of XFontStruct acording to the comma separated **/
/** list of fonts. XLoad all fonts. **/
/*********************************************************************/
XUtf8FontStruct *
XCreateUtf8FontStruct(Display *dpy,
const char *base_font_name_list) {
XUtf8FontStruct *font_set;
font_set = (XUtf8FontStruct*)malloc(sizeof(XUtf8FontStruct));
if (!font_set) {
return NULL;
}
font_set->nb_font = get_font_list(base_font_name_list,
&font_set->font_name_list);
if (font_set->nb_font < 1) {
free(font_set);
return NULL;
}
load_fonts(dpy, font_set);
return font_set;
}
/*****************************************************************************/
/** draw a Right To Left UTF-8 string using multiple fonts as needed. **/
/*****************************************************************************/
void
XUtf8DrawRtlString(Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
const char *string,
int num_bytes) {
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
Fl_XChar2b buf[128]; /* drawing buffer */
Fl_XChar2b *ptr; /* pointer to the drawing buffer */
int fnum; /* index of the current font in the fonts array*/
int i; /* current byte in the XChar2b buffer */
int first; /* first valid font index */
int last_fnum; /* font index of the previous char */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
nb_font = font_set->nb_font;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
i = 0;
fnum = 0;
ptr = buf + 128;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return;
}
first = fnum;
last_fnum = fnum;
while (num_bytes > 0) {
int ulen; /* byte length of the UTF-8 char */
unsigned int ucs; /* Unicode value of the UTF-8 char */
unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
if (i > 120) {
/*** draw the buffer **/
XSetFont(display, gc, fonts[fnum]->fid);
x -= XTextWidth16(fonts[fnum], ptr, i);
XDrawString16(display, d, gc, x, y, ptr, i);
i = 0;
ptr = buf + 128;
}
ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 ||
((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
if (last_fnum != fnum || no_spc) {
XSetFont(display, gc, fonts[last_fnum]->fid);
x -= XTextWidth16(fonts[last_fnum], ptr, i);
XDrawString16(display, d, gc, x, y, ptr, i);
i = 0;
ptr = buf + 127;
(*ptr).byte1 = glyph[0];
(*ptr).byte2 = glyph[1];
if (no_spc) {
x += XTextWidth16(fonts[fnum], ptr, 1);
}
} else {
ptr--;
(*ptr).byte1 = glyph[0];
(*ptr).byte2 = glyph[1];
}
last_fnum = fnum;
i++;
string += ulen;
num_bytes -= ulen;
}
if (i < 1) return;
XSetFont(display, gc, fonts[fnum]->fid);
x -= XTextWidth16(fonts[last_fnum], ptr, i);
XDrawString16(display, d, gc, x, y, ptr, i);
}
/*****************************************************************************/
/** draw an UTF-8 string using multiple fonts as needed. **/
/*****************************************************************************/
void
XUtf8DrawString(Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
const char *string,
int num_bytes) {
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
Fl_XChar2b buf[128]; /* drawing buffer */
int fnum; /* index of the current font in the fonts array*/
int i; /* current byte in the XChar2b buffer */
int first; /* first valid font index */
int last_fnum; /* font index of the previous char */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
nb_font = font_set->nb_font;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
i = 0;
fnum = 0;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return;
}
first = fnum;
last_fnum = fnum;
while (num_bytes > 0) {
int ulen; /* byte length of the UTF-8 char */
unsigned int ucs; /* Unicode value of the UTF-8 char */
unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
if (i > 120) {
/*** draw the buffer **/
XSetFont(display, gc, fonts[fnum]->fid);
XDrawString16(display, d, gc, x, y, buf, i);
x += XTextWidth16(fonts[fnum], buf, i);
i = 0;
}
ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 ||
((int)ucs >= ranges[fnum * 2] &&
(int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
if (last_fnum != fnum || no_spc) {
XSetFont(display, gc, fonts[last_fnum]->fid);
XDrawString16(display, d, gc, x, y, buf, i);
x += XTextWidth16(fonts[last_fnum], buf, i);
i = 0;
(*buf).byte1 = glyph[0];
(*buf).byte2 = glyph[1];
if (no_spc) {
x -= XTextWidth16(fonts[fnum], buf, 1);
}
} else {
(*(buf + i)).byte1 = glyph[0];
(*(buf + i)).byte2 = glyph[1];
}
last_fnum = fnum;
i++;
string += ulen;
num_bytes -= ulen;
}
XSetFont(display, gc, fonts[fnum]->fid);
XDrawString16(display, d, gc, x, y, buf, i);
}
/*****************************************************************************/
/** Measure the inked extents of a UTF-8 string using multiple fonts as **/
/** needed. Tries to mirror the behaviour of the draw function **/
/** XUtf8DrawString() as closely as possible to get consistent sizes. **/
/*****************************************************************************/
void
XUtf8_measure_extents(
Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int *xx, /* x-offset from origin */
int *yy, /* y-offset from origin */
int *ww, /* overall inked width */
int *hh, /* maximum inked height */
const char *string, /* text to measure */
int num_bytes) {
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
Fl_XChar2b buf[128]; /* drawing buffer */
int fnum; /* index of the current font in the fonts array*/
int i; /* current byte in the XChar2b buffer */
int first; /* first valid font index */
int last_fnum; /* font index of the previous char */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
int wd = 0; /* accumulates the width of the text */
int ht = 0; /* used to find max height in text */
int hs; /* "height sum" of current text segment */
int yt = 0x7FFFFFFF; /* used to find bounding rectangle delta-y */
/* int res; */ /* result from calling XTextExtents16() - we should test this is OK! */
/* FC: the man does not specify error codes for it, but X will generate X errors like BadGC or BadFont. */
XCharStruct sizes;
int dir_ret = 0;
int fnt_asc = 0;
int fnt_dsc = 0;
nb_font = font_set->nb_font;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
i = 0;
fnum = 0;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return;
}
first = fnum;
last_fnum = fnum;
while (num_bytes > 0) {
int ulen; /* byte length of the UTF-8 char */
unsigned int ucs; /* Unicode value of the UTF-8 char */
unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
if (i > 120) {
/*** draw the buffer **/
XSetFont(display, gc, fonts[fnum]->fid);
/* res = */ XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
/* recover the dimensions - should verify that res == 0 first! */
wd += sizes.width; /* accumulate the width */
hs = sizes.ascent + sizes.descent; /* total height */
if(hs > ht) ht = hs; /* new height exceeds previous height */
if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
i = 0;
}
ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 ||
((int)ucs >= ranges[fnum * 2] &&
(int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
if (last_fnum != fnum || no_spc) {
XSetFont(display, gc, fonts[last_fnum]->fid);
/* res = */ XTextExtents16(fonts[last_fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
/* recover the dimensions - should verify that res == 0 first! */
wd += sizes.width; /* accumulate the width */
hs = sizes.ascent + sizes.descent; /* total height */
if(hs > ht) ht = hs; /* new height exceeds previous height */
if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
i = 0;
(*buf).byte1 = glyph[0];
(*buf).byte2 = glyph[1];
if (no_spc) {
wd -= XTextWidth16(fonts[fnum], buf, 1);
}
} else {
(*(buf + i)).byte1 = glyph[0];
(*(buf + i)).byte2 = glyph[1];
}
last_fnum = fnum;
i++;
string += ulen;
num_bytes -= ulen;
}
XSetFont(display, gc, fonts[fnum]->fid);
/* res = */ XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
/* recover the dimensions - should verify that res == 0 first! */
wd += sizes.width; /* accumulate the width */
hs = sizes.ascent + sizes.descent; /* total height */
if(hs > ht) ht = hs; /* new height exceeds previous height */
if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
/* return values */
*ww = wd; /* width of inked area rectangle */
*hh = ht; /* max height of inked area rectangle */
*xx = 0; /* x-offset from origin to start of inked area - this is wrong! */
*yy = yt; /* y-offset from origin to start of inked rectangle */
}
/*****************************************************************************/
/** returns the pixel width of a UTF-8 string **/
/*****************************************************************************/
int
XUtf8TextWidth(XUtf8FontStruct *font_set,
const char *string,
int num_bytes) {
int x;
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
Fl_XChar2b buf[128]; /* drawing buffer */
int fnum; /* index of the current font in the fonts array*/
int i; /* current byte in the XChar2b buffer */
int first; /* first valid font index */
int last_fnum; /* font index of the previous char */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
nb_font = font_set->nb_font;
x = 0;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return x;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
i = 0;
fnum = 0;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return x;
}
first = fnum;
last_fnum = fnum;
while (num_bytes > 0) {
int ulen; /* byte length of the UTF-8 char */
unsigned int ucs; /* Unicode value of the UTF-8 char */
unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
if (i > 120) {
/*** measure the buffer **/
x += XTextWidth16(fonts[fnum], buf, i);
i = 0;
}
ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) {
ucs = no_spc;
}
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 ||
((int)ucs >= ranges[fnum * 2] &&
(int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
if (last_fnum != fnum || no_spc) {
x += XTextWidth16(fonts[last_fnum], buf, i);
i = 0;
(*buf).byte1 = glyph[0];
(*buf).byte2 = glyph[1];
if (no_spc) {
/* go back to draw the non-spacing char over the previous char */
x -= XTextWidth16(fonts[fnum], buf, 1);
}
} else {
(*(buf + i)).byte1 = glyph[0];
(*(buf + i)).byte2 = glyph[1];
}
last_fnum = fnum;
i++;
string += ulen;
num_bytes -= ulen;
}
x += XTextWidth16(fonts[last_fnum], buf, i);
return x;
}
/*****************************************************************************/
/** get the X font and glyph ID of a UCS char **/
/*****************************************************************************/
int
fl_XGetUtf8FontAndGlyph(XUtf8FontStruct *font_set,
unsigned int ucs,
XFontStruct **fnt,
unsigned short *id) {
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
int fnum; /* index of the current font in the fonts array*/
int first; /* first valid font index */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
nb_font = font_set->nb_font;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return -1;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
fnum = 0;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return -1;
}
first = fnum;
/*
* find the first encoding which can be used to draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 ||
((int)ucs >= ranges[fnum * 2] &&
(int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
*id = ((unsigned char)glyph[0] << 8) | (unsigned char)glyph[1] ;
*fnt = fonts[fnum];
return 0;
}
/*****************************************************************************/
/** returns the pixel width of a UCS char **/
/*****************************************************************************/
int
XUtf8UcsWidth(XUtf8FontStruct *font_set,
unsigned int ucs) {
int x;
int *encodings; /* encodings array */
XFontStruct **fonts; /* fonts array */
Fl_XChar2b buf[8]; /* drawing buffer */
int fnum; /* index of the current font in the fonts array*/
int first; /* first valid font index */
int nb_font; /* quantity of fonts in the font array */
char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
unsigned int no_spc;
nb_font = font_set->nb_font;
x = 0;
if (nb_font < 1) {
/* there is no font in the font_set :-( */
return x;
}
ranges = font_set->ranges;
fonts = font_set->fonts;
encodings = font_set->encodings;
fnum = 0;
while(fnum < nb_font && !fonts[fnum]) fnum++;
if (fnum >= nb_font) {
/* there is no valid font for the X server */
return x;
}
first = fnum;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] &&
ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] &&
(int)ucs <= ranges[fnum * 2 + 1])) {
break;
}
}
fnum++;
}
if (fnum == nb_font) {
/* the char is not valid in all encodings ->
* draw it using the first font :-(
*/
fnum = first;
ucs2fontmap(glyph, '?', encodings[fnum]);
}
(*buf).byte1 = glyph[0];
(*buf).byte2 = glyph[1];
x += XTextWidth16(fonts[fnum], buf, 1);
return x;
}
/*****************************************************************************/
/** draw an UTF-8 string and clear the background. **/
/*****************************************************************************/
void
XUtf8DrawImageString(Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
const char *string,
int num_bytes) {
/* FIXME: must be improved ! */
int w;
int fill_style;
unsigned long foreground;
unsigned long background;
int function;
XGCValues xgcv;
w = XUtf8TextWidth(font_set, string, num_bytes);
XGetGCValues(display, gc,
GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
function = xgcv.function;
fill_style = xgcv.fill_style;
foreground = xgcv.foreground;
background = xgcv.background;
xgcv.function = GXcopy;
xgcv.foreground = background;
xgcv.background = foreground;
xgcv.fill_style = FillSolid;
XChangeGC(display, gc,
GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
XFillRectangle(display, d, gc, x, y - font_set->ascent,
(unsigned)w, (unsigned)(font_set->ascent + font_set->descent));
xgcv.function = function;
xgcv.foreground = foreground;
xgcv.background = background;
xgcv.fill_style = fill_style;
XChangeGC(display, gc,
GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
XUtf8DrawString(display, d, font_set, gc, x, y, string, num_bytes);
}
/*****************************************************************************/
/** free the XFontSet and others things created by XCreateUtf8FontSet **/
/*****************************************************************************/
void
XFreeUtf8FontStruct(Display *dpy,
XUtf8FontStruct *font_set) {
int i;
i = 0;
while (i < font_set->nb_font) {
if (font_set->fonts[i]) {
XFreeFont(dpy, font_set->fonts[i]);
free(font_set->font_name_list[i]);
}
i++;
}
free(font_set->ranges);
free(font_set->font_name_list);
free(font_set->fonts);
free(font_set->encodings);
free(font_set);
}
#endif /* X11 only */
/*
* End of "$Id$".
*/