|
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 // 00002 // "$Id: fl_font_x.cxx 8126 2010-12-28 12:02:23Z manolo $" 00003 // 00004 // Standard X11 font selection code for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 #ifndef FL_DOXYGEN 00028 00029 Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) { 00030 font = XCreateUtf8FontStruct(fl_display, name); 00031 if (!font) { 00032 Fl::warning("bad font: %s", name); 00033 font = XCreateUtf8FontStruct(fl_display, "fixed"); 00034 } 00035 # if HAVE_GL 00036 listbase = 0; 00037 for (int u = 0; u < 64; u++) glok[u] = 0; 00038 # endif 00039 } 00040 00041 Fl_Font_Descriptor* fl_fontsize; 00042 Fl_XFont_On_Demand fl_xfont; 00043 00044 Fl_Font_Descriptor::~Fl_Font_Descriptor() { 00045 # if HAVE_GL 00046 // Delete list created by gl_draw(). This is not done by this code 00047 // as it will link in GL unnecessarily. There should be some kind 00048 // of "free" routine pointer, or a subclass? 00049 // if (listbase) { 00050 // int base = font->min_char_or_byte2; 00051 // int size = font->max_char_or_byte2-base+1; 00052 // int base = 0; int size = 256; 00053 // glDeleteLists(listbase+base,size); 00054 // } 00055 # endif 00056 if (this == fl_fontsize) { 00057 fl_fontsize = 0; 00058 fl_xfont = 0; 00059 } 00060 XFreeUtf8FontStruct(fl_display, font); 00061 } 00062 00064 00065 // WARNING: if you add to this table, you must redefine FL_FREE_FONT 00066 // in Enumerations.H & recompile!! 00067 static Fl_Fontdesc built_in_table[] = { 00068 {"-*-helvetica-medium-r-normal--*"}, 00069 {"-*-helvetica-bold-r-normal--*"}, 00070 {"-*-helvetica-medium-o-normal--*"}, 00071 {"-*-helvetica-bold-o-normal--*"}, 00072 {"-*-courier-medium-r-normal--*"}, 00073 {"-*-courier-bold-r-normal--*"}, 00074 {"-*-courier-medium-o-normal--*"}, 00075 {"-*-courier-bold-o-normal--*"}, 00076 {"-*-times-medium-r-normal--*"}, 00077 {"-*-times-bold-r-normal--*"}, 00078 {"-*-times-medium-i-normal--*"}, 00079 {"-*-times-bold-i-normal--*"}, 00080 {"-*-symbol-*"}, 00081 {"-*-lucidatypewriter-medium-r-normal-sans-*"}, 00082 {"-*-lucidatypewriter-bold-r-normal-sans-*"}, 00083 {"-*-*zapf dingbats-*"} 00084 }; 00085 00086 Fl_Fontdesc* fl_fonts = built_in_table; 00087 00088 #define MAXSIZE 32767 00089 00090 #define current_font (fl_fontsize->font) 00091 00092 // return dash number N, or pointer to ending null if none: 00093 const char* fl_font_word(const char* p, int n) { 00094 while (*p) {if (*p=='-') {if (!--n) break;} p++;} 00095 return p; 00096 } 00097 00098 // return a pointer to a number we think is "point size": 00099 char* fl_find_fontsize(char* name) { 00100 char* c = name; 00101 // for standard x font names, try after 7th dash: 00102 if (*c == '-') { 00103 c = (char*)fl_font_word(c,7); 00104 if (*c++ && isdigit(*c)) return c; 00105 return 0; // malformed x font name? 00106 } 00107 char* r = 0; 00108 // find last set of digits: 00109 for (c++;* c; c++) 00110 if (isdigit(*c) && !isdigit(*(c-1))) r = c; 00111 return r; 00112 } 00113 00114 const char* fl_encoding = "iso8859-1"; 00115 00116 // return true if this matches fl_encoding: 00117 int fl_correct_encoding(const char* name) { 00118 if (*name != '-') return 0; 00119 const char* c = fl_font_word(name,13); 00120 return (*c++ && !strcmp(c,fl_encoding)); 00121 } 00122 00123 static const char *find_best_font(const char *fname, int size) { 00124 int cnt; 00125 static char **list = NULL; 00126 // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: 00127 if (list) XFreeFontNames(list); 00128 list = XListFonts(fl_display, fname, 100, &cnt); 00129 if (!list) return "fixed"; 00130 00131 // search for largest <= font size: 00132 char* name = list[0]; int ptsize = 0; // best one found so far 00133 int matchedlength = 32767; 00134 char namebuffer[1024]; // holds scalable font name 00135 int found_encoding = 0; 00136 int m = cnt; if (m<0) m = -m; 00137 for (int n=0; n < m; n++) { 00138 char* thisname = list[n]; 00139 if (fl_correct_encoding(thisname)) { 00140 if (!found_encoding) ptsize = 0; // force it to choose this 00141 found_encoding = 1; 00142 } else { 00143 if (found_encoding) continue; 00144 } 00145 char* c = (char*)fl_find_fontsize(thisname); 00146 int thissize = c ? atoi(c) : MAXSIZE; 00147 int thislength = strlen(thisname); 00148 if (thissize == size && thislength < matchedlength) { 00149 // exact match, use it: 00150 name = thisname; 00151 ptsize = size; 00152 matchedlength = thislength; 00153 } else if (!thissize && ptsize!=size) { 00154 // whoa! A scalable font! Use unless exact match found: 00155 int l = c-thisname; 00156 memcpy(namebuffer,thisname,l); 00157 l += sprintf(namebuffer+l,"%d",size); 00158 while (*c == '0') c++; 00159 strcpy(namebuffer+l,c); 00160 name = namebuffer; 00161 ptsize = size; 00162 } else if (!ptsize || // no fonts yet 00163 (thissize < ptsize && ptsize > size) || // current font too big 00164 (thissize > ptsize && thissize <= size) // current too small 00165 ) { 00166 name = thisname; 00167 ptsize = thissize; 00168 matchedlength = thislength; 00169 } 00170 } 00171 00172 // if (ptsize != size) { // see if we already found this unscalable font: 00173 // for (f = s->first; f; f = f->next) { 00174 // if (f->minsize <= ptsize && f->maxsize >= ptsize) { 00175 // if (f->minsize > size) f->minsize = size; 00176 // if (f->maxsize < size) f->maxsize = size; 00177 // return f; 00178 // } 00179 // } 00180 // } 00181 // 00182 // // okay, we definately have some name, make the font: 00183 // f = new Fl_Font_Descriptor(name); 00184 // if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;} 00185 // else {f->minsize = size; f->maxsize = ptsize;} 00186 // f->next = s->first; 00187 // s->first = f; 00188 // return f; 00189 00190 return name; 00191 } 00192 00193 static char *put_font_size(const char *n, int size) 00194 { 00195 int i = 0; 00196 char *buf; 00197 const char *ptr; 00198 const char *f; 00199 char *name; 00200 int nbf = 1; 00201 name = strdup(n); 00202 while (name[i]) { 00203 if (name[i] == ',') {nbf++; name[i] = '\0';} 00204 i++; 00205 } 00206 00207 buf = (char*) malloc(nbf * 256); 00208 buf[0] = '\0'; 00209 ptr = name; 00210 i = 0; 00211 while (ptr && nbf > 0) { 00212 f = find_best_font(ptr, size); 00213 while (*f) { 00214 buf[i] = *f; 00215 f++; i++; 00216 } 00217 nbf--; 00218 while (*ptr) ptr++; 00219 if (nbf) { 00220 ptr++; 00221 buf[i] = ','; 00222 i++; 00223 } 00224 while(isspace(*ptr)) ptr++; 00225 } 00226 buf[i] = '\0'; 00227 free(name); 00228 return buf; 00229 } 00230 00231 00232 char *fl_get_font_xfld(int fnum, int size) { 00233 Fl_Fontdesc* s = fl_fonts+fnum; 00234 if (!s->name) s = fl_fonts; // use font 0 if still undefined 00235 fl_open_display(); 00236 return put_font_size(s->name, size); 00237 } 00238 00239 // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: 00240 static Fl_Font_Descriptor* find(int fnum, int size) { 00241 char *name; 00242 Fl_Fontdesc* s = fl_fonts+fnum; 00243 if (!s->name) s = fl_fonts; // use font 0 if still undefined 00244 Fl_Font_Descriptor* f; 00245 for (f = s->first; f; f = f->next) 00246 if (f->minsize <= size && f->maxsize >= size) return f; 00247 fl_open_display(); 00248 00249 name = put_font_size(s->name, size); 00250 f = new Fl_Font_Descriptor(name); 00251 f->minsize = size; 00252 f->maxsize = size; 00253 f->next = s->first; 00254 s->first = f; 00255 free(name); 00256 return f; 00257 } 00258 00259 00261 // Public interface: 00262 00263 Fl_Font fl_font_ = 0; 00264 Fl_Fontsize fl_size_ = 0; 00265 void *fl_xftfont = 0; 00266 static GC font_gc; 00267 00268 XFontStruct* Fl_XFont_On_Demand::value() { 00269 return ptr; 00270 } 00271 00272 void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { 00273 if (fnum==-1) { 00274 fl_font_ = 0; fl_size_ = 0; 00275 return; 00276 } 00277 if (fnum == fl_font_ && size == fl_size_) return; 00278 fl_font_ = fnum; fl_size_ = size; 00279 Fl_Font_Descriptor* f = find(fnum, size); 00280 if (f != fl_fontsize) { 00281 fl_fontsize = f; 00282 fl_xfont = current_font->fonts[0]; 00283 font_gc = 0; 00284 } 00285 } 00286 00287 int fl_height() { 00288 if (current_font) return (current_font->ascent + current_font->descent); 00289 else return -1; 00290 } 00291 00292 int fl_descent() { 00293 if (current_font) return current_font->descent; 00294 else return -1; 00295 } 00296 00297 double fl_width(const char* c, int n) { 00298 if (current_font) return (double) XUtf8TextWidth(current_font, c, n); 00299 else return -1; 00300 } 00301 00302 double fl_width(unsigned int c) { 00303 if (current_font) return (double) XUtf8UcsWidth(current_font, c); 00304 else return -1; 00305 } 00306 00307 00308 void fl_text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) { 00309 00310 #if defined(__GNUC__) 00311 #warning fl_text_extents is only a test stub in Xlib build at present 00312 #endif /*__GNUC__*/ 00313 00314 W = 0; H = 0; 00315 fl_measure(c, W, H, 0); 00316 dx = 0; 00317 dy = fl_descent() - H; 00318 } // fl_text_extents 00319 00320 00321 void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) { 00322 if (font_gc != fl_gc) { 00323 if (!current_font) fl_font(FL_HELVETICA, 14); 00324 font_gc = fl_gc; 00325 XSetFont(fl_display, fl_gc, current_font->fid); 00326 } 00327 XUtf8DrawString(fl_display, fl_window, current_font, fl_gc, x, y, c, n); 00328 } 00329 void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { 00330 fprintf(stderr,"ROTATING TEXT NOT IMPLEMENTED\n"); 00331 fl_draw(str, n, (int)x, (int)y); 00332 } 00333 00334 void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { 00335 if (font_gc != fl_gc) { 00336 if (!current_font) fl_font(FL_HELVETICA, 12); 00337 font_gc = fl_gc; 00338 } 00339 XUtf8DrawRtlString(fl_display, fl_window, current_font, fl_gc, x, y, c, n); 00340 } 00341 #endif // FL_DOXYGEN 00342 // 00343 // End of "$Id: fl_font_x.cxx 8126 2010-12-28 12:02:23Z manolo $". 00344 //