Attempt to fix STR #2550 to make fl_text_extents work in Xlib-only

(i.e. non-XFT) X11 builds.

This appears to be working now, though I can not test it fully, so we
need more feedback.
In particular the setting of the dx param is certainly wrong, but 
works fine in general cases. I think.
Also, I suspect it may behave badly in the face of RtoL text rendering
but I think we have other problems in that area anyway...



git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8399 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Ian MacArthur 2011-02-07 22:22:16 +00:00
parent d140f4f3be
commit 33af4e4ba5
3 changed files with 270 additions and 108 deletions

View File

@ -48,8 +48,8 @@ typedef struct {
XUtf8FontStruct *
XCreateUtf8FontStruct (
Display *dpy,
const char *base_font_name_list);
Display *dpy,
const char *base_font_name_list);
void
XUtf8DrawString(
@ -62,6 +62,19 @@ XUtf8DrawString(
const char *string,
int num_bytes);
void
XUtf8_measure_extents(
Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int *xx,
int *yy,
int *ww,
int *hh,
const char *string,
int num_bytes);
void
XUtf8DrawRtlString(
Display *display,
@ -89,7 +102,7 @@ XUtf8TextWidth(
XUtf8FontStruct *font_set,
const char *string,
int num_bytes);
int
int
XUtf8UcsWidth(
XUtf8FontStruct *font_set,
unsigned int ucs);
@ -100,41 +113,41 @@ XGetUtf8FontAndGlyph(
unsigned int ucs,
XFontStruct **fnt,
unsigned short *id);
void
XFreeUtf8FontStruct(
Display *dpy,
XUtf8FontStruct *font_set);
int
XConvertUtf8ToUcs(
const unsigned char *buf,
int len,
int
XConvertUtf8ToUcs(
const unsigned char *buf,
int len,
unsigned int *ucs);
int
int
XConvertUcsToUtf8(
unsigned int ucs,
unsigned int ucs,
char *buf);
int
int
XUtf8CharByteLen(
const unsigned char *buf,
const unsigned char *buf,
int len);
int
int
XCountUtf8Char(
const unsigned char *buf,
const unsigned char *buf,
int len);
int
XFastConvertUtf8ToUcs(
const unsigned char *buf,
int len,
int
XFastConvertUtf8ToUcs(
const unsigned char *buf,
int len,
unsigned int *ucs);
long
long
XKeysymToUcs(
KeySym keysym);
@ -147,7 +160,7 @@ XUtf8LookupString(
KeySym* keysym,
Status* status_return);
unsigned short
unsigned short
XUtf8IsNonSpacing(
unsigned int ucs);
@ -156,11 +169,11 @@ XUtf8IsRightToLeft(
unsigned int ucs);
int
int
XUtf8Tolower(
int ucs);
int
int
XUtf8Toupper(
int ucs);
@ -173,4 +186,4 @@ XUtf8Toupper(
/*
* End of "$Id$".
*/
*/

View File

@ -302,15 +302,20 @@ double fl_width(unsigned int c) {
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
if (font_gc != fl_gc) {
if (!current_font) fl_font(FL_HELVETICA, 14);
font_gc = fl_gc;
XSetFont(fl_display, fl_gc, current_font->fid);
}
int xx, yy, ww, hh;
XUtf8_measure_extents(fl_display, fl_window, current_font, fl_gc, &xx, &yy, &ww, &hh, c, n);
#if defined(__GNUC__)
#warning fl_text_extents is only a test stub in Xlib build at present
#endif /*__GNUC__*/
W = 0; H = 0;
fl_measure(c, W, H, 0);
dx = 0;
dy = fl_descent() - H;
W = ww; H = hh; dx = xx; dy = yy;
// This is the safe but mostly wrong thing we used to do...
// W = 0; H = 0;
// fl_measure(c, W, H, 0);
// dx = 0;
// dy = fl_descent() - H;
} // fl_text_extents

View File

@ -37,7 +37,7 @@
/* 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);
@ -63,15 +63,15 @@ Fl_XChar2b;
/*********************************************************************/
/** extract a list of font from the base font name list **/
/*********************************************************************/
static int
static int
get_font_list(
const char *base_font_name_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;
@ -103,28 +103,28 @@ get_font_list(
free(*flist);
*flist = (char**)NULL;
}
return nb;
return nb;
}
/*********************************************************************/
/** get the font name used as encoding for "fontspecific" encoding **/
/** (mainly used for adobe-symbol and adobe-zapfdingbats) **/
/*********************************************************************/
static int
static int
font_spec_enc(char *font) {
int ret;
char *enc;
char *end;
enc = font;
while (*enc != '-') enc++;
while (*enc != '-') enc++;
enc++;
while (*enc != '-') enc++;
enc++;
end = enc;
while (*end != '-') end++;
*end = '\0';
ret = encoding_number(enc);
*end = '-';
@ -159,14 +159,14 @@ get_range(const char *enc,
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,
get_encodings(char **font_name_list,
int *ranges,
int nb_font) {
@ -183,7 +183,7 @@ get_encodings(char **font_name_list,
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;
@ -194,13 +194,13 @@ get_encodings(char **font_name_list,
if (ec == 13) {
font_encoding_list[i] = encoding_number(ptr + 1);
if (font_encoding_list[i] == 0) {
get_range(ptr + 1,
get_range(ptr + 1,
ranges + i * 2,
ranges + i * 2 + 1);
}
break;
}
}
}
ptr++;
}
if (font_encoding_list[i] < 0) font_encoding_list[i] = 1;
@ -234,8 +234,8 @@ find_best_font(Display *dpy,
/*********************************************************************/
/** load all fonts **/
/*********************************************************************/
static void
load_fonts(Display *dpy,
static void
load_fonts(Display *dpy,
XUtf8FontStruct *font_set) {
int i;
@ -246,8 +246,8 @@ load_fonts(Display *dpy,
font_set->fonts = (XFontStruct**) malloc(sizeof(XFontStruct*) *
font_set->nb_font);
font_set->ranges = (int*) malloc(sizeof(int) *
font_set->ranges = (int*) malloc(sizeof(int) *
font_set->nb_font * 2);
font_set->descent = 0;
@ -257,7 +257,7 @@ load_fonts(Display *dpy,
while (i < font_set->nb_font) {
XFontStruct *fnt;
fnt = font_set->fonts[i] =
fnt = font_set->fonts[i] =
find_best_font(dpy, &(font_set->font_name_list[i]));
if (fnt) {
font_set->fid = fnt->fid;
@ -274,8 +274,8 @@ load_fonts(Display *dpy,
i++;
}
font_set->encodings =
get_encodings(font_set->font_name_list,
font_set->encodings =
get_encodings(font_set->font_name_list,
font_set->ranges, font_set->nb_font);
/* unload fonts with same encoding */
@ -297,7 +297,7 @@ load_fonts(Display *dpy,
}
}
}
}
}
}
/*********************************************************************/
@ -309,14 +309,14 @@ 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->nb_font = get_font_list(base_font_name_list,
&font_set->font_name_list);
if (font_set->nb_font < 1) {
@ -333,13 +333,13 @@ XCreateUtf8FontStruct(Display *dpy,
/*****************************************************************************/
/** draw a Right To Left UTF-8 string using multiple fonts as needed. **/
/*****************************************************************************/
void
XUtf8DrawRtlString(Display *display,
void
XUtf8DrawRtlString(Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
const char *string,
int num_bytes) {
@ -361,14 +361,14 @@ XUtf8DrawRtlString(Display *display,
/* 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 */
@ -392,21 +392,21 @@ XUtf8DrawRtlString(Display *display,
ptr = buf + 128;
}
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
/*
* 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 ||
if (encodings[fnum] != 0 ||
(ucs >= ranges[fnum * 2] && ucs <= ranges[fnum * 2 + 1])) {
break;
}
@ -454,13 +454,13 @@ XUtf8DrawRtlString(Display *display,
/*****************************************************************************/
/** draw an UTF-8 string using multiple fonts as needed. **/
/*****************************************************************************/
void
XUtf8DrawString(Display *display,
void
XUtf8DrawString(Display *display,
Drawable d,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
XUtf8FontStruct *font_set,
GC gc,
int x,
int y,
const char *string,
int num_bytes) {
@ -472,7 +472,7 @@ XUtf8DrawString(Display *display,
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 byte1 value of the UTF-8 char */
char glyph[2]; /* byte0 and byte1 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
nb_font = font_set->nb_font;
@ -486,7 +486,7 @@ XUtf8DrawString(Display *display,
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 */
@ -509,21 +509,21 @@ XUtf8DrawString(Display *display,
i = 0;
}
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
if (ulen < 1) ulen = 1;
no_spc = XUtf8IsNonSpacing(ucs);
if (no_spc) ucs = no_spc;
if (no_spc) ucs = no_spc;
/*
* find the first encoding which can be used to
* draw the glyph
/*
* 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 ||
if (encodings[fnum] != 0 ||
(ucs >= ranges[fnum * 2] &&
ucs <= ranges[fnum * 2 + 1])) {
break;
@ -564,12 +564,156 @@ XUtf8DrawString(Display *display,
}
/*****************************************************************************/
/** 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. **/
/*****************************************************************************/
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]; /* byte0 and byte1 value of the UTF-8 char */
int *ranges; /* sub range of iso10646 */
int wd = 0; /* accumulates the width */
int ht = 0; /* find max height in text */
int yt = 0x7FFFFFFF; /* delta-y found */
int res, hs;
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((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 ||
(ucs >= ranges[fnum * 2] &&
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;
*hh = ht;
*xx = 0;
*yy = yt;
}
/*****************************************************************************/
/** returns the pixel width of a UTF-8 string **/
/*****************************************************************************/
int
XUtf8TextWidth(XUtf8FontStruct *font_set,
int
XUtf8TextWidth(XUtf8FontStruct *font_set,
const char *string,
int num_bytes) {
@ -598,7 +742,7 @@ XUtf8TextWidth(XUtf8FontStruct *font_set,
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 */
@ -619,23 +763,23 @@ XUtf8TextWidth(XUtf8FontStruct *font_set,
i = 0;
}
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
if (ulen < 1) ulen = 1;
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
/*
* 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 ||
if (encodings[fnum] != 0 ||
(ucs >= ranges[fnum * 2] &&
ucs <= ranges[fnum * 2 + 1])) {
break;
@ -718,14 +862,14 @@ XGetUtf8FontAndGlyph(XUtf8FontStruct *font_set,
first = fnum;
last_fnum = fnum;
/*
* find the first encoding which can be used to
* draw the glyph
/*
* 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 ||
if (encodings[fnum] != 0 ||
(ucs >= ranges[fnum * 2] &&
ucs <= ranges[fnum * 2 + 1])) {
break;
@ -778,7 +922,7 @@ XUtf8UcsWidth(XUtf8FontStruct *font_set,
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 */
@ -790,13 +934,13 @@ XUtf8UcsWidth(XUtf8FontStruct *font_set,
ucs = XUtf8IsNonSpacing(ucs);
/*
* find the first encoding which can be used to
* draw the glyph
/*
* find the first encoding which can be used to
* draw the glyph
*/
fnum = first;
while (fnum < nb_font) {
if (fonts[fnum] &&
if (fonts[fnum] &&
ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
if (encodings[fnum] != 0 || (ucs >= ranges[fnum * 2] &&
ucs <= ranges[fnum * 2 + 1])) {
@ -843,10 +987,10 @@ XUtf8DrawImageString(Display *display,
XGCValues xgcv;
w = XUtf8TextWidth(font_set, string, num_bytes);
XGetGCValues(display, gc,
XGetGCValues(display, gc,
GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
function = xgcv.function;
fill_style = xgcv.fill_style;
foreground = xgcv.foreground;
@ -860,7 +1004,7 @@ XUtf8DrawImageString(Display *display,
XChangeGC(display, gc,
GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
XFillRectangle(display, d, gc, x, y - font_set->ascent,
XFillRectangle(display, d, gc, x, y - font_set->ascent,
(unsigned)w, (unsigned)(font_set->ascent + font_set->descent));
xgcv.function = function;
@ -877,8 +1021,8 @@ XUtf8DrawImageString(Display *display,
/*****************************************************************************/
/** free the XFontSet and others things created by XCreateUtf8FontSet **/
/*****************************************************************************/
void
XFreeUtf8FontStruct(Display *dpy,
void
XFreeUtf8FontStruct(Display *dpy,
XUtf8FontStruct *font_set) {
int i;