fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

fl_font_xft.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Xft font code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 2001-2016 Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 //
20 // Draw fonts using Keith Packard's Xft library to provide anti-
21 // aliased text. Yow!
22 //
23 // Many thanks to Carl for making the original version of this.
24 //
25 // This font code only requires libXft to work. Contrary to popular
26 // belief there is no need to have FreeType, or the Xrender extension
27 // available to use this code. You will just get normal Xlib fonts
28 // (Xft calls them "core" fonts) The Xft algorithms for choosing
29 // these is about as good as the FLTK ones (I hope to fix it so it is
30 // exactly as good...), plus it can cache its results and share them
31 // between programs, so using this should be a win in all cases. Also
32 // it should be obvious by comparing this file and fl_font_x.cxx that
33 // it is a lot easier to program with Xft than with Xlib.
34 //
35 // Also, Xft supports UTF-8 text rendering directly, which will allow
36 // us to support UTF-8 on all platforms more easily.
37 //
38 // To actually get antialiasing you need the following:
39 //
40 // 1. You have XFree86 4
41 // 2. You have the XRender extension
42 // 3. Your X device driver supports the render extension
43 // 4. You have libXft
44 // 5. Your libXft has FreeType2 support compiled in
45 // 6. You have the FreeType2 library
46 //
47 // Distributions that have XFree86 4.0.3 or later should have all of this...
48 //
49 // Unlike some other Xft packages, I tried to keep this simple and not
50 // to work around the current problems in Xft by making the "patterns"
51 // complicated. I believe doing this defeats our ability to improve Xft
52 // itself. You should edit the ~/.xftconfig file to "fix" things, there
53 // are several web pages of information on how to do this.
54 //
55 #ifndef FL_DOXYGEN
56 
57 #include <X11/Xft/Xft.h>
58 
59 #include <math.h>
60 
61 #define USE_OVERLAY 0
62 
63 // The predefined fonts that FLTK has:
65 #if 1
66 {" sans"},
67 {"Bsans"},
68 {"Isans"},
69 {"Psans"},
70 {" mono"},
71 {"Bmono"},
72 {"Imono"},
73 {"Pmono"},
74 {" serif"},
75 {"Bserif"},
76 {"Iserif"},
77 {"Pserif"},
78 {" symbol"},
79 {" screen"},
80 {"Bscreen"},
81 {" zapf dingbats"},
82 #else
83 {" helvetica"},
84 {"Bhelvetica"},
85 {"Ihelvetica"},
86 {"Phelvetica"},
87 {" courier"},
88 {"Bcourier"},
89 {"Icourier"},
90 {"Pcourier"},
91 {" times"},
92 {"Btimes"},
93 {"Itimes"},
94 {"Ptimes"},
95 {" symbol"},
96 {" lucidatypewriter"},
97 {"Blucidatypewriter"},
98 {" zapf dingbats"},
99 #endif
100 };
101 
103 
104 Fl_XFont_On_Demand fl_xfont;
105 void *fl_xftfont = 0;
106 //static const char* fl_encoding_ = "iso8859-1";
107 static const char* fl_encoding_ = "iso10646-1";
108 
109 static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
110  if (fnum==-1) { // special case to stop font caching
111  driver->Fl_Graphics_Driver::font(0, 0);
112  return;
113  }
114  Fl_Font_Descriptor* f = driver->font_descriptor();
115  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && f->angle == angle)
116  return;
117  driver->Fl_Graphics_Driver::font(fnum, size);
118  Fl_Fontdesc *font = fl_fonts + fnum;
119  // search the fontsizes we have generated already
120  for (f = font->first; f; f = f->next) {
121  if (f->size == size && f->angle == angle)// && !strcasecmp(f->encoding, fl_encoding_))
122  break;
123  }
124  if (!f) {
125  f = new Fl_Font_Descriptor(font->name, size, angle);
126  f->next = font->first;
127  font->first = f;
128  }
129  driver->font_descriptor(f);
130 #if XFT_MAJOR < 2
131  fl_xfont = f->font->u.core.font;
132 #else
133  fl_xfont = NULL; // invalidate
134 #endif // XFT_MAJOR < 2
135  fl_xftfont = (void*)f->font;
136 }
137 
139  fl_xft_font(this,fnum,size,0);
140 }
141 
142 static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angle) {
143  // Check: does it look like we have been passed an old-school XLFD fontname?
144  bool is_xlfd = false;
145  int hyphen_count = 0;
146  int comma_count = 0;
147  unsigned len = strlen(name);
148  if (len > 512) len = 512; // ensure we are not passed an unbounded font name
149  for(unsigned idx = 0; idx < len; idx++) {
150  if(name[idx] == '-') hyphen_count++; // check for XLFD hyphens
151  if(name[idx] == ',') comma_count++; // are there multiple names?
152  }
153  if(hyphen_count >= 14) is_xlfd = true; // Not a robust check, but good enough?
154 
155  fl_open_display();
156 
157  if(!is_xlfd) { // Not an XLFD - open as a XFT style name
158  XftFont *the_font = NULL; // the font we will return;
159  XftPattern *fnt_pat = XftPatternCreate(); // the pattern we will use for matching
160  int slant = XFT_SLANT_ROMAN;
161  int weight = XFT_WEIGHT_MEDIUM;
162 
163  /* This "converts" FLTK-style font names back into "regular" names, extracting
164  * the BOLD and ITALIC codes as it does so - all FLTK font names are prefixed
165  * by 'I' (italic) 'B' (bold) 'P' (bold italic) or ' ' (regular) modifiers.
166  * This gives a fairly limited font selection ability, but is retained for
167  * compatibility reasons. If you really need a more complex choice, you are best
168  * calling Fl::set_fonts(*) then selecting the font by font-index rather than by
169  * name anyway. Probably.
170  * If you want to load a font who's name does actually begin with I, B or P, you
171  * MUST use a leading space OR simply use lowercase for the name...
172  */
173  /* This may be efficient, but it is non-obvious. */
174  switch (*name++) {
175  case 'I': slant = XFT_SLANT_ITALIC; break; // italic
176  case 'P': slant = XFT_SLANT_ITALIC; // bold-italic (falls-through)
177  case 'B': weight = XFT_WEIGHT_BOLD; break; // bold
178  case ' ': break; // regular
179  default: name--; // no prefix, restore name
180  }
181 
182  if(comma_count) { // multiple comma-separated names were passed
183  char *local_name = strdup(name); // duplicate the full name so we can edit the copy
184  char *curr = local_name; // points to first name in string
185  char *nxt; // next name in string
186  do {
187  nxt = strchr(curr, ','); // find comma separator
188  if (nxt) {
189  *nxt = 0; // terminate first name
190  nxt++; // first char of next name
191  }
192 
193  // Add the current name to the match pattern
194  XftPatternAddString(fnt_pat, XFT_FAMILY, curr);
195 
196  if(nxt) curr = nxt; // move onto next name (if it exists)
197  // Now do a cut-down version of the FLTK name conversion.
198  // NOTE: we only use the slant and weight of the first name,
199  // subsequent names we ignore this for... But we still need to do the check.
200  switch (*curr++) {
201  case 'I': break; // italic
202  case 'P': // bold-italic (falls-through)
203  case 'B': break; // bold
204  case ' ': break; // regular
205  default: curr--; // no prefix, restore name
206  }
207 
208  comma_count--; // decrement name sections count
209  } while (comma_count >= 0);
210  free(local_name); // release our local copy of font names
211  }
212  else { // single name was passed - add it directly
213  XftPatternAddString(fnt_pat, XFT_FAMILY, name);
214  }
215 
216  // Construct a match pattern for the font we want...
217  XftPatternAddInteger(fnt_pat, XFT_WEIGHT, weight);
218  XftPatternAddInteger(fnt_pat, XFT_SLANT, slant);
219  XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)size);
220  XftPatternAddString (fnt_pat, XFT_ENCODING, fl_encoding_);
221 
222  // rotate font if angle!=0
223  if (angle !=0) {
224  XftMatrix m;
225  XftMatrixInit(&m);
226  XftMatrixRotate(&m,cos(M_PI*angle/180.),sin(M_PI*angle/180.));
227  XftPatternAddMatrix (fnt_pat, XFT_MATRIX,&m);
228  }
229 
230  if (core) {
231  XftPatternAddBool(fnt_pat, XFT_CORE, FcTrue);
232  XftPatternAddBool(fnt_pat, XFT_RENDER, FcFalse);
233  }
234 
235  XftPattern *match_pat; // the best available match on the system
236  XftResult match_result; // the result of our matching attempt
237 
238  // query the system to find a match for this font
239  match_pat = XftFontMatch(fl_display, fl_screen, fnt_pat, &match_result);
240 
241 #if 0 // the XftResult never seems to get set to anything... abandon this code?
242  switch(match_result) { // how good a match is this font for our request?
243  case XftResultMatch:
244  puts("Object exists with the specified ID");
245  break;
246 
247  case XftResultTypeMismatch:
248  puts("Object exists, but the type does not match");
249  break;
250 
251  case XftResultNoId:
252  puts("Object exists, but has fewer values than specified");
253  break;
254 
255  case FcResultOutOfMemory:
256  puts("FcResult: Malloc failed");
257  break;
258 
259  case XftResultNoMatch:
260  puts("Object does not exist at all");
261  break;
262 
263  default:
264  printf("Invalid XftResult status %d \n", match_result);
265  break;
266  }
267 #endif
268 
269 #if 0 // diagnostic to print the "full name" of the font we matched. This works.
270  FcChar8 *picked_name = FcNameUnparse(match_pat);
271  printf("Match: %s\n", picked_name);
272  free(picked_name);
273 #endif
274 
275  // open the matched font
276  if (match_pat) the_font = XftFontOpenPattern(fl_display, match_pat);
277 
278  if (!match_pat || !the_font) {
279  // last chance, just open any font in the right size
280  the_font = XftFontOpen (fl_display, fl_screen,
281  XFT_FAMILY, XftTypeString, "sans",
282  XFT_SIZE, XftTypeDouble, (double)size,
283  NULL);
284  XftPatternDestroy(fnt_pat);
285  if (!the_font) {
286  Fl::error("Unable to find fonts. Check your FontConfig configuration.\n");
287  exit(1);
288  }
289  return the_font;
290  }
291 
292 #if 0 // diagnostic to print the "full name" of the font we actually opened. This works.
293  FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern);
294  printf("Open : %s\n", picked_name2);
295  free(picked_name2);
296 #endif
297 
298  XftPatternDestroy(fnt_pat);
299 // XftPatternDestroy(match_pat); // FontConfig will destroy this resource for us. We must not!
300 
301  return the_font;
302  }
303  else { // We were passed a font name in XLFD format
304  /* OksiD's X font code could handle being passed a comma separated list
305  * of XLFD's. It then attempted to find which font was "best" from this list.
306  * But XftFontOpenXlfd can not do this, so if a list is passed, we just
307  * terminate it at the first comma.
308  * A "better" solution might be to use XftXlfdParse() on each of the passed
309  * XLFD's to construct a "super-pattern" that incorporates attributes from all
310  * XLFD's and use that to perform a XftFontMatch(). Maybe...
311  */
312  char *local_name = strdup(name);
313  if(comma_count) { // This means we were passed multiple XLFD's
314  char *pc = strchr(local_name, ',');
315  *pc = 0; // terminate the XLFD at the first comma
316  }
317  XftFont *the_font = XftFontOpenXlfd(fl_display, fl_screen, local_name);
318  free(local_name);
319 #if 0 // diagnostic to print the "full name" of the font we actually opened. This works.
320 puts("Font Opened"); fflush(stdout);
321  FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern);
322  printf("Open : %s\n", picked_name2); fflush(stdout);
323  free(picked_name2);
324 #endif
325  return the_font;
326  }
327 } // end of fontopen
328 
329 Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
330 // encoding = fl_encoding_;
331  size = fsize;
332  angle = fangle;
333 #if HAVE_GL
334  listbase = 0;
335 #endif // HAVE_GL
336  font = fontopen(name, fsize, false, angle);
337 }
338 
341 // XftFontClose(fl_display, font);
342 }
343 
344 /* decodes the input UTF-8 string into a series of wchar_t characters.
345  n is set upon return to the number of characters.
346  Don't deallocate the returned memory.
347  */
348 static const wchar_t *utf8reformat(const char *str, int& n)
349 {
350  static const wchar_t empty[] = {0};
351  static wchar_t *buffer;
352  static int lbuf = 0;
353  int newn;
354  if (n == 0) return empty;
355  newn = fl_utf8towc(str, n, (wchar_t*)buffer, lbuf);
356  if (newn >= lbuf) {
357  lbuf = newn + 100;
358  if (buffer) free(buffer);
359  buffer = (wchar_t*)malloc(lbuf * sizeof(wchar_t));
360  n = fl_utf8towc(str, n, (wchar_t*)buffer, lbuf);
361  } else {
362  n = newn;
363  }
364  return buffer;
365 }
366 
367 static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents)
368 {
369  memset(extents, 0, sizeof(XGlyphInfo));
370  const wchar_t *buffer = utf8reformat(str, n);
371 #ifdef __CYGWIN__
372  XftTextExtents16(fl_display, desc->font, (XftChar16 *)buffer, n, extents);
373 #else
374  XftTextExtents32(fl_display, desc->font, (XftChar32 *)buffer, n, extents);
375 #endif
376 }
377 
380  else return -1;
381 }
382 
384  if (font_descriptor()) return font_descriptor()->font->descent;
385  else return -1;
386 }
387 
388 double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
389  if (!font_descriptor()) return -1.0;
390  XGlyphInfo i;
391  utf8extents(font_descriptor(), str, n, &i);
392  return i.xOff;
393 }
394 
395 /*double fl_width(uchar c) {
396  return fl_graphics_driver->width((const char *)(&c), 1);
397 }*/
398 
399 static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
400  if (!desc) return -1.0;
401  XGlyphInfo i;
402  XftTextExtents32(fl_display, desc->font, str, n, &i);
403  return i.xOff;
404 }
405 
406 double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
407  return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
408 }
409 
410 void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
411  if (!font_descriptor()) {
412  w = h = 0;
413  dx = dy = 0;
414  return;
415  }
416  XGlyphInfo gi;
417  utf8extents(font_descriptor(), c, n, &gi);
418 
419  w = gi.width;
420  h = gi.height;
421  dx = -gi.x;
422  dy = -gi.y;
423 } // fl_text_extents
424 
425 
426 /* This code is used (mainly by opengl) to get a bitmapped font. The
427  * original XFT-1 code used XFT's "core" fonts methods to load an XFT
428  * font that was actually a X-bitmap font, that could then be readily
429  * used with GL. But XFT-2 does not provide that ability, and there
430  * is no easy method to use an XFT font directly with GL. So...
431 */
432 
433 # if XFT_MAJOR > 1
434 // This function attempts, on XFT2 systems, to find a suitable "core" Xfont
435 // for GL or other bitmap font needs (we dont have an XglUseXftFont(...) function.)
436 // There's probably a better way to do this. I can't believe it is this hard...
437 // Anyway... This code attempts to make an XLFD out of the fltk-style font
438 // name it is passed, then tries to load that font. Surprisingly, this quite
439 // often works - boxes that have XFT generally also have a fontserver that
440 // can serve TTF and other fonts to X, and so the font name that fltk makes
441 // from the XFT name often also "exists" as an "core" X font...
442 // If this code fails to load the requested font, it falls back through a
443 // series of tried 'n tested alternatives, ultimately resorting to what the
444 // original fltk code did.
445 // NOTE: On my test boxes (FC6, FC7, FC8, ubuntu8.04, 9.04, 9.10) this works
446 // well for the fltk "built-in" font names.
447 static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
448  XFontStruct* xgl_font = 0;
449  int size = driver->size();
450  int fnum = driver->font();
451  const char *wt_med = "medium";
452  const char *wt_bold = "bold";
453  const char *weight = wt_med; // no specifc weight requested - accept any
454  char slant = 'r'; // regular non-italic by default
455  char xlfd[128]; // we will put our synthetic XLFD in here
456  char *pc = strdup(fl_fonts[fnum].name); // what font were we asked for?
457  const char *name = pc; // keep a handle to the original name for freeing later
458  // Parse the "fltk-name" of the font
459  switch (*name++) {
460  case 'I': slant = 'i'; break; // italic
461  case 'P': slant = 'i'; // bold-italic (falls-through)
462  case 'B': weight = wt_bold; break; // bold
463  case ' ': break; // regular
464  default: name--; // no prefix, restore name
465  }
466 
467  // first, we do a query with no prefered size, to see if the font exists at all
468  snprintf(xlfd, 128, "-*-%s-%s-%c-*--*-*-*-*-*-*-*-*", name, weight, slant); // make up xlfd style name
469  xgl_font = XLoadQueryFont(fl_display, xlfd);
470  if(xgl_font) { // the face exists, but can we get it in a suitable size?
471  XFreeFont(fl_display, xgl_font); // release the non-sized version
472  snprintf(xlfd, 128, "-*-%s-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10));
473  xgl_font = XLoadQueryFont(fl_display, xlfd); // attempt to load the font at the right size
474  }
475 //puts(xlfd);
476 
477  // try alternative names
478  if (!xgl_font) {
479  if (!strcmp(name, "sans")) {
480  name = "helvetica";
481  } else if (!strcmp(name, "mono")) {
482  name = "courier";
483  } else if (!strcmp(name, "serif")) {
484  name = "times";
485  } else if (!strcmp(name, "screen")) {
486  name = "lucidatypewriter";
487  } else if (!strcmp(name, "dingbats")) {
488  name = "zapf dingbats";
489  }
490  snprintf(xlfd, 128, "-*-*%s*-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10));
491  xgl_font = XLoadQueryFont(fl_display, xlfd);
492  }
493  free(pc); // release our copy of the font name
494 
495  // if we have nothing loaded, try a generic proportional font
496  if(!xgl_font) {
497  snprintf(xlfd, 128, "-*-helvetica-*-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10));
498  xgl_font = XLoadQueryFont(fl_display, xlfd);
499  }
500  // If that still didn't work, try courier with resquested weight and slant
501  if(!xgl_font && weight != wt_med) {
502  snprintf(xlfd, 128, "-*-courier*-%s-%c-*--*-%d-*-*-*-*-*-*", weight, slant, (size*10));
503  xgl_font = XLoadQueryFont(fl_display, xlfd);
504  }
505  // If that still didn't work, try this instead
506  if(!xgl_font) {
507  snprintf(xlfd, 128, "-*-courier*-medium-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10));
508  xgl_font = XLoadQueryFont(fl_display, xlfd);
509  }
510 //printf("glf: %d\n%s\n%s\n", size, xlfd, fl_fonts[fl_font_].name);
511 //if(xgl_font) puts("ok");
512 
513  // Last chance fallback - this usually loads something...
514  if (!xgl_font) xgl_font = XLoadQueryFont(fl_display, "fixed");
515 
516  return xgl_font;
517 } // end of load_xfont_for_xft2
518 # endif
519 
520 static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) {
521 # if XFT_MAJOR > 1
522  // kludge! XFT 2 and later does not provide core fonts for us to use with GL
523  // try to load a bitmap X font instead
524  static XFontStruct* xgl_font = 0;
525  static int glsize = 0;
526  static int glfont = -1;
527  // Do we need to load a new font?
528  if ((!xgl_font) || (glsize != driver->size()) || (glfont != driver->font())) {
529  // create a dummy XLFD for some font of the appropriate size...
530  if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea
531  glsize = driver->size(); // record current font size
532  glfont = driver->font(); // and face
533  xgl_font = load_xfont_for_xft2(driver);
534  }
535  return xgl_font;
536 # else // XFT-1 provides a means to load a "core" font directly
537  if (driver->font_descriptor()->font->core) {
538  return driver->font_descriptor()->font->u.core.font; // is the current font a "core" font? If so, use it.
539  }
540  static XftFont* xftfont;
541  if (xftfont) XftFontClose (fl_display, xftfont);
542  xftfont = fontopen(fl_fonts[driver->font()].name, driver->size(), true, 0); // else request XFT to load a suitable "core" font instead.
543  return xftfont->u.core.font;
544 # endif // XFT_MAJOR > 1
545 }
546 
547 XFontStruct* Fl_XFont_On_Demand::value() {
548  if (!ptr) ptr = fl_xxfont(fl_graphics_driver);
549  return ptr;
550 }
551 
552 #if USE_OVERLAY
553 // Currently Xft does not work with colormapped visuals, so this probably
554 // does not work unless you have a true-color overlay.
555 extern bool fl_overlay;
556 extern Colormap fl_overlay_colormap;
557 extern XVisualInfo* fl_overlay_visual;
558 #endif
559 
560 // For some reason Xft produces errors if you destroy a window whose id
561 // still exists in an XftDraw structure. It would be nice if this is not
562 // true, a lot of junk is needed to try to stop this:
563 
564 static XftDraw* draw_;
566 #if USE_OVERLAY
567 static XftDraw* draw_overlay;
568 static Window draw_overlay_window;
569 #endif
570 
572  if (id == draw_window)
573  XftDrawChange(draw_, draw_window = fl_message_window);
574 #if USE_OVERLAY
575  if (id == draw_overlay_window)
576  XftDrawChange(draw_overlay, draw_overlay_window = fl_message_window);
577 #endif
578 }
579 
580 void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
581  if ( !this->font_descriptor() ) {
583  }
584 #if USE_OVERLAY
585  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
586  if (fl_overlay) {
587  if (!draw_)
588  draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
589  fl_overlay_visual->visual, fl_overlay_colormap);
590  else //if (draw_overlay_window != fl_window)
591  XftDrawChange(draw_, draw_overlay_window = fl_window);
592  } else
593 #endif
594  if (!draw_)
595  draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
596  fl_visual->visual, fl_colormap);
597  else //if (draw_window != fl_window)
598  XftDrawChange(draw_, draw_window = fl_window);
599 
600  Region region = fl_clip_region();
601  if (region && XEmptyRegion(region)) return;
602  XftDrawSetClip(draw_, region);
603 
604  // Use fltk's color allocator, copy the results to match what
605  // XftCollorAllocValue returns:
606  XftColor color;
609  color.color.red = ((int)r)*0x101;
610  color.color.green = ((int)g)*0x101;
611  color.color.blue = ((int)b)*0x101;
612  color.color.alpha = 0xffff;
613 
614  const wchar_t *buffer = utf8reformat(str, n);
615 #ifdef __CYGWIN__
616  XftDrawString16(draw_, &color, font_descriptor()->font, x, y, (XftChar16 *)buffer, n);
617 #else
618  XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
619 #endif
620 }
621 
622 void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
623  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
624  this->draw(str, n, (int)x, (int)y);
625  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
626 }
627 
628 static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, int x, int y) {
629 #if USE_OVERLAY
630  XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
631  if (fl_overlay) {
632  if (!draw_)
633  draw_ = XftDrawCreate(fl_display, draw_overlay_window = fl_window,
634  fl_overlay_visual->visual, fl_overlay_colormap);
635  else //if (draw_overlay_window != fl_window)
636  XftDrawChange(draw_, draw_overlay_window = fl_window);
637  } else
638 #endif
639  if (!draw_)
640  draw_ = XftDrawCreate(fl_display, draw_window = fl_window,
641  fl_visual->visual, fl_colormap);
642  else //if (draw_window != fl_window)
643  XftDrawChange(draw_, draw_window = fl_window);
644 
645  Region region = fl_clip_region();
646  if (region && XEmptyRegion(region)) return;
647  XftDrawSetClip(draw_, region);
648 
649  // Use fltk's color allocator, copy the results to match what
650  // XftCollorAllocValue returns:
651  XftColor color;
652  color.pixel = fl_xpixel(driver->color());
653  uchar r,g,b; Fl::get_color(driver->color(), r,g,b);
654  color.color.red = ((int)r)*0x101;
655  color.color.green = ((int)g)*0x101;
656  color.color.blue = ((int)b)*0x101;
657  color.color.alpha = 0xffff;
658 
659  XftDrawString32(draw_, &color, driver->font_descriptor()->font, x, y, (FcChar32 *)str, n);
660 }
661 
662 
663 void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
664 
665 #if defined(__GNUC__)
666 // FIXME: warning Need to improve this XFT right to left draw function
667 #endif /*__GNUC__*/
668 
669 // This actually draws LtoR, but aligned to R edge with the glyph order reversed...
670 // but you can't just byte-rev a UTF-8 string, that isn't valid.
671 // You can reverse a UCS4 string though...
672  int num_chars, wid, utf_len = strlen(c);
673  FcChar8 *u8 = (FcChar8 *)c;
674  FcBool valid = FcUtf8Len(u8, utf_len, &num_chars, &wid);
675  if (!valid)
676  {
677  // badly formed Utf-8 input string
678  return;
679  }
680  if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array
681  FcChar32 *ucs_txt = new FcChar32[n+1];
682  FcChar32* pu;
683  int out, sz;
684  ucs_txt[n] = 0;
685  out = n-1;
686  while ((out >= 0) && (utf_len > 0))
687  {
688  pu = &ucs_txt[out];
689  sz = FcUtf8ToUcs4(u8, pu, utf_len);
690  utf_len = utf_len - sz;
691  u8 = u8 + sz;
692  out = out - 1;
693  }
694  // Now we have a UCS4 version of the input text, reversed, in ucs_txt
695  int offs = (int)fl_xft_width(font_descriptor(), ucs_txt, n);
696  fl_drawUCS4(this, ucs_txt, n, (x-offs), y);
697 
698  delete[] ucs_txt;
699 }
700 #endif
701 
702 //
703 // End of "$Id$"
704 //
fl_xpixel
ulong fl_xpixel(Fl_Color i)
Definition: fl_color.cxx:203
fl_encoding_
static const char * fl_encoding_
Definition: fl_font_xft.cxx:107
fl_utf8towc
unsigned fl_utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen)
Definition: fl_utf.c:500
Fl_Graphics_Driver::color
Fl_Color color()
see fl_color(void).
Definition: Fl_Device.H:402
fl_message_window
Window fl_message_window
Definition: Fl_x.cxx:315
Fl_Xlib_Graphics_Driver::rtl_draw
void rtl_draw(const char *str, int n, int x, int y)
see fl_rtl_draw(const char *str, int n, int x, int y).
Definition: fl_font_x.cxx:331
M_PI
#define M_PI
Definition: math.h:38
Fl_Fontdesc
Definition: Fl_Font.H:86
fl_fonts
Fl_Fontdesc * fl_fonts
Definition: fl_font_xft.cxx:102
Fl_Graphics_Driver::fl_clip_region
friend Fl_Region fl_clip_region()
Definition: fl_draw.H:140
Fl_Graphics_Driver::font
virtual void font(Fl_Font face, Fl_Fontsize fsize)
see fl_font(Fl_Font face, Fl_Fontsize size).
Definition: Fl_Device.H:386
free
void free()
Fl_Graphics_Driver::font
Fl_Font font()
see fl_font(void).
Definition: Fl_Device.H:388
NULL
#define NULL
Definition: forms.H:34
draw_
static XftDraw * draw_
Definition: fl_font_xft.cxx:564
fl_visual
XVisualInfo * fl_visual
Definition: Fl_x.cxx:317
built_in_table
static Fl_Fontdesc built_in_table[]
Definition: fl_font_xft.cxx:64
b
long b
Definition: jpegint.h:397
snprintf
#define snprintf
Definition: flstring.h:64
Fl_Xlib_Graphics_Driver
The Xlib-specific graphics class.
Definition: Fl_Device.H:507
Fl_Xlib_Graphics_Driver::descent
int descent()
see fl_descent().
Definition: fl_font_x.cxx:278
Fl_Fontdesc::name
const char * name
Definition: Fl_Font.H:87
fl_colormap
Colormap fl_colormap
Definition: Fl_x.cxx:318
buffer
static char * buffer
Definition: file.cxx:215
math.h
Fl_Font_Descriptor::font
XUtf8FontStruct * font
Definition: Fl_Font.H:69
XUtf8FontStruct::descent
int descent
Definition: Xutf8.h:37
Fl::get_color
static unsigned get_color(Fl_Color i)
Definition: fl_color.cxx:359
fl_xftfont
void * fl_xftfont
Definition: fl_font_xft.cxx:105
utf8extents
static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents)
Definition: fl_font_xft.cxx:367
FL_HELVETICA
const Fl_Font FL_HELVETICA
Helvetica (or Arial) normal (0)
Definition: Enumerations.H:879
Fl_Graphics_Driver::color
virtual void color(Fl_Color c)
see fl_color(Fl_Color c).
Definition: Fl_Device.H:260
Fl_Fontsize
int Fl_Fontsize
Definition: Enumerations.H:906
fl_xft_font
static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle)
Definition: fl_font_xft.cxx:109
fl_drawUCS4
static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, int x, int y)
Definition: fl_font_xft.cxx:628
fl_display
FL_EXPORT HINSTANCE fl_display
END TIMERS.
Definition: Fl_win32.cxx:2147
FL_NORMAL_SIZE
Fl_Fontsize FL_NORMAL_SIZE
normal font size
Definition: Fl_Widget.cxx:117
fl_graphics_driver
FL_EXPORT Fl_Graphics_Driver * fl_graphics_driver
Points to the driver that currently receives all graphics requests.
Definition: Fl_Device.cxx:50
fl_xxfont
static XFontStruct * fl_xxfont(Fl_Graphics_Driver *driver)
Definition: fl_font_xft.cxx:520
XUtf8FontStruct::ascent
int ascent
Definition: Xutf8.h:36
Fl_Fontdesc::first
Fl_Font_Descriptor * first
Definition: Fl_Font.H:89
Fl_Xlib_Graphics_Driver::draw
void draw(const char *str, int n, int x, int y)
see fl_draw(const char *str, int n, int x, int y).
Definition: fl_font_x.cxx:311
color
void color(int n)
Definition: gl2opengl.h:29
Fl_Xlib_Graphics_Driver::height
int height()
see fl_height().
Definition: fl_font_x.cxx:273
utf8reformat
static const wchar_t * utf8reformat(const char *str, int &n)
Definition: fl_font_xft.cxx:348
fl_xft_width
static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n)
Definition: fl_font_xft.cxx:399
fl_clip_region
void fl_clip_region(Fl_Region r)
Definition: fl_draw.H:136
x
int x
Definition: test.c:73
Fl_Graphics_Driver
A virtual class subclassed for each graphics driver FLTK uses. Typically, FLTK applications do not us...
Definition: Fl_Device.H:110
Fl_Font
int Fl_Font
Definition: Enumerations.H:877
Fl_Font_Descriptor::Fl_Font_Descriptor
FL_EXPORT Fl_Font_Descriptor(const char *xfontname)
Definition: fl_font_mac.cxx:36
Fl_Xlib_Graphics_Driver::text_extents
void text_extents(const char *, int n, int &dx, int &dy, int &w, int &h)
see fl_text_extents(const char*, int n, int& dx, int& dy, int& w, int& h).
Definition: fl_font_x.cxx:293
Fl_Graphics_Driver::size
Fl_Fontsize size()
see fl_size().
Definition: Fl_Device.H:390
draw_window
static Window draw_window
Definition: fl_font_xft.cxx:565
dy
uchar dy
Definition: fl_boxtype.cxx:286
Fl_Xlib_Graphics_Driver::width
double width(const char *str, int n)
see fl_width(const char *str, int n).
Definition: fl_font_x.cxx:283
y
int y
Definition: test.c:74
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
malloc
voidp malloc()
gi
static int gi
Definition: fl_draw_image.cxx:68
fl_xfont
Fl_XFont_On_Demand fl_xfont
Definition: fl_font_xft.cxx:104
Fl_Font_Descriptor::size
Fl_Fontsize size
Definition: Fl_Font.H:45
fl_overlay
#define fl_overlay
Definition: fl_color.cxx:115
Fl_Graphics_Driver::n
int n
Definition: Fl_Device.H:124
fl_destroy_xft_draw
void fl_destroy_xft_draw(Window id)
Definition: fl_font_xft.cxx:571
Fl::error
static void(* error)(const char *,...)
Definition: Fl.H:513
fl_screen
int fl_screen
Definition: Fl_x.cxx:316
fl_open_display
void fl_open_display()
Definition: Fl_win32.cxx:496
uchar
unsigned char uchar
Definition: fl_types.h:30
name
static const char * name
Definition: Fl_arg.cxx:53
fl_window
FL_EXPORT Window fl_window
Definition: Fl_win32.cxx:2571
fontopen
static XftFont * fontopen(const char *name, Fl_Fontsize size, bool core, int angle)
Definition: fl_font_xft.cxx:142
Window
class FLWindow * Window
Definition: mac.H:32
dx
uchar dx
Definition: fl_boxtype.cxx:286
Fl_Font_Descriptor::~Fl_Font_Descriptor
FL_EXPORT ~Fl_Font_Descriptor()
Definition: fl_font_mac.cxx:155
Fl_Graphics_Driver::font_descriptor
Fl_Font_Descriptor * font_descriptor()
Definition: Fl_Device.H:404
Fl_Font_Descriptor
Definition: Fl_Font.H:41