diff options
Diffstat (limited to 'src')
17 files changed, 731 insertions, 755 deletions
diff --git a/src/cfg_gfx/xlib.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h index 4ce00b426..255e5f16b 100644 --- a/src/cfg_gfx/xlib.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h @@ -18,7 +18,7 @@ // /** - \file xlib.H + \file Fl_Xlib_Graphics_Driver.h \brief Definition of X11 Xlib graphics driver. */ diff --git a/src/cfg_gfx/xlib_arci.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx index 118e683a1..118e683a1 100644 --- a/src/cfg_gfx/xlib_arci.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx diff --git a/src/cfg_gfx/xlib_color.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx index e7e9d0cf7..e7e9d0cf7 100644 --- a/src/cfg_gfx/xlib_color.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx diff --git a/src/fl_set_fonts_x.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx index 845f15a87..cec910f30 100644 --- a/src/fl_set_fonts_x.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx @@ -339,3 +339,338 @@ int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { // // End of "$Id$". // +// +// "$Id$" +// +// Standard X11 font selection code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2011 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +#ifndef FL_DOXYGEN + +Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) { + font = XCreateUtf8FontStruct(fl_display, name); + if (!font) { + Fl::warning("bad font: %s", name); + font = XCreateUtf8FontStruct(fl_display, "fixed"); + } +# if HAVE_GL + listbase = 0; + for (int u = 0; u < 64; u++) glok[u] = 0; +# endif +} + +Fl_XFont_On_Demand fl_xfont; + +Fl_Font_Descriptor::~Fl_Font_Descriptor() { +# if HAVE_GL +// Delete list created by gl_draw(). This is not done by this code +// as it will link in GL unnecessarily. There should be some kind +// of "free" routine pointer, or a subclass? +// if (listbase) { +// int base = font->min_char_or_byte2; +// int size = font->max_char_or_byte2-base+1; +// int base = 0; int size = 256; +// glDeleteLists(listbase+base,size); +// } +# endif + if (this == fl_graphics_driver->font_descriptor()) { + fl_graphics_driver->font_descriptor(NULL); + fl_xfont = 0; + } + XFreeUtf8FontStruct(fl_display, font); +} + +//////////////////////////////////////////////////////////////// + +// WARNING: if you add to this table, you must redefine FL_FREE_FONT +// in Enumerations.H & recompile!! +static Fl_Fontdesc built_in_table[] = { +{"-*-helvetica-medium-r-normal--*"}, +{"-*-helvetica-bold-r-normal--*"}, +{"-*-helvetica-medium-o-normal--*"}, +{"-*-helvetica-bold-o-normal--*"}, +{"-*-courier-medium-r-normal--*"}, +{"-*-courier-bold-r-normal--*"}, +{"-*-courier-medium-o-normal--*"}, +{"-*-courier-bold-o-normal--*"}, +{"-*-times-medium-r-normal--*"}, +{"-*-times-bold-r-normal--*"}, +{"-*-times-medium-i-normal--*"}, +{"-*-times-bold-i-normal--*"}, +{"-*-symbol-*"}, +{"-*-lucidatypewriter-medium-r-normal-sans-*"}, +{"-*-lucidatypewriter-bold-r-normal-sans-*"}, +{"-*-*zapf dingbats-*"} +}; + +Fl_Fontdesc* fl_fonts = built_in_table; + +#define MAXSIZE 32767 + +// return dash number N, or pointer to ending null if none: +const char* fl_font_word(const char* p, int n) { + while (*p) {if (*p=='-') {if (!--n) break;} p++;} + return p; +} + +// return a pointer to a number we think is "point size": +char* fl_find_fontsize(char* name) { + char* c = name; + // for standard x font names, try after 7th dash: + if (*c == '-') { + c = (char*)fl_font_word(c,7); + if (*c++ && isdigit(*c)) return c; + return 0; // malformed x font name? + } + char* r = 0; + // find last set of digits: + for (c++;* c; c++) + if (isdigit(*c) && !isdigit(*(c-1))) r = c; + return r; +} + +//const char* fl_encoding = "iso8859-1"; +const char* fl_encoding = "iso10646-1"; + +// return true if this matches fl_encoding: +int fl_correct_encoding(const char* name) { + if (*name != '-') return 0; + const char* c = fl_font_word(name,13); + return (*c++ && !strcmp(c,fl_encoding)); +} + +static const char *find_best_font(const char *fname, int size) { + int cnt; + static char **list = NULL; +// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: + if (list) XFreeFontNames(list); + list = XListFonts(fl_display, fname, 100, &cnt); + if (!list) return "fixed"; + + // search for largest <= font size: + char* name = list[0]; int ptsize = 0; // best one found so far + int matchedlength = 32767; + char namebuffer[1024]; // holds scalable font name + int found_encoding = 0; + int m = cnt; if (m<0) m = -m; + for (int n=0; n < m; n++) { + char* thisname = list[n]; + if (fl_correct_encoding(thisname)) { + if (!found_encoding) ptsize = 0; // force it to choose this + found_encoding = 1; + } else { + if (found_encoding) continue; + } + char* c = (char*)fl_find_fontsize(thisname); + int thissize = c ? atoi(c) : MAXSIZE; + int thislength = strlen(thisname); + if (thissize == size && thislength < matchedlength) { + // exact match, use it: + name = thisname; + ptsize = size; + matchedlength = thislength; + } else if (!thissize && ptsize!=size) { + // whoa! A scalable font! Use unless exact match found: + int l = c-thisname; + memcpy(namebuffer,thisname,l); + l += sprintf(namebuffer+l,"%d",size); + while (*c == '0') c++; + strcpy(namebuffer+l,c); + name = namebuffer; + ptsize = size; + } else if (!ptsize || // no fonts yet + (thissize < ptsize && ptsize > size) || // current font too big + (thissize > ptsize && thissize <= size) // current too small + ) { + name = thisname; + ptsize = thissize; + matchedlength = thislength; + } + } + +// if (ptsize != size) { // see if we already found this unscalable font: +// for (f = s->first; f; f = f->next) { +// if (f->minsize <= ptsize && f->maxsize >= ptsize) { +// if (f->minsize > size) f->minsize = size; +// if (f->maxsize < size) f->maxsize = size; +// return f; +// } +// } +// } +// +// // okay, we definately have some name, make the font: +// f = new Fl_Font_Descriptor(name); +// if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;} +// else {f->minsize = size; f->maxsize = ptsize;} +// f->next = s->first; +// s->first = f; +// return f; + + return name; +} + +static char *put_font_size(const char *n, int size) +{ + int i = 0; + char *buf; + const char *ptr; + const char *f; + char *name; + int nbf = 1; + name = strdup(n); + while (name[i]) { + if (name[i] == ',') {nbf++; name[i] = '\0';} + i++; + } + + buf = (char*) malloc(nbf * 256); + buf[0] = '\0'; + ptr = name; + i = 0; + while (ptr && nbf > 0) { + f = find_best_font(ptr, size); + while (*f) { + buf[i] = *f; + f++; i++; + } + nbf--; + while (*ptr) ptr++; + if (nbf) { + ptr++; + buf[i] = ','; + i++; + } + while(isspace(*ptr)) ptr++; + } + buf[i] = '\0'; + free(name); + return buf; +} + + +char *fl_get_font_xfld(int fnum, int size) { + Fl_Fontdesc* s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // use font 0 if still undefined + fl_open_display(); + return put_font_size(s->name, size); +} + +// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: +static Fl_Font_Descriptor* find(int fnum, int size) { + char *name; + Fl_Fontdesc* s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // use font 0 if still undefined + Fl_Font_Descriptor* f; + for (f = s->first; f; f = f->next) + if (f->size == size) return f; + fl_open_display(); + + name = put_font_size(s->name, size); + f = new Fl_Font_Descriptor(name); + f->size = size; + f->next = s->first; + s->first = f; + free(name); + return f; +} + + +//////////////////////////////////////////////////////////////// +// Public interface: + +void *fl_xftfont = 0; +static GC font_gc; + +XFontStruct* Fl_XFont_On_Demand::value() { + return ptr; +} + +void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { + if (fnum==-1) { + Fl_Graphics_Driver::font(0, 0); + return; + } + if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return; + Fl_Graphics_Driver::font(fnum, size); + Fl_Font_Descriptor* f = find(fnum, size); + if (f != this->font_descriptor()) { + this->font_descriptor(f); + fl_xfont = f->font->fonts[0]; + font_gc = 0; + } +} + +int Fl_Xlib_Graphics_Driver::height() { + if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent; + else return -1; +} + +int Fl_Xlib_Graphics_Driver::descent() { + if (font_descriptor()) return font_descriptor()->font->descent; + else return -1; +} + +double Fl_Xlib_Graphics_Driver::width(const char* c, int n) { + if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n); + else return -1; +} + +double Fl_Xlib_Graphics_Driver::width(unsigned int c) { + if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c); + else return -1; +} + +void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) { + if (font_gc != fl_gc) { + if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); + font_gc = fl_gc; + XSetFont(fl_display, fl_gc, font_descriptor()->font->fid); + } + int xx, yy, ww, hh; + xx = yy = ww = hh = 0; + if (fl_gc) XUtf8_measure_extents(fl_display, fl_window, font_descriptor()->font, fl_gc, &xx, &yy, &ww, &hh, c, n); + + W = ww; H = hh; dx = xx; dy = yy; +// This is the safe but mostly wrong thing we used to do... +// W = 0; H = 0; +// fl_measure(c, W, H, 0); +// dx = 0; +// dy = fl_descent() - H; +} + +void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) { + if (font_gc != fl_gc) { + if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); + font_gc = fl_gc; + XSetFont(fl_display, fl_gc, font_descriptor()->font->fid); + } + if (fl_gc) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n); +} + +void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { + fprintf(stderr,"ROTATING TEXT NOT IMPLEMENTED\n"); + this->draw(str, n, (int)x, (int)y); +} + +void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { + if (font_gc != fl_gc) { + if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); + font_gc = fl_gc; + } + if (fl_gc) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n); +} +#endif // FL_DOXYGEN +// +// End of "$Id$". +// diff --git a/src/fl_font_xft.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx index 67921699a..91ee460ce 100644 --- a/src/fl_font_xft.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx @@ -1,6 +1,390 @@ // // "$Id$" // +// More font utilities for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2011 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <X11/Xft/Xft.h> + +// This function fills in the fltk font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + +// Bug: older versions calculated the value for *ap as a side effect of +// making the name, and then forgot about it. To avoid having to change +// the header files I decided to store this value in the last character +// of the font name array. +#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 + +// turn a stored font name in "fltk format" into a pretty name: +const char* Fl::get_font_name(Fl_Font fnum, int* ap) { + Fl_Fontdesc *f = fl_fonts + fnum; + if (!f->fontname[0]) { + const char* p = f->name; + int type; + switch (p[0]) { + case 'B': type = FL_BOLD; break; + case 'I': type = FL_ITALIC; break; + case 'P': type = FL_BOLD | FL_ITALIC; break; + default: type = 0; break; + } + + // NOTE: This can cause duplications in fonts that already have Bold or Italic in + // their "name". Maybe we need to find a cleverer way? + strlcpy(f->fontname, p+1, ENDOFBUFFER); + if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); + if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); + f->fontname[ENDOFBUFFER] = (char)type; + } + if (ap) *ap = f->fontname[ENDOFBUFFER]; + return f->fontname; +} + +/////////////////////////////////////////////////////////// +#define LOCAL_RAW_NAME_MAX 256 + +extern "C" { +// sort returned fontconfig font names +static int name_sort(const void *aa, const void *bb) { + // What should we do here? Just do a string compare for now... + // NOTE: This yeilds some oddities - in particular a Blah Bold font will be + // listed before Blah... + // Also - the fontconfig listing returns some faces that are effectively duplicates + // as far as fltk is concerned, e.g. where there are ko or ja variants that we + // can't distinguish (since we are not yet fully UTF-*) - should we strip them here? + return fl_ascii_strcasecmp(*(char**)aa, *(char**)bb); +} // end of name_sort +} // end of extern C section + + +// Read the "pretty" name we have derived from fontconfig then convert +// it into the format fltk uses internally for Xft names... +// This is just a mess - I should have tokenised the strings and gone from there, +// but I really thought this would be easier! +static void make_raw_name(char *raw, char *pretty) +{ + // Input name will be "Some Name:style = Bold Italic" or whatever + // The plan is this: + // - the first char in the "raw" name becomes either I, B, P or " " for + // italic, bold, bold italic or normal - this seems to be the fltk way... + + char *style = strchr(pretty, ':'); + + if (style) + { + *style = 0; // Terminate "name" string + style ++; // point to start of style section + } + + // It is still possible that the "pretty" name has multiple comma separated entries + // I've seen this often in CJK fonts, for example... Keep only the first one... This + // is not ideal, the CJK fonts often have the name in utf8 in several languages. What + // we ought to do is use fontconfig to query the available languages and pick one... But which? +#if 0 // loop to keep the LAST name entry... + char *nm1 = pretty; + char *nm2 = strchr(nm1, ','); + while(nm2) { + nm1 = nm2 + 1; + nm2 = strchr(nm1, ','); + } + raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text + strncat(raw, nm1, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 + // Ensure raw is terminated, just in case the given name is infeasibly long... + raw[LOCAL_RAW_NAME_MAX-1] = 0; +#else // keep the first remaining name entry + char *nm2 = strchr(pretty, ','); + if(nm2) *nm2 = 0; // terminate name after first entry + raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text + strncat(raw, pretty, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 + // Ensure raw is terminated, just in case the given name is infeasibly long... + raw[LOCAL_RAW_NAME_MAX-1] = 0; +#endif + // At this point, the name is "marked" as regular... + if (style) + { +#define PLAIN 0 +#define BOLD 1 +#define ITALIC 2 +#define BITALIC (BOLD | ITALIC) + + int mods = PLAIN; + char *last = style + strlen(style) - 2; + + // Now try and parse the style string - look for the "=" sign + style = strchr(style, '='); + while ((style) && (style < last)) + { + int type; + while ((*style == '=') || (*style == ' ') || (*style == '\t') || (*style == ',')) + { + style++; // Start of Style string + if ((style >= last) || (*style == 0)) continue; + } + type = toupper(style[0]); + switch (type) + { + // Things we might see: Regular Normal Bold Italic Oblique (??what??) Medium + // Roman Light Demi Sans SemiCondensed SuperBold Book... etc... + // Things we actually care about: Bold Italic Oblique SuperBold - Others??? + case 'I': + if (strncasecmp(style, "Italic", 6) == 0) + { + mods |= ITALIC; + } + goto NEXT_STYLE; + + case 'B': + if (strncasecmp(style, "Bold", 4) == 0) + { + mods |= BOLD; + } + goto NEXT_STYLE; + + case 'O': + if (strncasecmp(style, "Oblique", 7) == 0) + { + mods |= ITALIC; + } + goto NEXT_STYLE; + + case 'S': + if (strncasecmp(style, "SuperBold", 9) == 0) + { + mods |= BOLD; + } + goto NEXT_STYLE; + + default: // find the next gap + goto NEXT_STYLE; + } // switch end +NEXT_STYLE: + while ((*style != ' ') && (*style != '\t') && (*style != ',')) + { + style++; + if ((style >= last) || (*style == 0)) goto STYLE_DONE; + } + } +STYLE_DONE: + // Set the "modifier" character in the raw string + switch(mods) + { + case BOLD: raw[0] = 'B'; + break; + case ITALIC: raw[0] = 'I'; + break; + case BITALIC: raw[0] = 'P'; + break; + default: raw[0] = ' '; + break; + } + } +} // make_raw_name + +/////////////////////////////////////////////////////////// + +static int fl_free_font = FL_FREE_FONT; + +// Uses the fontconfig lib to construct a list of all installed fonts. +// I tried using XftListFonts for this, but the API is tricky - and when +// I looked at the XftList* code, it calls the Fc* functions anyway, so... +// +// Also, for now I'm ignoring the "pattern_name" and just getting everything... +// AND I don't try and skip the fonts we've already loaded in the defaults. +// Blimey! What a hack! +Fl_Font Fl::set_fonts(const char* pattern_name) +{ + FcFontSet *fnt_set; // Will hold the list of fonts we find + FcPattern *fnt_pattern; // Holds the generic "match all names" pattern + FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" + + int j; // loop iterator variable + int font_count; // Total number of fonts found to process + char **full_list; // The list of font names we build + + if (fl_free_font > FL_FREE_FONT) // already been here + return (Fl_Font)fl_free_font; + + fl_open_display(); // Just in case... + + // Make sure fontconfig is ready... is this necessary? The docs say it is + // safe to call it multiple times, so just go for it anyway! + if (!FcInit()) + { + // What to do? Just return defaults... + return FL_FREE_FONT; + } + + // Create a search pattern that will match every font name - I think this + // does the Right Thing, but am not certain... + // + // This could possibly be "enhanced" to pay attention to the requested + // "pattern_name"? + fnt_pattern = FcPatternCreate(); + fnt_obj_set = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (void *)0); + + // Hopefully, this is a set of all the fonts... + fnt_set = FcFontList(0, fnt_pattern, fnt_obj_set); + + // We don't need the fnt_pattern and fnt_obj_set any more, release them + FcPatternDestroy(fnt_pattern); + FcObjectSetDestroy(fnt_obj_set); + + // Now, if we got any fonts, iterate through them... + if (fnt_set) + { + char *stop; + char *start; + char *first; + + font_count = fnt_set->nfont; // How many fonts? + + // Allocate array of char*'s to hold the name strings + full_list = (char **)malloc(sizeof(char *) * font_count); + + // iterate through all the font patterns and get the names out... + for (j = 0; j < font_count; j++) + { + // NOTE: FcChar8 is a typedef of "unsigned char"... + FcChar8 *font; // String to hold the font's name + + // Convert from fontconfig internal pattern to human readable name + // NOTE: This WILL malloc storage, so we need to free it later... + font = FcNameUnparse(fnt_set->fonts[j]); + + // The returned strings look like this... + // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,... + // So the bit we want is up to the first comma - BUT some strings have + // more than one name, separated by, guess what?, a comma... + stop = start = first = 0; + stop = strchr((char *)font, ','); + start = strchr((char *)font, ':'); + if ((stop) && (start) && (stop < start)) + { + first = stop + 1; // discard first version of name + // find first comma *after* the end of the name + stop = strchr((char *)start, ','); + } + else + { + first = (char *)font; // name is just what was returned + } + // Truncate the name after the (english) modifiers description + // Matt: Actually, there is no guarantee that the *first* description is the English one. + // Matt: So we keep the entire description, just in case. + //if (stop) + //{ + // *stop = 0; // Terminate the string at the first comma, if there is one + //} + + // Copy the font description into our list + if (first == (char *)font) + { // The listed name is still OK + full_list[j] = (char *)font; + } + else + { // The listed name has been modified + full_list[j] = strdup(first); + // Free the font name storage + free (font); + } + // replace "style=Regular" so strcmp sorts it first + if (start) { + char *reg = strstr(full_list[j], "=Regular"); + if (reg) reg[1]='.'; + } + } + + // Release the fnt_set - we don't need it any more + FcFontSetDestroy(fnt_set); + + // Sort the list into alphabetic order + qsort(full_list, font_count, sizeof(*full_list), name_sort); + + // Now let us add the names we got to fltk's font list... + for (j = 0; j < font_count; j++) + { + if (full_list[j]) + { + char xft_name[LOCAL_RAW_NAME_MAX]; + char *stored_name; + // Parse the strings into FLTK-XFT style.. + make_raw_name(xft_name, full_list[j]); + // NOTE: This just adds on AFTER the default fonts - no attempt is made + // to identify already loaded fonts. Is this bad? + stored_name = strdup(xft_name); + Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name); + fl_free_font ++; + + free(full_list[j]); // release that name from our internal array + } + } + // Now we are done with the list, release it fully + free(full_list); + } + return (Fl_Font)fl_free_font; +} // ::set_fonts +//////////////////////////////////////////////////////////////// + + +extern "C" { +static int int_sort(const void *aa, const void *bb) { + return (*(int*)aa)-(*(int*)bb); +} +} + +//////////////////////////////////////////////////////////////// + +// Return all the point sizes supported by this font: +// Suprisingly enough Xft works exactly like fltk does and returns +// the same list. Except there is no way to tell if the font is scalable. +int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { + Fl_Fontdesc *s = fl_fonts+fnum; + if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 + + fl_open_display(); + XftFontSet* fs = XftListFonts(fl_display, fl_screen, + XFT_FAMILY, XftTypeString, s->name+1, + (void *)0, + XFT_PIXEL_SIZE, + (void *)0); + static int* array = 0; + static int array_size = 0; + if (fs->nfont >= array_size) { + delete[] array; + array = new int[array_size = fs->nfont+1]; + } + array[0] = 0; int j = 1; // claim all fonts are scalable + for (int i = 0; i < fs->nfont; i++) { + double v; + if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) { + array[j++] = int(v); + } + } + qsort(array+1, j-1, sizeof(int), int_sort); + XftFontSetDestroy(fs); + sizep = array; + return j; +} + +// +// End of "$Id$". +// +// +// "$Id$" +// // Xft font code for the Fast Light Tool Kit (FLTK). // // Copyright 2001-2011 Bill Spitzak and others. diff --git a/src/cfg_gfx/xlib_line_style.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx index 55e759a61..a20ace778 100644 --- a/src/cfg_gfx/xlib_line_style.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx @@ -24,7 +24,7 @@ \brief Line style drawing utility hiding different platforms. */ -#include "xlib.H" +#include "Fl_Xlib_Graphics_Driver.h" void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) { diff --git a/src/cfg_gfx/xlib_rect.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx index fc5ff1474..225b578d1 100644 --- a/src/cfg_gfx/xlib_rect.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx @@ -27,7 +27,7 @@ */ -#include "xlib.H" +#include "Fl_Xlib_Graphics_Driver.h" #ifndef SHRT_MAX diff --git a/src/cfg_gfx/xlib_vertex.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx index 9fe73a27c..4c559ad8c 100644 --- a/src/cfg_gfx/xlib_vertex.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx @@ -25,7 +25,7 @@ simple 2D transformations, implemented for X11 Xlib. */ -#include "xlib.H" +#include "Fl_Xlib_Graphics_Driver.h" #include <FL/fl_draw.H> #include <FL/x.H> diff --git a/src/fl_arci.cxx b/src/fl_arci.cxx index 7cc3c0690..11f6d4273 100644 --- a/src/fl_arci.cxx +++ b/src/fl_arci.cxx @@ -60,7 +60,7 @@ #ifdef FL_CFG_GFX_XLIB -# include "cfg_gfx/xlib_arci.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx" #endif diff --git a/src/fl_color.cxx b/src/fl_color.cxx index ddcb8a3ca..1bf3a19f6 100644 --- a/src/fl_color.cxx +++ b/src/fl_color.cxx @@ -52,7 +52,7 @@ #ifdef FL_CFG_GFX_XLIB -# include "cfg_gfx/xlib_color.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx" #endif diff --git a/src/fl_font.cxx b/src/fl_font.cxx index ca7e87560..02a6b8932 100644 --- a/src/fl_font.cxx +++ b/src/fl_font.cxx @@ -54,7 +54,8 @@ #elif defined(FL_PORTING) # pragma message "FL_PORTING: implement font handling specifics in its own file" #else -# include "fl_font_x.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx" #endif // WIN32 #if defined(WIN32) || defined(__APPLE__) diff --git a/src/fl_font_x.cxx b/src/fl_font_x.cxx deleted file mode 100644 index cd2ac4e6a..000000000 --- a/src/fl_font_x.cxx +++ /dev/null @@ -1,335 +0,0 @@ -// -// "$Id$" -// -// Standard X11 font selection code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2011 by Bill Spitzak and others. -// -// This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this -// file is missing or damaged, see the license at: -// -// http://www.fltk.org/COPYING.php -// -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php -// -#ifndef FL_DOXYGEN - -Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) { - font = XCreateUtf8FontStruct(fl_display, name); - if (!font) { - Fl::warning("bad font: %s", name); - font = XCreateUtf8FontStruct(fl_display, "fixed"); - } -# if HAVE_GL - listbase = 0; - for (int u = 0; u < 64; u++) glok[u] = 0; -# endif -} - -Fl_XFont_On_Demand fl_xfont; - -Fl_Font_Descriptor::~Fl_Font_Descriptor() { -# if HAVE_GL -// Delete list created by gl_draw(). This is not done by this code -// as it will link in GL unnecessarily. There should be some kind -// of "free" routine pointer, or a subclass? -// if (listbase) { -// int base = font->min_char_or_byte2; -// int size = font->max_char_or_byte2-base+1; -// int base = 0; int size = 256; -// glDeleteLists(listbase+base,size); -// } -# endif - if (this == fl_graphics_driver->font_descriptor()) { - fl_graphics_driver->font_descriptor(NULL); - fl_xfont = 0; - } - XFreeUtf8FontStruct(fl_display, font); -} - -//////////////////////////////////////////////////////////////// - -// WARNING: if you add to this table, you must redefine FL_FREE_FONT -// in Enumerations.H & recompile!! -static Fl_Fontdesc built_in_table[] = { -{"-*-helvetica-medium-r-normal--*"}, -{"-*-helvetica-bold-r-normal--*"}, -{"-*-helvetica-medium-o-normal--*"}, -{"-*-helvetica-bold-o-normal--*"}, -{"-*-courier-medium-r-normal--*"}, -{"-*-courier-bold-r-normal--*"}, -{"-*-courier-medium-o-normal--*"}, -{"-*-courier-bold-o-normal--*"}, -{"-*-times-medium-r-normal--*"}, -{"-*-times-bold-r-normal--*"}, -{"-*-times-medium-i-normal--*"}, -{"-*-times-bold-i-normal--*"}, -{"-*-symbol-*"}, -{"-*-lucidatypewriter-medium-r-normal-sans-*"}, -{"-*-lucidatypewriter-bold-r-normal-sans-*"}, -{"-*-*zapf dingbats-*"} -}; - -Fl_Fontdesc* fl_fonts = built_in_table; - -#define MAXSIZE 32767 - -// return dash number N, or pointer to ending null if none: -const char* fl_font_word(const char* p, int n) { - while (*p) {if (*p=='-') {if (!--n) break;} p++;} - return p; -} - -// return a pointer to a number we think is "point size": -char* fl_find_fontsize(char* name) { - char* c = name; - // for standard x font names, try after 7th dash: - if (*c == '-') { - c = (char*)fl_font_word(c,7); - if (*c++ && isdigit(*c)) return c; - return 0; // malformed x font name? - } - char* r = 0; - // find last set of digits: - for (c++;* c; c++) - if (isdigit(*c) && !isdigit(*(c-1))) r = c; - return r; -} - -//const char* fl_encoding = "iso8859-1"; -const char* fl_encoding = "iso10646-1"; - -// return true if this matches fl_encoding: -int fl_correct_encoding(const char* name) { - if (*name != '-') return 0; - const char* c = fl_font_word(name,13); - return (*c++ && !strcmp(c,fl_encoding)); -} - -static const char *find_best_font(const char *fname, int size) { - int cnt; - static char **list = NULL; -// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: - if (list) XFreeFontNames(list); - list = XListFonts(fl_display, fname, 100, &cnt); - if (!list) return "fixed"; - - // search for largest <= font size: - char* name = list[0]; int ptsize = 0; // best one found so far - int matchedlength = 32767; - char namebuffer[1024]; // holds scalable font name - int found_encoding = 0; - int m = cnt; if (m<0) m = -m; - for (int n=0; n < m; n++) { - char* thisname = list[n]; - if (fl_correct_encoding(thisname)) { - if (!found_encoding) ptsize = 0; // force it to choose this - found_encoding = 1; - } else { - if (found_encoding) continue; - } - char* c = (char*)fl_find_fontsize(thisname); - int thissize = c ? atoi(c) : MAXSIZE; - int thislength = strlen(thisname); - if (thissize == size && thislength < matchedlength) { - // exact match, use it: - name = thisname; - ptsize = size; - matchedlength = thislength; - } else if (!thissize && ptsize!=size) { - // whoa! A scalable font! Use unless exact match found: - int l = c-thisname; - memcpy(namebuffer,thisname,l); - l += sprintf(namebuffer+l,"%d",size); - while (*c == '0') c++; - strcpy(namebuffer+l,c); - name = namebuffer; - ptsize = size; - } else if (!ptsize || // no fonts yet - (thissize < ptsize && ptsize > size) || // current font too big - (thissize > ptsize && thissize <= size) // current too small - ) { - name = thisname; - ptsize = thissize; - matchedlength = thislength; - } - } - -// if (ptsize != size) { // see if we already found this unscalable font: -// for (f = s->first; f; f = f->next) { -// if (f->minsize <= ptsize && f->maxsize >= ptsize) { -// if (f->minsize > size) f->minsize = size; -// if (f->maxsize < size) f->maxsize = size; -// return f; -// } -// } -// } -// -// // okay, we definately have some name, make the font: -// f = new Fl_Font_Descriptor(name); -// if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;} -// else {f->minsize = size; f->maxsize = ptsize;} -// f->next = s->first; -// s->first = f; -// return f; - - return name; -} - -static char *put_font_size(const char *n, int size) -{ - int i = 0; - char *buf; - const char *ptr; - const char *f; - char *name; - int nbf = 1; - name = strdup(n); - while (name[i]) { - if (name[i] == ',') {nbf++; name[i] = '\0';} - i++; - } - - buf = (char*) malloc(nbf * 256); - buf[0] = '\0'; - ptr = name; - i = 0; - while (ptr && nbf > 0) { - f = find_best_font(ptr, size); - while (*f) { - buf[i] = *f; - f++; i++; - } - nbf--; - while (*ptr) ptr++; - if (nbf) { - ptr++; - buf[i] = ','; - i++; - } - while(isspace(*ptr)) ptr++; - } - buf[i] = '\0'; - free(name); - return buf; -} - - -char *fl_get_font_xfld(int fnum, int size) { - Fl_Fontdesc* s = fl_fonts+fnum; - if (!s->name) s = fl_fonts; // use font 0 if still undefined - fl_open_display(); - return put_font_size(s->name, size); -} - -// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: -static Fl_Font_Descriptor* find(int fnum, int size) { - char *name; - Fl_Fontdesc* s = fl_fonts+fnum; - if (!s->name) s = fl_fonts; // use font 0 if still undefined - Fl_Font_Descriptor* f; - for (f = s->first; f; f = f->next) - if (f->size == size) return f; - fl_open_display(); - - name = put_font_size(s->name, size); - f = new Fl_Font_Descriptor(name); - f->size = size; - f->next = s->first; - s->first = f; - free(name); - return f; -} - - -//////////////////////////////////////////////////////////////// -// Public interface: - -void *fl_xftfont = 0; -static GC font_gc; - -XFontStruct* Fl_XFont_On_Demand::value() { - return ptr; -} - -void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { - if (fnum==-1) { - Fl_Graphics_Driver::font(0, 0); - return; - } - if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return; - Fl_Graphics_Driver::font(fnum, size); - Fl_Font_Descriptor* f = find(fnum, size); - if (f != this->font_descriptor()) { - this->font_descriptor(f); - fl_xfont = f->font->fonts[0]; - font_gc = 0; - } -} - -int Fl_Xlib_Graphics_Driver::height() { - if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent; - else return -1; -} - -int Fl_Xlib_Graphics_Driver::descent() { - if (font_descriptor()) return font_descriptor()->font->descent; - else return -1; -} - -double Fl_Xlib_Graphics_Driver::width(const char* c, int n) { - if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n); - else return -1; -} - -double Fl_Xlib_Graphics_Driver::width(unsigned int c) { - if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c); - else return -1; -} - -void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) { - if (font_gc != fl_gc) { - if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); - font_gc = fl_gc; - XSetFont(fl_display, fl_gc, font_descriptor()->font->fid); - } - int xx, yy, ww, hh; - xx = yy = ww = hh = 0; - if (fl_gc) XUtf8_measure_extents(fl_display, fl_window, font_descriptor()->font, fl_gc, &xx, &yy, &ww, &hh, c, n); - - W = ww; H = hh; dx = xx; dy = yy; -// This is the safe but mostly wrong thing we used to do... -// W = 0; H = 0; -// fl_measure(c, W, H, 0); -// dx = 0; -// dy = fl_descent() - H; -} - -void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) { - if (font_gc != fl_gc) { - if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); - font_gc = fl_gc; - XSetFont(fl_display, fl_gc, font_descriptor()->font->fid); - } - if (fl_gc) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n); -} - -void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { - fprintf(stderr,"ROTATING TEXT NOT IMPLEMENTED\n"); - this->draw(str, n, (int)x, (int)y); -} - -void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { - if (font_gc != fl_gc) { - if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); - font_gc = fl_gc; - } - if (fl_gc) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, fl_gc, x, y, c, n); -} -#endif // FL_DOXYGEN -// -// End of "$Id$". -// diff --git a/src/fl_line_style.cxx b/src/fl_line_style.cxx index e07add50b..83a373394 100644 --- a/src/fl_line_style.cxx +++ b/src/fl_line_style.cxx @@ -60,7 +60,7 @@ int fl_line_width_ = 0; #ifdef FL_CFG_GFX_XLIB -# include "cfg_gfx/xlib_line_style.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx" #endif diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx index 0676bb8f6..39af2e20c 100644 --- a/src/fl_rect.cxx +++ b/src/fl_rect.cxx @@ -65,31 +65,6 @@ Fl_Region Fl_Graphics_Driver::clip_region() { -//////////////////////////////////////////////////////////////// - -/* - Matt: I wrote individual methods for every class. They are virtual, so the - correct function is called, depending on the active driver. - - By having individual methods, multiple drivers can co-exist, for example - Quartz, OpenGL, and a printer driver. - - The individual implementations should eventually go into files that are - included into this file, based on the configuration, for example: - - src/cfg_gfx/quartz_rect.cxx - src/cfg_gfx/gdi_rect.cxx - src/cfg_gfx/xlib_rect.cxx - - Porting the graphics system to a new platform then requires to copy one of - these files and implement the virtual functions. point() is the only function - that *must* be implemented when deriving from 'Fl_Minimal_Graphics_Driver" - (which is still to be written) - */ - -//////////////////////////////////////////////////////////////// - - #ifdef FL_CFG_GFX_QUARTZ # include "cfg_gfx/quartz_rect.cxx" @@ -112,7 +87,7 @@ Fl_Region Fl_Graphics_Driver::clip_region() { #ifdef FL_CFG_GFX_XLIB -# include "cfg_gfx/xlib_rect.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx" #endif diff --git a/src/fl_set_fonts.cxx b/src/fl_set_fonts.cxx index 2673a78fd..ab92dc664 100644 --- a/src/fl_set_fonts.cxx +++ b/src/fl_set_fonts.cxx @@ -31,7 +31,7 @@ #elif defined(FL_PORTING) # pragma message "FL_PORTING: implement changes in font in its own file" #else -# include "fl_set_fonts_x.cxx" +// now included for fl_font.cxx, but will be its own source code module in drivers/Xlib/Fl_Xlib_Graphics_Driver_font..." #endif // WIN32 // diff --git a/src/fl_set_fonts_xft.cxx b/src/fl_set_fonts_xft.cxx deleted file mode 100644 index 13374ee7f..000000000 --- a/src/fl_set_fonts_xft.cxx +++ /dev/null @@ -1,384 +0,0 @@ -// -// "$Id$" -// -// More font utilities for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2011 by Bill Spitzak and others. -// -// This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this -// file is missing or damaged, see the license at: -// -// http://www.fltk.org/COPYING.php -// -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php -// - -#include <X11/Xft/Xft.h> - -// This function fills in the fltk font table with all the fonts that -// are found on the X server. It tries to place the fonts into families -// and to sort them so the first 4 in a family are normal, bold, italic, -// and bold italic. - -// Bug: older versions calculated the value for *ap as a side effect of -// making the name, and then forgot about it. To avoid having to change -// the header files I decided to store this value in the last character -// of the font name array. -#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 - -// turn a stored font name in "fltk format" into a pretty name: -const char* Fl::get_font_name(Fl_Font fnum, int* ap) { - Fl_Fontdesc *f = fl_fonts + fnum; - if (!f->fontname[0]) { - const char* p = f->name; - int type; - switch (p[0]) { - case 'B': type = FL_BOLD; break; - case 'I': type = FL_ITALIC; break; - case 'P': type = FL_BOLD | FL_ITALIC; break; - default: type = 0; break; - } - - // NOTE: This can cause duplications in fonts that already have Bold or Italic in - // their "name". Maybe we need to find a cleverer way? - strlcpy(f->fontname, p+1, ENDOFBUFFER); - if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); - if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); - f->fontname[ENDOFBUFFER] = (char)type; - } - if (ap) *ap = f->fontname[ENDOFBUFFER]; - return f->fontname; -} - -/////////////////////////////////////////////////////////// -#define LOCAL_RAW_NAME_MAX 256 - -extern "C" { -// sort returned fontconfig font names -static int name_sort(const void *aa, const void *bb) { - // What should we do here? Just do a string compare for now... - // NOTE: This yeilds some oddities - in particular a Blah Bold font will be - // listed before Blah... - // Also - the fontconfig listing returns some faces that are effectively duplicates - // as far as fltk is concerned, e.g. where there are ko or ja variants that we - // can't distinguish (since we are not yet fully UTF-*) - should we strip them here? - return fl_ascii_strcasecmp(*(char**)aa, *(char**)bb); -} // end of name_sort -} // end of extern C section - - -// Read the "pretty" name we have derived from fontconfig then convert -// it into the format fltk uses internally for Xft names... -// This is just a mess - I should have tokenised the strings and gone from there, -// but I really thought this would be easier! -static void make_raw_name(char *raw, char *pretty) -{ - // Input name will be "Some Name:style = Bold Italic" or whatever - // The plan is this: - // - the first char in the "raw" name becomes either I, B, P or " " for - // italic, bold, bold italic or normal - this seems to be the fltk way... - - char *style = strchr(pretty, ':'); - - if (style) - { - *style = 0; // Terminate "name" string - style ++; // point to start of style section - } - - // It is still possible that the "pretty" name has multiple comma separated entries - // I've seen this often in CJK fonts, for example... Keep only the first one... This - // is not ideal, the CJK fonts often have the name in utf8 in several languages. What - // we ought to do is use fontconfig to query the available languages and pick one... But which? -#if 0 // loop to keep the LAST name entry... - char *nm1 = pretty; - char *nm2 = strchr(nm1, ','); - while(nm2) { - nm1 = nm2 + 1; - nm2 = strchr(nm1, ','); - } - raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text - strncat(raw, nm1, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 - // Ensure raw is terminated, just in case the given name is infeasibly long... - raw[LOCAL_RAW_NAME_MAX-1] = 0; -#else // keep the first remaining name entry - char *nm2 = strchr(pretty, ','); - if(nm2) *nm2 = 0; // terminate name after first entry - raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text - strncat(raw, pretty, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 - // Ensure raw is terminated, just in case the given name is infeasibly long... - raw[LOCAL_RAW_NAME_MAX-1] = 0; -#endif - // At this point, the name is "marked" as regular... - if (style) - { -#define PLAIN 0 -#define BOLD 1 -#define ITALIC 2 -#define BITALIC (BOLD | ITALIC) - - int mods = PLAIN; - char *last = style + strlen(style) - 2; - - // Now try and parse the style string - look for the "=" sign - style = strchr(style, '='); - while ((style) && (style < last)) - { - int type; - while ((*style == '=') || (*style == ' ') || (*style == '\t') || (*style == ',')) - { - style++; // Start of Style string - if ((style >= last) || (*style == 0)) continue; - } - type = toupper(style[0]); - switch (type) - { - // Things we might see: Regular Normal Bold Italic Oblique (??what??) Medium - // Roman Light Demi Sans SemiCondensed SuperBold Book... etc... - // Things we actually care about: Bold Italic Oblique SuperBold - Others??? - case 'I': - if (strncasecmp(style, "Italic", 6) == 0) - { - mods |= ITALIC; - } - goto NEXT_STYLE; - - case 'B': - if (strncasecmp(style, "Bold", 4) == 0) - { - mods |= BOLD; - } - goto NEXT_STYLE; - - case 'O': - if (strncasecmp(style, "Oblique", 7) == 0) - { - mods |= ITALIC; - } - goto NEXT_STYLE; - - case 'S': - if (strncasecmp(style, "SuperBold", 9) == 0) - { - mods |= BOLD; - } - goto NEXT_STYLE; - - default: // find the next gap - goto NEXT_STYLE; - } // switch end -NEXT_STYLE: - while ((*style != ' ') && (*style != '\t') && (*style != ',')) - { - style++; - if ((style >= last) || (*style == 0)) goto STYLE_DONE; - } - } -STYLE_DONE: - // Set the "modifier" character in the raw string - switch(mods) - { - case BOLD: raw[0] = 'B'; - break; - case ITALIC: raw[0] = 'I'; - break; - case BITALIC: raw[0] = 'P'; - break; - default: raw[0] = ' '; - break; - } - } -} // make_raw_name - -/////////////////////////////////////////////////////////// - -static int fl_free_font = FL_FREE_FONT; - -// Uses the fontconfig lib to construct a list of all installed fonts. -// I tried using XftListFonts for this, but the API is tricky - and when -// I looked at the XftList* code, it calls the Fc* functions anyway, so... -// -// Also, for now I'm ignoring the "pattern_name" and just getting everything... -// AND I don't try and skip the fonts we've already loaded in the defaults. -// Blimey! What a hack! -Fl_Font Fl::set_fonts(const char* pattern_name) -{ - FcFontSet *fnt_set; // Will hold the list of fonts we find - FcPattern *fnt_pattern; // Holds the generic "match all names" pattern - FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" - - int j; // loop iterator variable - int font_count; // Total number of fonts found to process - char **full_list; // The list of font names we build - - if (fl_free_font > FL_FREE_FONT) // already been here - return (Fl_Font)fl_free_font; - - fl_open_display(); // Just in case... - - // Make sure fontconfig is ready... is this necessary? The docs say it is - // safe to call it multiple times, so just go for it anyway! - if (!FcInit()) - { - // What to do? Just return defaults... - return FL_FREE_FONT; - } - - // Create a search pattern that will match every font name - I think this - // does the Right Thing, but am not certain... - // - // This could possibly be "enhanced" to pay attention to the requested - // "pattern_name"? - fnt_pattern = FcPatternCreate(); - fnt_obj_set = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (void *)0); - - // Hopefully, this is a set of all the fonts... - fnt_set = FcFontList(0, fnt_pattern, fnt_obj_set); - - // We don't need the fnt_pattern and fnt_obj_set any more, release them - FcPatternDestroy(fnt_pattern); - FcObjectSetDestroy(fnt_obj_set); - - // Now, if we got any fonts, iterate through them... - if (fnt_set) - { - char *stop; - char *start; - char *first; - - font_count = fnt_set->nfont; // How many fonts? - - // Allocate array of char*'s to hold the name strings - full_list = (char **)malloc(sizeof(char *) * font_count); - - // iterate through all the font patterns and get the names out... - for (j = 0; j < font_count; j++) - { - // NOTE: FcChar8 is a typedef of "unsigned char"... - FcChar8 *font; // String to hold the font's name - - // Convert from fontconfig internal pattern to human readable name - // NOTE: This WILL malloc storage, so we need to free it later... - font = FcNameUnparse(fnt_set->fonts[j]); - - // The returned strings look like this... - // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,... - // So the bit we want is up to the first comma - BUT some strings have - // more than one name, separated by, guess what?, a comma... - stop = start = first = 0; - stop = strchr((char *)font, ','); - start = strchr((char *)font, ':'); - if ((stop) && (start) && (stop < start)) - { - first = stop + 1; // discard first version of name - // find first comma *after* the end of the name - stop = strchr((char *)start, ','); - } - else - { - first = (char *)font; // name is just what was returned - } - // Truncate the name after the (english) modifiers description - // Matt: Actually, there is no guarantee that the *first* description is the English one. - // Matt: So we keep the entire description, just in case. - //if (stop) - //{ - // *stop = 0; // Terminate the string at the first comma, if there is one - //} - - // Copy the font description into our list - if (first == (char *)font) - { // The listed name is still OK - full_list[j] = (char *)font; - } - else - { // The listed name has been modified - full_list[j] = strdup(first); - // Free the font name storage - free (font); - } - // replace "style=Regular" so strcmp sorts it first - if (start) { - char *reg = strstr(full_list[j], "=Regular"); - if (reg) reg[1]='.'; - } - } - - // Release the fnt_set - we don't need it any more - FcFontSetDestroy(fnt_set); - - // Sort the list into alphabetic order - qsort(full_list, font_count, sizeof(*full_list), name_sort); - - // Now let us add the names we got to fltk's font list... - for (j = 0; j < font_count; j++) - { - if (full_list[j]) - { - char xft_name[LOCAL_RAW_NAME_MAX]; - char *stored_name; - // Parse the strings into FLTK-XFT style.. - make_raw_name(xft_name, full_list[j]); - // NOTE: This just adds on AFTER the default fonts - no attempt is made - // to identify already loaded fonts. Is this bad? - stored_name = strdup(xft_name); - Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name); - fl_free_font ++; - - free(full_list[j]); // release that name from our internal array - } - } - // Now we are done with the list, release it fully - free(full_list); - } - return (Fl_Font)fl_free_font; -} // ::set_fonts -//////////////////////////////////////////////////////////////// - - -extern "C" { -static int int_sort(const void *aa, const void *bb) { - return (*(int*)aa)-(*(int*)bb); -} -} - -//////////////////////////////////////////////////////////////// - -// Return all the point sizes supported by this font: -// Suprisingly enough Xft works exactly like fltk does and returns -// the same list. Except there is no way to tell if the font is scalable. -int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { - Fl_Fontdesc *s = fl_fonts+fnum; - if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 - - fl_open_display(); - XftFontSet* fs = XftListFonts(fl_display, fl_screen, - XFT_FAMILY, XftTypeString, s->name+1, - (void *)0, - XFT_PIXEL_SIZE, - (void *)0); - static int* array = 0; - static int array_size = 0; - if (fs->nfont >= array_size) { - delete[] array; - array = new int[array_size = fs->nfont+1]; - } - array[0] = 0; int j = 1; // claim all fonts are scalable - for (int i = 0; i < fs->nfont; i++) { - double v; - if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) { - array[j++] = int(v); - } - } - qsort(array+1, j-1, sizeof(int), int_sort); - XftFontSetDestroy(fs); - sizep = array; - return j; -} - -// -// End of "$Id$". -// diff --git a/src/fl_vertex.cxx b/src/fl_vertex.cxx index 16f0a501f..d891794c0 100644 --- a/src/fl_vertex.cxx +++ b/src/fl_vertex.cxx @@ -170,7 +170,7 @@ void Fl_Graphics_Driver::fixloop() { // remove equal points from closed path #ifdef FL_CFG_GFX_XLIB -# include "cfg_gfx/xlib_vertex.cxx" +# include "drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx" #endif |
