summaryrefslogtreecommitdiff
path: root/src/xutf8
diff options
context:
space:
mode:
authorIan MacArthur <imacarthur@gmail.com>2011-02-07 22:22:16 +0000
committerIan MacArthur <imacarthur@gmail.com>2011-02-07 22:22:16 +0000
commit33af4e4ba5cec3f0fe757ca9889b23b2ba0f3b76 (patch)
tree198b2daea575779dac3dd942934e66e15a59e38b /src/xutf8
parentd140f4f3be96f7002c6d8a50d72f11baa92509d1 (diff)
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
Diffstat (limited to 'src/xutf8')
-rw-r--r--src/xutf8/utf8Wrap.c298
1 files changed, 221 insertions, 77 deletions
diff --git a/src/xutf8/utf8Wrap.c b/src/xutf8/utf8Wrap.c
index 67b3d8da0..66094b890 100644
--- a/src/xutf8/utf8Wrap.c
+++ b/src/xutf8/utf8Wrap.c
@@ -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;