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)  

fl_font_x.cxx

Go to the documentation of this file.
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 //