mirror of
https://github.com/fltk/fltk.git
synced 2026-06-04 15:32:12 +08:00
Preliminary commit of porting Xlib drivers to the new naming scheme
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11053 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
//
|
||||
|
||||
/**
|
||||
\file xlib.H
|
||||
\file Fl_Xlib_Graphics_Driver.h
|
||||
\brief Definition of X11 Xlib graphics driver.
|
||||
*/
|
||||
|
||||
@@ -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$".
|
||||
//
|
||||
@@ -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.
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "xlib.H"
|
||||
#include "Fl_Xlib_Graphics_Driver.h"
|
||||
|
||||
|
||||
#ifndef SHRT_MAX
|
||||
@@ -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>
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
+2
-1
@@ -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__)
|
||||
|
||||
@@ -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$".
|
||||
//
|
||||
@@ -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
|
||||
|
||||
|
||||
+1
-26
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
//
|
||||
|
||||
@@ -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$".
|
||||
//
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user