2 // "$Id: fl_font_x.cxx 8446 2011-02-19 18:03:43Z manolo $"
4 // Standard X11 font selection code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2011 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name
) {
30 font
= XCreateUtf8FontStruct(fl_display
, name
);
32 Fl::warning("bad font: %s", name
);
33 font
= XCreateUtf8FontStruct(fl_display
, "fixed");
37 for (int u
= 0; u
< 64; u
++) glok
[u
] = 0;
41 Fl_XFont_On_Demand fl_xfont
;
43 Fl_Font_Descriptor::~Fl_Font_Descriptor() {
45 // Delete list created by gl_draw(). This is not done by this code
46 // as it will link in GL unnecessarily. There should be some kind
47 // of "free" routine pointer, or a subclass?
49 // int base = font->min_char_or_byte2;
50 // int size = font->max_char_or_byte2-base+1;
51 // int base = 0; int size = 256;
52 // glDeleteLists(listbase+base,size);
55 if (this == fl_graphics_driver
->font_descriptor()) {
56 fl_graphics_driver
->font_descriptor(NULL
);
59 XFreeUtf8FontStruct(fl_display
, font
);
62 ////////////////////////////////////////////////////////////////
64 // WARNING: if you add to this table, you must redefine FL_FREE_FONT
65 // in Enumerations.H & recompile!!
66 static Fl_Fontdesc built_in_table
[] = {
67 {"-*-helvetica-medium-r-normal--*"},
68 {"-*-helvetica-bold-r-normal--*"},
69 {"-*-helvetica-medium-o-normal--*"},
70 {"-*-helvetica-bold-o-normal--*"},
71 {"-*-courier-medium-r-normal--*"},
72 {"-*-courier-bold-r-normal--*"},
73 {"-*-courier-medium-o-normal--*"},
74 {"-*-courier-bold-o-normal--*"},
75 {"-*-times-medium-r-normal--*"},
76 {"-*-times-bold-r-normal--*"},
77 {"-*-times-medium-i-normal--*"},
78 {"-*-times-bold-i-normal--*"},
80 {"-*-lucidatypewriter-medium-r-normal-sans-*"},
81 {"-*-lucidatypewriter-bold-r-normal-sans-*"},
82 {"-*-*zapf dingbats-*"}
85 Fl_Fontdesc
* fl_fonts
= built_in_table
;
89 // return dash number N, or pointer to ending null if none:
90 const char* fl_font_word(const char* p
, int n
) {
91 while (*p
) {if (*p
=='-') {if (!--n
) break;} p
++;}
95 // return a pointer to a number we think is "point size":
96 char* fl_find_fontsize(char* name
) {
98 // for standard x font names, try after 7th dash:
100 c
= (char*)fl_font_word(c
,7);
101 if (*c
++ && isdigit(*c
)) return c
;
102 return 0; // malformed x font name?
105 // find last set of digits:
107 if (isdigit(*c
) && !isdigit(*(c
-1))) r
= c
;
111 //const char* fl_encoding = "iso8859-1";
112 const char* fl_encoding
= "iso10646-1";
114 // return true if this matches fl_encoding:
115 int fl_correct_encoding(const char* name
) {
116 if (*name
!= '-') return 0;
117 const char* c
= fl_font_word(name
,13);
118 return (*c
++ && !strcmp(c
,fl_encoding
));
121 static const char *find_best_font(const char *fname
, int size
) {
123 static char **list
= NULL
;
124 // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
125 if (list
) XFreeFontNames(list
);
126 list
= XListFonts(fl_display
, fname
, 100, &cnt
);
127 if (!list
) return "fixed";
129 // search for largest <= font size:
130 char* name
= list
[0]; int ptsize
= 0; // best one found so far
131 int matchedlength
= 32767;
132 char namebuffer
[1024]; // holds scalable font name
133 int found_encoding
= 0;
134 int m
= cnt
; if (m
<0) m
= -m
;
135 for (int n
=0; n
< m
; n
++) {
136 char* thisname
= list
[n
];
137 if (fl_correct_encoding(thisname
)) {
138 if (!found_encoding
) ptsize
= 0; // force it to choose this
141 if (found_encoding
) continue;
143 char* c
= (char*)fl_find_fontsize(thisname
);
144 int thissize
= c
? atoi(c
) : MAXSIZE
;
145 int thislength
= strlen(thisname
);
146 if (thissize
== size
&& thislength
< matchedlength
) {
147 // exact match, use it:
150 matchedlength
= thislength
;
151 } else if (!thissize
&& ptsize
!=size
) {
152 // whoa! A scalable font! Use unless exact match found:
154 memcpy(namebuffer
,thisname
,l
);
155 l
+= sprintf(namebuffer
+l
,"%d",size
);
156 while (*c
== '0') c
++;
157 strcpy(namebuffer
+l
,c
);
160 } else if (!ptsize
|| // no fonts yet
161 (thissize
< ptsize
&& ptsize
> size
) || // current font too big
162 (thissize
> ptsize
&& thissize
<= size
) // current too small
166 matchedlength
= thislength
;
170 // if (ptsize != size) { // see if we already found this unscalable font:
171 // for (f = s->first; f; f = f->next) {
172 // if (f->minsize <= ptsize && f->maxsize >= ptsize) {
173 // if (f->minsize > size) f->minsize = size;
174 // if (f->maxsize < size) f->maxsize = size;
180 // // okay, we definately have some name, make the font:
181 // f = new Fl_Font_Descriptor(name);
182 // if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;}
183 // else {f->minsize = size; f->maxsize = ptsize;}
184 // f->next = s->first;
191 static char *put_font_size(const char *n
, int size
)
201 if (name
[i
] == ',') {nbf
++; name
[i
] = '\0';}
205 buf
= (char*) malloc(nbf
* 256);
209 while (ptr
&& nbf
> 0) {
210 f
= find_best_font(ptr
, size
);
222 while(isspace(*ptr
)) ptr
++;
230 char *fl_get_font_xfld(int fnum
, int size
) {
231 Fl_Fontdesc
* s
= fl_fonts
+fnum
;
232 if (!s
->name
) s
= fl_fonts
; // use font 0 if still undefined
234 return put_font_size(s
->name
, size
);
237 // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
238 static Fl_Font_Descriptor
* find(int fnum
, int size
) {
240 Fl_Fontdesc
* s
= fl_fonts
+fnum
;
241 if (!s
->name
) s
= fl_fonts
; // use font 0 if still undefined
242 Fl_Font_Descriptor
* f
;
243 for (f
= s
->first
; f
; f
= f
->next
)
244 if (f
->size
== size
) return f
;
247 name
= put_font_size(s
->name
, size
);
248 f
= new Fl_Font_Descriptor(name
);
257 ////////////////////////////////////////////////////////////////
260 void *fl_xftfont
= 0;
263 XFontStruct
* Fl_XFont_On_Demand::value() {
267 void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum
, Fl_Fontsize size
) {
269 Fl_Graphics_Driver::font(0, 0);
272 if (fnum
== Fl_Graphics_Driver::font() && size
== Fl_Graphics_Driver::size()) return;
273 Fl_Graphics_Driver::font(fnum
, size
);
274 Fl_Font_Descriptor
* f
= find(fnum
, size
);
275 if (f
!= this->font_descriptor()) {
276 this->font_descriptor(f
);
277 fl_xfont
= f
->font
->fonts
[0];
282 int Fl_Xlib_Graphics_Driver::height() {
283 if (font_descriptor()) return font_descriptor()->font
->ascent
+ font_descriptor()->font
->descent
;
287 int Fl_Xlib_Graphics_Driver::descent() {
288 if (font_descriptor()) return font_descriptor()->font
->descent
;
292 double Fl_Xlib_Graphics_Driver::width(const char* c
, int n
) {
293 if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font
, c
, n
);
297 double Fl_Xlib_Graphics_Driver::width(unsigned int c
) {
298 if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font
, c
);
302 void Fl_Xlib_Graphics_Driver::text_extents(const char *c
, int n
, int &dx
, int &dy
, int &W
, int &H
) {
303 if (font_gc
!= fl_gc
) {
304 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
306 XSetFont(fl_display
, fl_gc
, font_descriptor()->font
->fid
);
309 xx
= yy
= ww
= hh
= 0;
310 if (fl_gc
) XUtf8_measure_extents(fl_display
, fl_window
, font_descriptor()->font
, fl_gc
, &xx
, &yy
, &ww
, &hh
, c
, n
);
312 W
= ww
; H
= hh
; dx
= xx
; dy
= yy
;
313 // This is the safe but mostly wrong thing we used to do...
315 // fl_measure(c, W, H, 0);
317 // dy = fl_descent() - H;
320 void Fl_Xlib_Graphics_Driver::draw(const char* c
, int n
, int x
, int y
) {
321 if (font_gc
!= fl_gc
) {
322 if (!font_descriptor()) this->font(FL_HELVETICA
, FL_NORMAL_SIZE
);
324 XSetFont(fl_display
, fl_gc
, font_descriptor()->font
->fid
);
326 if (fl_gc
) XUtf8DrawString(fl_display
, fl_window
, font_descriptor()->font
, fl_gc
, x
, y
, c
, n
);
329 void Fl_Xlib_Graphics_Driver::draw(int angle
, const char *str
, int n
, int x
, int y
) {
330 fprintf(stderr
,"ROTATING TEXT NOT IMPLEMENTED\n");
331 this->draw(str
, n
, (int)x
, (int)y
);
334 void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c
, int n
, int x
, int y
) {
335 if (font_gc
!= fl_gc
) {
336 if (!font_descriptor()) this->font(FL_HELVETICA
, FL_NORMAL_SIZE
);
339 if (fl_gc
) XUtf8DrawRtlString(fl_display
, fl_window
, font_descriptor()->font
, fl_gc
, x
, y
, c
, n
);
343 // End of "$Id: fl_font_x.cxx 8446 2011-02-19 18:03:43Z manolo $".