|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 /* "$Id: $" 00002 * 00003 * Author: Jean-Marc Lienher ( http://oksid.ch ) 00004 * Copyright 2000-2003 by O'ksi'D. 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00019 * USA. 00020 * 00021 * Please report all bugs and problems on the following page: 00022 * 00023 * http://www.fltk.org/str.php 00024 */ 00025 00026 /* 00027 * X11 UTF-8 text drawing functions. 00028 */ 00029 #if !defined(WIN32) && !defined(__APPLE__) 00030 00031 #include "../../FL/Xutf8.h" 00032 #include <X11/Xlib.h> 00033 #include <ctype.h> 00034 #include <stdlib.h> 00035 #include <string.h> 00036 #include <stdio.h> 00037 00038 /* External auto generated functions : */ 00039 #include "ucs2fontmap.c" 00040 /* 00041 * extern int ucs2fontmap(char *s, unsigned int ucs, int enc); 00042 * extern int encoding_number(const char *enc); 00043 * extern const char *encoding_name(int num); 00044 */ 00045 00046 /* The ARM header files have a bug by not taking into account that ARM cpu 00047 * likes pacing to 4 bytes. This little trick defines our own version of 00048 * XChar2b which does not have this problem 00049 */ 00050 00051 #if defined(__GNUC__) && defined(__arm__) && !defined(__ARM_EABI__) 00052 typedef struct { 00053 unsigned char byte1; 00054 unsigned char byte2; 00055 } 00056 __attribute__ ((packed)) 00057 Fl_XChar2b; 00058 #else 00059 #define Fl_XChar2b XChar2b 00060 #endif 00061 00062 00063 /*********************************************************************/ 00065 /*********************************************************************/ 00066 static int 00067 get_font_list( 00068 const char *base_font_name_list, 00069 char ***flist) { 00070 const char *ptr; 00071 const char *p; 00072 int nb; 00073 int nb_name; 00074 00075 ptr = base_font_name_list; 00076 p = NULL; 00077 nb = 0; 00078 nb_name = 1; 00079 00080 while (*ptr) { 00081 if (*ptr == ',') nb_name++; 00082 ptr++; 00083 } 00084 00085 *flist = (char **) malloc(sizeof(char*) * nb_name); 00086 ptr = base_font_name_list; 00087 00088 while (*ptr) { 00089 int l = 0, i = 0; 00090 00091 while(isspace(*ptr)) ptr++; 00092 p = ptr; 00093 while (*ptr && *ptr != ',') { ptr++; l++; } 00094 if (l > 2) { 00095 (*flist)[nb] = (char*) malloc((unsigned)l + 2); 00096 while (p != ptr) { ((*flist)[nb])[i] = *p; i++; p++; } 00097 (*flist)[nb][i] = '\0'; 00098 nb++; 00099 } 00100 if (*ptr) ptr++; 00101 } 00102 if (nb < 1) { 00103 free(*flist); 00104 *flist = (char**)NULL; 00105 } 00106 return nb; 00107 } 00108 00109 /*********************************************************************/ 00112 /*********************************************************************/ 00113 static int 00114 font_spec_enc(char *font) { 00115 int ret; 00116 char *enc; 00117 char *end; 00118 00119 enc = font; 00120 while (*enc != '-') enc++; 00121 enc++; 00122 while (*enc != '-') enc++; 00123 enc++; 00124 end = enc; 00125 while (*end != '-') end++; 00126 *end = '\0'; 00127 00128 ret = encoding_number(enc); 00129 *end = '-'; 00130 00131 return ret; 00132 } 00133 00134 00135 /*********************************************************************/ 00137 /*********************************************************************/ 00138 static void 00139 get_range(const char *enc, 00140 int *min, 00141 int *max) { 00142 00143 const char *ptr = enc; 00144 const char *ptr1; 00145 00146 if (!enc) return; 00147 00148 while (*ptr && *ptr != '-') ptr++; 00149 if (!*ptr) return; 00150 while (*ptr && *ptr != '[') ptr++; 00151 if (!*ptr) return; 00152 *min = 0xFFFF; 00153 *max = 0; 00154 while (*ptr && *ptr != ']') { 00155 int val; 00156 ptr++; 00157 ptr1 = ptr; 00158 while (*ptr && *ptr != ']' && *ptr != ' ' && *ptr != '_') ptr++; 00159 val = strtol(ptr1, NULL, 0); 00160 if (val < *min) *min = val; 00161 if (val > *max) *max = val; 00162 } 00163 } 00164 00165 /*********************************************************************/ 00167 /*********************************************************************/ 00168 static int * 00169 get_encodings(char **font_name_list, 00170 int *ranges, 00171 int nb_font) { 00172 00173 int *font_encoding_list; 00174 int i; 00175 i = 0; 00176 00177 font_encoding_list = (int *) malloc(sizeof(int) * nb_font); 00178 while (i < nb_font) { 00179 char *ptr; 00180 int ec; 00181 ptr = font_name_list[i]; 00182 ec = 0; 00183 font_encoding_list[i] = -1; 00184 ranges[i * 2] = 0; 00185 ranges[i * 2 + 1] = 0xFFFF; 00186 00187 if (ptr && strstr(ptr, "fontspecific")) { 00188 font_encoding_list[i] = font_spec_enc(ptr); 00189 ptr = NULL; 00190 } 00191 while (ptr && *ptr) { 00192 if (*ptr == '-') { 00193 ec++; 00194 if (ec == 13) { 00195 font_encoding_list[i] = encoding_number(ptr + 1); 00196 if (font_encoding_list[i] == 0) { 00197 get_range(ptr + 1, 00198 ranges + i * 2, 00199 ranges + i * 2 + 1); 00200 } 00201 break; 00202 } 00203 } 00204 ptr++; 00205 } 00206 if (font_encoding_list[i] < 0) font_encoding_list[i] = 1; 00207 i++; 00208 } 00209 return font_encoding_list; 00210 } 00211 00212 /*********************************************************************/ 00214 /*********************************************************************/ 00215 XFontStruct * 00216 find_best_font(Display *dpy, 00217 char **name) { 00218 00219 char **list; 00220 int cnt; 00221 XFontStruct *s; 00222 00223 list = XListFonts(dpy, *name, 1, &cnt); 00224 if (cnt && list) { 00225 free(*name); 00226 *name = strdup(list[0]); 00227 s = XLoadQueryFont(dpy, *name); 00228 XFreeFontNames(list); 00229 return s; 00230 } 00231 return NULL; 00232 } 00233 00234 /*********************************************************************/ 00236 /*********************************************************************/ 00237 static void 00238 load_fonts(Display *dpy, 00239 XUtf8FontStruct *font_set) { 00240 00241 int i; 00242 char **list; 00243 00244 i = 0; 00245 list = NULL; 00246 00247 font_set->fonts = (XFontStruct**) malloc(sizeof(XFontStruct*) * 00248 font_set->nb_font); 00249 00250 font_set->ranges = (int*) malloc(sizeof(int) * 00251 font_set->nb_font * 2); 00252 00253 font_set->descent = 0; 00254 font_set->ascent = 0; 00255 font_set->fid = 0; 00256 00257 while (i < font_set->nb_font) { 00258 XFontStruct *fnt; 00259 00260 fnt = font_set->fonts[i] = 00261 find_best_font(dpy, &(font_set->font_name_list[i])); 00262 if (fnt) { 00263 font_set->fid = fnt->fid; 00264 if (fnt->ascent > font_set->ascent) { 00265 font_set->ascent = fnt->ascent; 00266 } 00267 if (fnt->descent > font_set->descent) { 00268 font_set->descent = fnt->descent; 00269 } 00270 } else { 00271 free(font_set->font_name_list[i]); 00272 font_set->font_name_list[i] = NULL; 00273 } 00274 i++; 00275 } 00276 00277 font_set->encodings = 00278 get_encodings(font_set->font_name_list, 00279 font_set->ranges, font_set->nb_font); 00280 00281 /* unload fonts with same encoding */ 00282 for (i = 0; i < font_set->nb_font; i++) { 00283 if (font_set->font_name_list[i]) { 00284 int j; 00285 for (j = 0; j < i; j++) { 00286 if (font_set->font_name_list[j] && 00287 font_set->encodings[j] == 00288 font_set->encodings[i] && 00289 font_set->ranges[2*j] == 00290 font_set->ranges[2*i] && 00291 font_set->ranges[(2*j)+1] && 00292 font_set->ranges[(2*i)+1]) { 00293 XFreeFont(dpy, font_set->fonts[i]); 00294 free(font_set->font_name_list[i]); 00295 font_set->font_name_list[i] = NULL; 00296 font_set->fonts[i] = 0; 00297 } 00298 } 00299 } 00300 } 00301 } 00302 00303 /*********************************************************************/ 00306 /*********************************************************************/ 00307 XUtf8FontStruct * 00308 XCreateUtf8FontStruct(Display *dpy, 00309 const char *base_font_name_list) { 00310 00311 XUtf8FontStruct *font_set; 00312 00313 font_set = (XUtf8FontStruct*)malloc(sizeof(XUtf8FontStruct)); 00314 00315 if (!font_set) { 00316 return NULL; 00317 } 00318 00319 font_set->nb_font = get_font_list(base_font_name_list, 00320 &font_set->font_name_list); 00321 00322 if (font_set->nb_font < 1) { 00323 free(font_set); 00324 return NULL; 00325 } 00326 00327 load_fonts(dpy, font_set); 00328 00329 return font_set; 00330 } 00331 00332 00333 /*****************************************************************************/ 00335 /*****************************************************************************/ 00336 void 00337 XUtf8DrawRtlString(Display *display, 00338 Drawable d, 00339 XUtf8FontStruct *font_set, 00340 GC gc, 00341 int x, 00342 int y, 00343 const char *string, 00344 int num_bytes) { 00345 00346 int *encodings; /* encodings array */ 00347 XFontStruct **fonts; /* fonts array */ 00348 Fl_XChar2b buf[128]; /* drawing buffer */ 00349 Fl_XChar2b *ptr; /* pointer to the drawing buffer */ 00350 int fnum; /* index of the current font in the fonts array*/ 00351 int i; /* current byte in the XChar2b buffer */ 00352 int first; /* first valid font index */ 00353 int last_fnum; /* font index of the previous char */ 00354 int nb_font; /* quantity of fonts in the font array */ 00355 char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ 00356 int *ranges; /* sub range of iso10646 */ 00357 00358 nb_font = font_set->nb_font; 00359 00360 if (nb_font < 1) { 00361 /* there is no font in the font_set :-( */ 00362 return; 00363 } 00364 00365 ranges = font_set->ranges; 00366 fonts = font_set->fonts; 00367 encodings = font_set->encodings; 00368 i = 0; 00369 fnum = 0; 00370 ptr = buf + 128; 00371 00372 while(fnum < nb_font && !fonts[fnum]) fnum++; 00373 if (fnum >= nb_font) { 00374 /* there is no valid font for the X server */ 00375 return; 00376 } 00377 00378 first = fnum; 00379 last_fnum = fnum; 00380 00381 while (num_bytes > 0) { 00382 int ulen; /* byte length of the UTF-8 char */ 00383 unsigned int ucs; /* Unicode value of the UTF-8 char */ 00384 unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ 00385 00386 if (i > 120) { 00387 /*** draw the buffer **/ 00388 XSetFont(display, gc, fonts[fnum]->fid); 00389 x -= XTextWidth16(fonts[fnum], ptr, i); 00390 XDrawString16(display, d, gc, x, y, ptr, i); 00391 i = 0; 00392 ptr = buf + 128; 00393 } 00394 00395 ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs); 00396 00397 if (ulen < 1) ulen = 1; 00398 00399 no_spc = XUtf8IsNonSpacing(ucs); 00400 if (no_spc) ucs = no_spc; 00401 00402 /* 00403 * find the first encoding which can be used to 00404 * draw the glyph 00405 */ 00406 fnum = first; 00407 while (fnum < nb_font) { 00408 if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { 00409 if (encodings[fnum] != 0 || 00410 (ucs >= ranges[fnum * 2] && ucs <= ranges[fnum * 2 + 1])) { 00411 break; 00412 } 00413 } 00414 fnum++; 00415 } 00416 if (fnum == nb_font) { 00417 /* the char is not valid in all encodings -> 00418 * draw it using the first font :-( 00419 */ 00420 fnum = first; 00421 ucs2fontmap(glyph, '?', encodings[fnum]); 00422 } 00423 00424 if (last_fnum != fnum || no_spc) { 00425 XSetFont(display, gc, fonts[last_fnum]->fid); 00426 x -= XTextWidth16(fonts[last_fnum], ptr, i); 00427 XDrawString16(display, d, gc, x, y, ptr, i); 00428 i = 0; 00429 ptr = buf + 127; 00430 (*ptr).byte1 = glyph[0]; 00431 (*ptr).byte2 = glyph[1]; 00432 if (no_spc) { 00433 x += XTextWidth16(fonts[fnum], ptr, 1); 00434 } 00435 } else { 00436 ptr--; 00437 (*ptr).byte1 = glyph[0]; 00438 (*ptr).byte2 = glyph[1]; 00439 } 00440 last_fnum = fnum; 00441 i++; 00442 string += ulen; 00443 num_bytes -= ulen; 00444 } 00445 00446 if (i < 1) return; 00447 00448 XSetFont(display, gc, fonts[fnum]->fid); 00449 x -= XTextWidth16(fonts[last_fnum], ptr, i); 00450 XDrawString16(display, d, gc, x, y, ptr, i); 00451 } 00452 00453 00454 /*****************************************************************************/ 00456 /*****************************************************************************/ 00457 void 00458 XUtf8DrawString(Display *display, 00459 Drawable d, 00460 XUtf8FontStruct *font_set, 00461 GC gc, 00462 int x, 00463 int y, 00464 const char *string, 00465 int num_bytes) { 00466 00467 int *encodings; /* encodings array */ 00468 XFontStruct **fonts; /* fonts array */ 00469 Fl_XChar2b buf[128]; /* drawing buffer */ 00470 int fnum; /* index of the current font in the fonts array*/ 00471 int i; /* current byte in the XChar2b buffer */ 00472 int first; /* first valid font index */ 00473 int last_fnum; /* font index of the previous char */ 00474 int nb_font; /* quantity of fonts in the font array */ 00475 char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ 00476 int *ranges; /* sub range of iso10646 */ 00477 00478 nb_font = font_set->nb_font; 00479 00480 if (nb_font < 1) { 00481 /* there is no font in the font_set :-( */ 00482 return; 00483 } 00484 ranges = font_set->ranges; 00485 fonts = font_set->fonts; 00486 encodings = font_set->encodings; 00487 i = 0; 00488 fnum = 0; 00489 00490 while(fnum < nb_font && !fonts[fnum]) fnum++; 00491 if (fnum >= nb_font) { 00492 /* there is no valid font for the X server */ 00493 return; 00494 } 00495 00496 first = fnum; 00497 last_fnum = fnum; 00498 00499 while (num_bytes > 0) { 00500 int ulen; /* byte length of the UTF-8 char */ 00501 unsigned int ucs; /* Unicode value of the UTF-8 char */ 00502 unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ 00503 00504 if (i > 120) { 00505 /*** draw the buffer **/ 00506 XSetFont(display, gc, fonts[fnum]->fid); 00507 XDrawString16(display, d, gc, x, y, buf, i); 00508 x += XTextWidth16(fonts[fnum], buf, i); 00509 i = 0; 00510 } 00511 00512 ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs); 00513 00514 if (ulen < 1) ulen = 1; 00515 00516 no_spc = XUtf8IsNonSpacing(ucs); 00517 if (no_spc) ucs = no_spc; 00518 00519 /* 00520 * find the first encoding which can be used to 00521 * draw the glyph 00522 */ 00523 fnum = first; 00524 while (fnum < nb_font) { 00525 if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { 00526 if (encodings[fnum] != 0 || 00527 (ucs >= ranges[fnum * 2] && 00528 ucs <= ranges[fnum * 2 + 1])) { 00529 break; 00530 } 00531 } 00532 fnum++; 00533 } 00534 if (fnum == nb_font) { 00535 /* the char is not valid in all encodings -> 00536 * draw it using the first font :-( 00537 */ 00538 fnum = first; 00539 ucs2fontmap(glyph, '?', encodings[fnum]); 00540 } 00541 00542 if (last_fnum != fnum || no_spc) { 00543 XSetFont(display, gc, fonts[last_fnum]->fid); 00544 XDrawString16(display, d, gc, x, y, buf, i); 00545 x += XTextWidth16(fonts[last_fnum], buf, i); 00546 i = 0; 00547 (*buf).byte1 = glyph[0]; 00548 (*buf).byte2 = glyph[1]; 00549 if (no_spc) { 00550 x -= XTextWidth16(fonts[fnum], buf, 1); 00551 } 00552 } else { 00553 (*(buf + i)).byte1 = glyph[0]; 00554 (*(buf + i)).byte2 = glyph[1]; 00555 } 00556 last_fnum = fnum; 00557 i++; 00558 string += ulen; 00559 num_bytes -= ulen; 00560 } 00561 00562 XSetFont(display, gc, fonts[fnum]->fid); 00563 XDrawString16(display, d, gc, x, y, buf, i); 00564 } 00565 00566 00567 00568 /*****************************************************************************/ 00570 /*****************************************************************************/ 00571 int 00572 XUtf8TextWidth(XUtf8FontStruct *font_set, 00573 const char *string, 00574 int num_bytes) { 00575 00576 int x; 00577 int *encodings; /* encodings array */ 00578 XFontStruct **fonts; /* fonts array */ 00579 Fl_XChar2b buf[128]; /* drawing buffer */ 00580 int fnum; /* index of the current font in the fonts array*/ 00581 int i; /* current byte in the XChar2b buffer */ 00582 int first; /* first valid font index */ 00583 int last_fnum; /* font index of the previous char */ 00584 int nb_font; /* quantity of fonts in the font array */ 00585 char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ 00586 int *ranges; /* sub range of iso10646 */ 00587 00588 nb_font = font_set->nb_font; 00589 x = 0; 00590 00591 if (nb_font < 1) { 00592 /* there is no font in the font_set :-( */ 00593 return x; 00594 } 00595 00596 ranges = font_set->ranges; 00597 fonts = font_set->fonts; 00598 encodings = font_set->encodings; 00599 i = 0; 00600 fnum = 0; 00601 00602 while(fnum < nb_font && !fonts[fnum]) fnum++; 00603 if (fnum >= nb_font) { 00604 /* there is no valid font for the X server */ 00605 return x; 00606 } 00607 00608 first = fnum; 00609 last_fnum = fnum; 00610 00611 while (num_bytes > 0) { 00612 int ulen; /* byte length of the UTF-8 char */ 00613 unsigned int ucs; /* Unicode value of the UTF-8 char */ 00614 unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ 00615 00616 if (i > 120) { 00617 /*** measure the buffer **/ 00618 x += XTextWidth16(fonts[fnum], buf, i); 00619 i = 0; 00620 } 00621 00622 ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs); 00623 00624 if (ulen < 1) ulen = 1; 00625 00626 no_spc = XUtf8IsNonSpacing(ucs); 00627 if (no_spc) { 00628 ucs = no_spc; 00629 } 00630 00631 /* 00632 * find the first encoding which can be used to 00633 * draw the glyph 00634 */ 00635 fnum = first; 00636 while (fnum < nb_font) { 00637 if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { 00638 if (encodings[fnum] != 0 || 00639 (ucs >= ranges[fnum * 2] && 00640 ucs <= ranges[fnum * 2 + 1])) { 00641 break; 00642 } 00643 } 00644 fnum++; 00645 } 00646 if (fnum == nb_font) { 00647 /* the char is not valid in all encodings -> 00648 * draw it using the first font :-( 00649 */ 00650 fnum = first; 00651 ucs2fontmap(glyph, '?', encodings[fnum]); 00652 } 00653 00654 if (last_fnum != fnum || no_spc) { 00655 x += XTextWidth16(fonts[last_fnum], buf, i); 00656 i = 0; 00657 (*buf).byte1 = glyph[0]; 00658 (*buf).byte2 = glyph[1]; 00659 if (no_spc) { 00660 /* go back to draw the non-spacing char over the previous char */ 00661 x -= XTextWidth16(fonts[fnum], buf, 1); 00662 } 00663 } else { 00664 (*(buf + i)).byte1 = glyph[0]; 00665 (*(buf + i)).byte2 = glyph[1]; 00666 } 00667 last_fnum = fnum; 00668 i++; 00669 string += ulen; 00670 num_bytes -= ulen; 00671 } 00672 00673 x += XTextWidth16(fonts[last_fnum], buf, i); 00674 00675 return x; 00676 } 00677 00678 /*****************************************************************************/ 00680 /*****************************************************************************/ 00681 int 00682 XGetUtf8FontAndGlyph(XUtf8FontStruct *font_set, 00683 unsigned int ucs, 00684 XFontStruct **fnt, 00685 unsigned short *id) { 00686 00687 int x; 00688 int *encodings; /* encodings array */ 00689 XFontStruct **fonts; /* fonts array */ 00690 int fnum; /* index of the current font in the fonts array*/ 00691 int i; /* current byte in the XChar2b buffer */ 00692 int first; /* first valid font index */ 00693 int last_fnum; /* font index of the previous char */ 00694 int nb_font; /* quantity of fonts in the font array */ 00695 char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ 00696 int *ranges; /* sub range of iso10646 */ 00697 00698 nb_font = font_set->nb_font; 00699 x = 0; 00700 00701 if (nb_font < 1) { 00702 /* there is no font in the font_set :-( */ 00703 return -1; 00704 } 00705 00706 ranges = font_set->ranges; 00707 fonts = font_set->fonts; 00708 encodings = font_set->encodings; 00709 i = 0; 00710 fnum = 0; 00711 00712 while(fnum < nb_font && !fonts[fnum]) fnum++; 00713 if (fnum >= nb_font) { 00714 /* there is no valid font for the X server */ 00715 return -1; 00716 } 00717 00718 first = fnum; 00719 last_fnum = fnum; 00720 00721 /* 00722 * find the first encoding which can be used to 00723 * draw the glyph 00724 */ 00725 fnum = first; 00726 while (fnum < nb_font) { 00727 if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { 00728 if (encodings[fnum] != 0 || 00729 (ucs >= ranges[fnum * 2] && 00730 ucs <= ranges[fnum * 2 + 1])) { 00731 break; 00732 } 00733 } 00734 fnum++; 00735 } 00736 if (fnum == nb_font) { 00737 /* the char is not valid in all encodings -> 00738 * draw it using the first font :-( 00739 */ 00740 fnum = first; 00741 ucs2fontmap(glyph, '?', encodings[fnum]); 00742 } 00743 00744 *id = ((unsigned char)glyph[0] << 8) | (unsigned char)glyph[1] ; 00745 *fnt = fonts[fnum]; 00746 return 0; 00747 } 00748 00749 /*****************************************************************************/ 00751 /*****************************************************************************/ 00752 int 00753 XUtf8UcsWidth(XUtf8FontStruct *font_set, 00754 unsigned int ucs) { 00755 00756 int x; 00757 int *encodings; /* encodings array */ 00758 XFontStruct **fonts; /* fonts array */ 00759 Fl_XChar2b buf[8]; /* drawing buffer */ 00760 int fnum; /* index of the current font in the fonts array*/ 00761 int i; /* current byte in the XChar2b buffer */ 00762 int first; /* first valid font index */ 00763 int last_fnum; /* font index of the previous char */ 00764 int nb_font; /* quantity of fonts in the font array */ 00765 char glyph[2]; /* byte1 and byte1 value of the UTF-8 char */ 00766 int *ranges; /* sub range of iso10646 */ 00767 00768 nb_font = font_set->nb_font; 00769 x = 0; 00770 00771 if (nb_font < 1) { 00772 /* there is no font in the font_set :-( */ 00773 return x; 00774 } 00775 00776 ranges = font_set->ranges; 00777 fonts = font_set->fonts; 00778 encodings = font_set->encodings; 00779 i = 0; 00780 fnum = 0; 00781 00782 while(fnum < nb_font && !fonts[fnum]) fnum++; 00783 if (fnum >= nb_font) { 00784 /* there is no valid font for the X server */ 00785 return x; 00786 } 00787 00788 first = fnum; 00789 last_fnum = fnum; 00790 00791 ucs = XUtf8IsNonSpacing(ucs); 00792 00793 /* 00794 * find the first encoding which can be used to 00795 * draw the glyph 00796 */ 00797 fnum = first; 00798 while (fnum < nb_font) { 00799 if (fonts[fnum] && 00800 ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { 00801 if (encodings[fnum] != 0 || (ucs >= ranges[fnum * 2] && 00802 ucs <= ranges[fnum * 2 + 1])) { 00803 break; 00804 } 00805 } 00806 fnum++; 00807 } 00808 if (fnum == nb_font) { 00809 /* the char is not valid in all encodings -> 00810 * draw it using the first font :-( 00811 */ 00812 fnum = first; 00813 ucs2fontmap(glyph, '?', encodings[fnum]); 00814 } 00815 00816 (*buf).byte1 = glyph[0]; 00817 (*buf).byte2 = glyph[1]; 00818 00819 x += XTextWidth16(fonts[fnum], buf, 1); 00820 00821 return x; 00822 } 00823 00824 /*****************************************************************************/ 00826 /*****************************************************************************/ 00827 void 00828 XUtf8DrawImageString(Display *display, 00829 Drawable d, 00830 XUtf8FontStruct *font_set, 00831 GC gc, 00832 int x, 00833 int y, 00834 const char *string, 00835 int num_bytes) { 00836 00837 /* FIXME: must be improved ! */ 00838 int w; 00839 int fill_style; 00840 unsigned long foreground; 00841 unsigned long background; 00842 int function; 00843 XGCValues xgcv; 00844 00845 w = XUtf8TextWidth(font_set, string, num_bytes); 00846 00847 XGetGCValues(display, gc, 00848 GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); 00849 00850 function = xgcv.function; 00851 fill_style = xgcv.fill_style; 00852 foreground = xgcv.foreground; 00853 background = xgcv.background; 00854 00855 xgcv.function = GXcopy; 00856 xgcv.foreground = background; 00857 xgcv.background = foreground; 00858 xgcv.fill_style = FillSolid; 00859 00860 XChangeGC(display, gc, 00861 GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); 00862 00863 XFillRectangle(display, d, gc, x, y - font_set->ascent, 00864 (unsigned)w, (unsigned)(font_set->ascent + font_set->descent)); 00865 00866 xgcv.function = function; 00867 xgcv.foreground = foreground; 00868 xgcv.background = background; 00869 xgcv.fill_style = fill_style; 00870 00871 XChangeGC(display, gc, 00872 GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); 00873 00874 XUtf8DrawString(display, d, font_set, gc, x, y, string, num_bytes); 00875 } 00876 00877 /*****************************************************************************/ 00879 /*****************************************************************************/ 00880 void 00881 XFreeUtf8FontStruct(Display *dpy, 00882 XUtf8FontStruct *font_set) { 00883 00884 int i; 00885 i = 0; 00886 while (i < font_set->nb_font) { 00887 if (font_set->fonts[i]) { 00888 XFreeFont(dpy, font_set->fonts[i]); 00889 free(font_set->font_name_list[i]); 00890 } 00891 i++; 00892 } 00893 free(font_set->ranges); 00894 free(font_set->font_name_list); 00895 free(font_set->fonts); 00896 free(font_set->encodings); 00897 free(font_set); 00898 } 00899 00900 #endif /* X11 only */ 00901 00902 /* 00903 * End of "$Id: $". 00904 */