FLTK 1.3.9: fl_font_x.cxx Source File

FLTK 1.3.9

Loading...
Searching...
No Matches
fl_font_x.cxx
1//
2// "$Id$"
3//
4// Standard X11 font selection code for the Fast Light Tool Kit (FLTK).
5//
6// Copyright 1998-2016 by 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#ifndef FL_DOXYGEN
19
20Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) {
21 font = XCreateUtf8FontStruct(fl_display, name);
22 if (!font) {
23 Fl::warning("bad font: %s", name);
24 font = XCreateUtf8FontStruct(fl_display, "fixed");
25 }
26# if HAVE_GL
27 listbase = 0;
28 for (int u = 0; u < 64; u++) glok[u] = 0;
29# endif
30}
31
32Fl_XFont_On_Demand fl_xfont;
33
34Fl_Font_Descriptor::~Fl_Font_Descriptor() {
35# if HAVE_GL
36// Delete list created by gl_draw(). This is not done by this code
37// as it will link in GL unnecessarily. There should be some kind
38// of "free" routine pointer, or a subclass?
39// if (listbase) {
40// int base = font->min_char_or_byte2;
41// int size = font->max_char_or_byte2-base+1;
42// int base = 0; int size = 256;
43// glDeleteLists(listbase+base,size);
44// }
45# endif
46 if (this == fl_graphics_driver->font_descriptor()) {
47 fl_graphics_driver->font_descriptor(NULL);
48 fl_xfont = 0;
49 }
50 XFreeUtf8FontStruct(fl_display, font);
51}
52
54
55// WARNING: if you add to this table, you must redefine FL_FREE_FONT
56// in Enumerations.H & recompile!!
57static Fl_Fontdesc built_in_table[] = {
58{"-*-helvetica-medium-r-normal--*"},
59{"-*-helvetica-bold-r-normal--*"},
60{"-*-helvetica-medium-o-normal--*"},
61{"-*-helvetica-bold-o-normal--*"},
62{"-*-courier-medium-r-normal--*"},
63{"-*-courier-bold-r-normal--*"},
64{"-*-courier-medium-o-normal--*"},
65{"-*-courier-bold-o-normal--*"},
66{"-*-times-medium-r-normal--*"},
67{"-*-times-bold-r-normal--*"},
68{"-*-times-medium-i-normal--*"},
69{"-*-times-bold-i-normal--*"},
70{"-*-symbol-*"},
71{"-*-lucidatypewriter-medium-r-normal-sans-*"},
72{"-*-lucidatypewriter-bold-r-normal-sans-*"},
73{"-*-*zapf dingbats-*"}
74};
75
76 Fl_Fontdesc* fl_fonts = built_in_table;
77
78#define MAXSIZE 32767
79
80// return dash number N, or pointer to ending null if none:
81const char* fl_font_word(const char* p, int n) {
82 while (*p) {if (*p=='-') {if (!--n) break;} p++;}
83 return p;
84}
85
86// return a pointer to a number we think is "point size":
87char* fl_find_fontsize(char* name) {
88 char* c = name;
89 // for standard x font names, try after 7th dash:
90 if (*c == '-') {
91 c = (char*)fl_font_word(c,7);
92 if (*c++ && isdigit(*c)) return c;
93 return 0; // malformed x font name?
94 }
95 char* r = 0;
96 // find last set of digits:
97 for (c++;* c; c++)
98 if (isdigit(*c) && !isdigit(*(c-1))) r = c;
99 return r;
100}
101
102//const char* fl_encoding = "iso8859-1";
103const char* fl_encoding = "iso10646-1";
104
105// return true if this matches fl_encoding:
106int fl_correct_encoding(const char* name) {
107 if (*name != '-') return 0;
108 const char* c = fl_font_word(name,13);
109 return (*c++ && !strcmp(c,fl_encoding));
110}
111
112static const char *find_best_font(const char *fname, int size) {
113 int cnt;
114 static char **list = NULL;
115// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
116 if (list) XFreeFontNames(list);
117 list = XListFonts(fl_display, fname, 100, &cnt);
118 if (!list) return "fixed";
119
120 // search for largest <= font size:
121 char* name = list[0]; int ptsize = 0; // best one found so far
122 int matchedlength = 32767;
123 static char namebuffer[1024]; // holds scalable font name
124 int found_encoding = 0;
125 int m = cnt; if (m<0) m = -m;
126 for (int n=0; n < m; n++) {
127 char* thisname = list[n];
128 if (fl_correct_encoding(thisname)) {
129 if (!found_encoding) ptsize = 0; // force it to choose this
130 found_encoding = 1;
131 } else {
132 if (found_encoding) continue;
133 }
134 char* c = (char*)fl_find_fontsize(thisname);
135 int thissize = c ? atoi(c) : MAXSIZE;
136 int thislength = strlen(thisname);
137 if (thissize == size && thislength < matchedlength) {
138 // exact match, use it:
139 name = thisname;
140 ptsize = size;
141 matchedlength = thislength;
142 } else if (!thissize && ptsize!=size) {
143 // whoa! A scalable font! Use unless exact match found:
144 int l = c-thisname;
145 memcpy(namebuffer,thisname,l);
146 l += sprintf(namebuffer+l,"%d",size);
147 while (*c == '0') c++;
148 strcpy(namebuffer+l,c);
149 name = namebuffer;
150 ptsize = size;
151 } else if (!ptsize || // no fonts yet
152 (thissize < ptsize && ptsize > size) || // current font too big
153 (thissize > ptsize && thissize <= size) // current too small
154 ) {
155 name = thisname;
156 ptsize = thissize;
157 matchedlength = thislength;
158 }
159 }
160
161// if (ptsize != size) { // see if we already found this unscalable font:
162// for (f = s->first; f; f = f->next) {
163// if (f->minsize <= ptsize && f->maxsize >= ptsize) {
164// if (f->minsize > size) f->minsize = size;
165// if (f->maxsize < size) f->maxsize = size;
166// return f;
167// }
168// }
169// }
170//
171// // okay, we definately have some name, make the font:
172// f = new Fl_Font_Descriptor(name);
173// if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;}
174// else {f->minsize = size; f->maxsize = ptsize;}
175// f->next = s->first;
176// s->first = f;
177// return f;
178
179 return name;
180}
181
182static char *put_font_size(const char *n, int size)
183{
184 int i = 0;
185 char *buf;
186 const char *ptr;
187 const char *f;
188 char *name;
189 int nbf = 1;
190 name = strdup(n);
191 while (name[i]) {
192 if (name[i] == ',') {nbf++; name[i] = '\0';}
193 i++;
194 }
195
196 buf = (char*) malloc(nbf * 256);
197 buf[0] = '\0';
198 ptr = name;
199 i = 0;
200 while (ptr && nbf > 0) {
201 f = find_best_font(ptr, size);
202 while (*f) {
203 buf[i] = *f;
204 f++; i++;
205 }
206 nbf--;
207 while (*ptr) ptr++;
208 if (nbf) {
209 ptr++;
210 buf[i] = ',';
211 i++;
212 }
213 while(isspace(*ptr)) ptr++;
214 }
215 buf[i] = '\0';
216 free(name);
217 return buf;
218}
219
220
221char *fl_get_font_xfld(int fnum, int size) {
222 Fl_Fontdesc* s = fl_fonts+fnum;
223 if (!s->name) s = fl_fonts; // use font 0 if still undefined
224 fl_open_display();
225 return put_font_size(s->name, size);
226}
227
228// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
229static Fl_Font_Descriptor* find(int fnum, int size) {
230 char *name;
231 Fl_Fontdesc* s = fl_fonts+fnum;
232 if (!s->name) s = fl_fonts; // use font 0 if still undefined
233 Fl_Font_Descriptor* f;
234 for (f = s->first; f; f = f->next)
235 if (f->size == size) return f;
236 fl_open_display();
237
238 name = put_font_size(s->name, size);
239 f = new Fl_Font_Descriptor(name);
240 f->size = size;
241 f->next = s->first;
242 s->first = f;
243 free(name);
244 return f;
245}
246
247
249// Public interface:
250
251void *fl_xftfont = 0;
252static GC font_gc;
253
254XFontStruct* Fl_XFont_On_Demand::value() {
255 return ptr;
256}
257
258void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
259 if (fnum==-1) {
260 Fl_Graphics_Driver::font(0, 0);
261 return;
262 }
263 if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return;
264 Fl_Graphics_Driver::font(fnum, size);
265 Fl_Font_Descriptor* f = find(fnum, size);
266 if (f != this->font_descriptor()) {
267 this->font_descriptor(f);
268 fl_xfont = f->font->fonts[0];
269 font_gc = 0;
270 }
271}
272
273int Fl_Xlib_Graphics_Driver::height() {
274 if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
275 else return -1;
276}
277
278int Fl_Xlib_Graphics_Driver::descent() {
279 if (font_descriptor()) return font_descriptor()->font->descent;
280 else return -1;
281}
282
283double Fl_Xlib_Graphics_Driver::width(const char* c, int n) {
284 if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
285 else return -1;
286}
287
288double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
289 if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
290 else return -1;
291}
292
293void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
294 if (font_gc != fl_gc) {
295 if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
296 font_gc = fl_gc;
297 XSetFont(fl_display, fl_gc, font_descriptor()->font->fid);
298 }
299 int xx, yy, ww, hh;
300 xx = yy = ww = hh = 0;
301 if (fl_gc) XUtf8_measure_extents(fl_display, fl_window, font_descriptor()->font, fl_gc, &xx, &yy, &ww, &hh, c, n);
302
303 W = ww; H = hh; dx = xx; dy = yy;
304// This is the safe but mostly wrong thing we used to do...
305// W = 0; H = 0;
306// fl_measure(c, W, H, 0);
307// dx = 0;
308// dy = fl_descent() - H;
309}
310
311void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) {
312 if (font_gc != fl_gc) {
313 if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
314 font_gc = fl_gc;
315 XSetFont(fl_display, fl_gc, font_descriptor()->font->fid);
316 }
317 if (fl_gc) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n);
318}
319
320void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
321 static char warning = 0; // issue warning only once
322 if (!warning && angle != 0) {
323 warning = 1;
324 fprintf(stderr,
325 "libfltk: rotated text not implemented by X backend.\n"
326 " You should use the Xft backend. Check USE_XFT in config.h.\n");
327 }
328 this->draw(str, n, (int)x, (int)y);
329}
330
331void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
332 if (font_gc != fl_gc) {
333 if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
334 font_gc = fl_gc;
335 }
336 if (fl_gc) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n);
337}
338#endif // FL_DOXYGEN
339//
340// End of "$Id$".
341//
FL_NORMAL_SIZE
FL_EXPORT Fl_Fontsize FL_NORMAL_SIZE
normal font size
Definition Fl_Widget.cxx:117
Fl_Font
int Fl_Font
A font number is an index into the internal font table.
Definition Enumerations.H:875
FL_HELVETICA
const Fl_Font FL_HELVETICA
Helvetica (or Arial) normal (0)
Definition Enumerations.H:877
Fl_Fontsize
int Fl_Fontsize
Size of a font in pixels.
Definition Enumerations.H:904
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_Font_Descriptor
This a structure for an actual system font, with junk to help choose it and info on character sizes.
Definition Fl_Font.H:41
Fl_Graphics_Driver::font_descriptor
Fl_Font_Descriptor * font_descriptor()
Returns a pointer to the current Fl_Font_Descriptor for the graphics driver.
Definition Fl_Device.H:404
Fl_Graphics_Driver::size
Fl_Fontsize size()
see fl_size().
Definition Fl_Device.H:390
Fl_Graphics_Driver::font
Fl_Font font()
see fl_font(void).
Definition Fl_Device.H:388
Fl_Xlib_Graphics_Driver::width
double width(const char *str, int n)
see fl_width(const char *str, int n).
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).
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).
Fl_Xlib_Graphics_Driver::height
int height()
see fl_height().
Fl_Xlib_Graphics_Driver::descent
int descent()
see fl_descent().
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).
Fl::warning
static void(* warning)(const char *,...)
FLTK calls Fl::warning() to output a warning message.
Definition Fl.H:505
Fl_Fontdesc
Definition Fl_Font.H:86