diff options
| -rw-r--r-- | FL/Xutf8.h | 59 | ||||
| -rw-r--r-- | src/fl_font_x.cxx | 23 | ||||
| -rw-r--r-- | src/xutf8/utf8Wrap.c | 298 |
3 files changed, 271 insertions, 109 deletions
diff --git a/FL/Xutf8.h b/FL/Xutf8.h index 459db02b8..609a7cff7 100644 --- a/FL/Xutf8.h +++ b/FL/Xutf8.h @@ -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( @@ -63,6 +63,19 @@ XUtf8DrawString( 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, Drawable d, @@ -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$". - */ + */ diff --git a/src/fl_font_x.cxx b/src/fl_font_x.cxx index c55b97734..de5a2ab8f 100644 --- a/src/fl_font_x.cxx +++ b/src/fl_font_x.cxx @@ -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 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; + 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); + + 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 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; |
