Added virtual width(), height(), descent() and text_extents() functions to the Fl_Graphics_Driver

class to prepare for the future definition of graphics drivers that fully deal with text measurement.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8442 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2011-02-18 13:39:48 +00:00
parent 2c129b4833
commit 199b32d921
11 changed files with 224 additions and 171 deletions

View File

@ -107,7 +107,7 @@ public:
/**
\brief A virtual class subclassed for each graphics driver FLTK uses.
*
The protected virtual methods of this class are those that a graphics driver should implement to
The virtual methods of this class are those that a graphics driver should implement to
support all of FLTK drawing functions.
<br> The public API for drawing operations is functionally presented in \ref drawing and as function lists
in the \ref fl_drawings and \ref fl_attributes modules.
@ -156,6 +156,9 @@ protected:
friend void fl_line(int x, int y, int x1, int y1);
friend void fl_line(int x, int y, int x1, int y1, int x2, int y2);
friend void fl_draw(const char *str, int n, int x, int y);
#ifdef __APPLE__
friend void fl_draw(const char *str, int n, float x, float y);
#endif
friend void fl_draw(int angle, const char *str, int n, int x, int y);
friend void fl_rtl_draw(const char *str, int n, int x, int y);
friend void fl_font(Fl_Font face, Fl_Fontsize size);
@ -234,6 +237,9 @@ protected:
virtual void line(int x, int y, int x1, int y1, int x2, int y2);
/** \brief see fl_draw(const char *str, int n, int x, int y). */
virtual void draw(const char *str, int n, int x, int y) = 0;
#ifdef __APPLE__
virtual void draw(const char *str, int n, float x, float y) = 0;
#endif
/** \brief see fl_draw(int angle, const char *str, int n, int x, int y). */
virtual void draw(int angle, const char *str, int n, int x, int y) = 0;
/** \brief see fl_rtl_draw(const char *str, int n, int x, int y). */
@ -357,6 +363,16 @@ public:
Fl_Font font() {return font_; }
/** \brief see fl_size(). */
Fl_Fontsize size() {return size_; }
/** \brief see fl_width(const char *str, int n). */
virtual double width(const char *str, int n) = 0;
/** \brief see fl_width(unsigned int n). */
virtual inline double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); }
/** \brief see fl_text_extents(const char*, int n, int& dx, int& dy, int& w, int& h). */
virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
/** \brief see fl_height(). */
virtual int height() = 0;
/** \brief see fl_descent(). */
virtual int descent() = 0;
/** \brief see fl_color(void). */
Fl_Color color() {return color_;}
/** Returns a pointer to the current Fl_Font_Descriptor for the graphics driver */
@ -381,6 +397,9 @@ public:
void color(Fl_Color c);
void color(uchar r, uchar g, uchar b);
void draw(const char* str, int n, int x, int y);
#ifdef __APPLE__
void draw(const char *str, int n, float x, float y);
#endif
void draw(int angle, const char *str, int n, int x, int y);
void rtl_draw(const char* str, int n, int x, int y);
void font(Fl_Font face, Fl_Fontsize size);
@ -391,6 +410,11 @@ public:
void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
double width(const char *str, int n);
double width(unsigned int c);
void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
int height();
int descent();
};
#endif
#if defined(WIN32) || defined(FL_DOXYGEN)
@ -417,6 +441,11 @@ public:
void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
double width(const char *str, int n);
double width(unsigned int c);
void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
int height();
int descent();
};
#endif
#if !(defined(__APPLE__) || defined(WIN32))
@ -443,6 +472,11 @@ public:
void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
double width(const char *str, int n);
double width(unsigned int c);
void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
int height();
int descent();
};
#endif

View File

@ -116,6 +116,9 @@ class Clip {
/* int alpha_mask(const uchar * data, int w, int h, int D, int LD=0);
*/
void draw(const char* s, int n, int x, int y) {transformed_draw(s,n,x,y); };
#ifdef __APPLE__
void draw(const char* s, int n, float x, float y) {transformed_draw(s,n,x,y); };
#endif
void draw(int angle, const char *str, int n, int x, int y);
void rtl_draw(const char* s, int n, int x, int y);
void transformed_draw(const char* s, int n, double x, double y); //precise text placing
@ -180,6 +183,10 @@ class Clip {
void transformed_vertex(double x, double y);
void font(int face, int size);
double width(const char *, int);
void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h);
int height();
int descent();
void draw_image(const uchar* d, int x,int y,int w,int h, int delta=3, int ldelta=0){draw_scaled_image(d,x,y,w,h,w,h,delta,ldelta);};
void draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0){draw_scaled_image_mono(d,x,y,w,h,w,h,delta,ld);};

View File

@ -495,21 +495,21 @@ inline Fl_Fontsize fl_size() {return fl_graphics_driver->size();}
Returns the recommended minimum line spacing for the current font.
You can also use the value of \p size passed to fl_font()
*/
FL_EXPORT int fl_height(); // using "size" should work ok
inline int fl_height() {return fl_graphics_driver->height();}
FL_EXPORT int fl_height(int font, int size);
/**
Returns the recommended distance above the bottom of a fl_height() tall box to
draw the text at so it looks centered vertically in that box.
*/
FL_EXPORT int fl_descent();
inline int fl_descent() {return fl_graphics_driver->descent();}
/** Return the typographical width of a nul-terminated string */
FL_EXPORT double fl_width(const char* txt);
/** Return the typographical width of a sequence of \p n characters */
FL_EXPORT double fl_width(const char* txt, int n);
inline double fl_width(const char* txt, int n) {return fl_graphics_driver->width(txt, n);}
/** Return the typographical width of a single character :
\note if a valid fl_gc is NOT found then it uses the first window gc,
or the screen gc if no fltk window is available when called. */
FL_EXPORT double fl_width(unsigned int);
inline double fl_width(unsigned int c) {return fl_graphics_driver->width(c);}
/** Determine the minimum pixel dimensions of a nul-terminated string.
Usage: given a string "txt" drawn using fl_draw(txt, x, y) you would determine
@ -522,7 +522,8 @@ FL_EXPORT void fl_text_extents(const char*, int& dx, int& dy, int& w, int& h); /
/** Determine the minimum pixel dimensions of a sequence of \p n characters.
\see fl_text_extents(const char*, int& dx, int& dy, int& w, int& h)
*/
FL_EXPORT void fl_text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
inline void fl_text_extents(const char *t, int n, int& dx, int& dy, int& w, int& h)
{fl_graphics_driver->text_extents(t, n, dx, dy, w, h);}
// font encoding:
// Note: doxygen comments here to avoid duplication for os-sepecific cases

View File

@ -64,6 +64,14 @@ Fl_Graphics_Driver::Fl_Graphics_Driver() {
font_descriptor_ = NULL;
};
void Fl_Graphics_Driver::text_extents(const char*t, int n, int& dx, int& dy, int& w, int& h)
{
w = (int)width(t, n);
h = - height();
dx = dy = 0;
}
//
// End of "$Id$".
//

View File

@ -944,7 +944,7 @@ void Fl_PostScript_Graphics_Driver::font(int f, int s) {
fprintf(output, "/%s SF\n" , _fontNames[f]);
#if defined(USE_X11)
#if USE_XFT
// Xft font height is sometimes larger than the size required (see STR 2566).
// Xft font height is sometimes larger than the required size (see STR 2566).
// Increase the PostScript font size by 15% without exceeding the display font height
int max = desc->font->height;
ps_size = s * 1.15;
@ -963,6 +963,23 @@ void Fl_PostScript_Graphics_Driver::font(int f, int s) {
}
}
double Fl_PostScript_Graphics_Driver::width(const char *s, int n) {
return Fl_Display_Device::display_device()->driver()->width(s, n);
}
int Fl_PostScript_Graphics_Driver::height() {
return Fl_Display_Device::display_device()->driver()->height();
}
int Fl_PostScript_Graphics_Driver::descent() {
return Fl_Display_Device::display_device()->driver()->descent();
}
void Fl_PostScript_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
return Fl_Display_Device::display_device()->driver()->text_extents(c, n, dx, dy, w, h);
}
void Fl_PostScript_Graphics_Driver::color(Fl_Color c) {
Fl::get_color(c, cr_, cg_, cb_);
color(cr_, cg_, cb_);
@ -1022,45 +1039,48 @@ static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg)
}
// write to PostScript a bitmap image of a UTF8 string
static void transformed_draw_extra(const char* str, int n, double x, double y, int w, FILE *output) {
static void transformed_draw_extra(
const char* str, int n, double x, double y, int w, FILE *output, Fl_Graphics_Driver *driver) {
// scale for bitmask computation
#if defined(USE_X11) && !USE_XFT
const float scale = 1; // don't scale because we can't expect to have scalable fonts
float scale = 1; // don't scale because we can't expect to have scalable fonts
#else
const float scale = 3;
float scale = 3;
#endif
Fl_Fontsize old_size = fl_size();
Fl_Font fontnum = fl_font();
w = (int)(w *scale + 0.5);
int h = (int)(fl_height() * scale);
Fl_Fontsize old_size = driver->size();
Fl_Font fontnum = driver->font();
int w_scaled = (int)(w * (scale + 0.5));
int h = (int)(driver->height() * scale);
// create an offscreen image of the string
Fl_Color text_color = fl_color();
Fl_Color text_color = driver->color();
Fl_Color bg_color = fl_contrast(FL_WHITE, text_color);
Fl_Offscreen off = fl_create_offscreen(w+2, (int)(h+3*scale) );
Fl_Offscreen off = fl_create_offscreen(w_scaled, (int)(h+3*scale) );
fl_begin_offscreen(off);
fl_color(bg_color);
// color offscreen background with a shade contrasting with the text color
fl_rectf(0, 0, w+2, (int)(h+3*scale) );
fl_rectf(0, 0, w_scaled, (int)(h+3*scale) );
fl_color(text_color);
#if defined(USE_X11) && !USE_XFT
// force seeing this font as new so it's applied to the offscreen graphics context
fl_graphics_driver->font_descriptor(NULL);
fl_graphics_driver->Fl_Graphics_Driver::font(fontnum, 0);
fl_font(fontnum, 0);
#endif
fl_font(fontnum, (Fl_Fontsize)(scale * old_size) );
fl_draw(str, n, 1, (int)(h * 0.8) ); // draw string in offscreen
int w2 = (int)fl_width(str, n);
// read (most of) the offscreen image
uchar *img = fl_read_image(NULL, 1, 1, w, h, 0);
uchar *img = fl_read_image(NULL, 1, 1, w2, h, 0);
fl_end_offscreen();
fl_font(fontnum, old_size);
driver->font(fontnum, old_size);
fl_delete_offscreen(off);
// compute the mask of what is not the background
uchar *mask = calc_mask(img, w, h, bg_color);
uchar *mask = calc_mask(img, w2, h, bg_color);
delete[] img;
// write the string image to PostScript as a scaled bitmask
fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w/scale, h/scale, w, h);
scale = w2 / float(w);
fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h);
uchar *di;
int wmask = (w+7)/8;
int wmask = (w2+7)/8;
for (int j = h - 1; j >= 0; j--){
di = mask + j * wmask;
for (int i = 0; i < wmask; i++){
@ -1101,13 +1121,13 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou
int len, code;
if (!n || !str || !*str) return;
// compute display width of string
int width = (int)fl_width(str, n);
if (width == 0) return;
if (fl_font() >= FL_FREE_FONT) {
transformed_draw_extra(str, n, x, y, width, output);
int w = (int)width(str, n);
if (w == 0) return;
if (Fl_Graphics_Driver::font() >= FL_FREE_FONT) {
transformed_draw_extra(str, n, x, y, w, output, this);
return;
}
fprintf(output, "%d <", width);
fprintf(output, "%d <", w);
// transforms UTF8 encoding to our custom PostScript encoding as follows:
// extract each unicode character
// if unicode <= 0x17F, unicode and PostScript codes are identical
@ -1129,7 +1149,7 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou
}
else { // unhandled character: draw all string as bitmap image
fprintf(output, "> pop pop\n"); // close and ignore the opened hex string
transformed_draw_extra(str, n, x, y, width, output);
transformed_draw_extra(str, n, x, y, w, output, this);
return;
}
fprintf(output, "%4.4X", utf);

View File

@ -81,11 +81,13 @@ void fl_text_extents(const char *c, int &dx, int &dy, int &w, int &h) {
} // fl_text_extents
#ifndef __APPLE__
void fl_draw(const char* str, int l, float x, float y) {
#ifdef __APPLE__
fl_graphics_driver->draw(str, l, x, y);
#else
fl_draw(str, l, (int)x, (int)y);
}
#endif
}
//
// End of "$Id$".
//

View File

@ -30,9 +30,6 @@
/* from fl_utf.c */
extern unsigned fl_utf8toUtf16(const char* src, unsigned srclen, unsigned short* dst, unsigned dstlen);
// if no font has been selected yet by the user, get one.
#define check_default_font() {if (!fl_fontsize) fl_font(FL_HELVETICA, FL_NORMAL_SIZE);}
static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
static CFMutableDictionaryRef attributes = NULL;
@ -251,26 +248,22 @@ void Fl_Quartz_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
this->font_descriptor( find(fnum, size) );
}
int fl_height() {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
check_default_font();
if (fl_fontsize) return fl_fontsize->ascent+fl_fontsize->descent;
else return -1;
int Fl_Quartz_Graphics_Driver::height() {
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
return fl_fontsize->ascent + fl_fontsize->descent;
}
int fl_descent() {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
check_default_font();
if (fl_fontsize)
return fl_fontsize->descent+1;
else return -1;
int Fl_Quartz_Graphics_Driver::descent() {
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
return fl_fontsize->descent+1;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
// returns width of a pair of UniChar's in the surrogate range
static CGFloat surrogate_width(const UniChar *txt)
static CGFloat surrogate_width(const UniChar *txt, Fl_Font_Descriptor *fl_fontsize)
{
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, txt, 2, kCFAllocatorNull);
CTFontRef font2 = CTFontCreateForString(fl_fontsize->fontref, str, CFRangeMake(0,2));
CFRelease(str);
@ -284,14 +277,7 @@ static CGFloat surrogate_width(const UniChar *txt)
}
#endif
static double fl_width(const UniChar* txt, int n) {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
check_default_font();
if (!fl_fontsize) {
check_default_font(); // avoid a crash!
if (!fl_fontsize)
return 8*n; // user must select a font first!
}
static double fl_mac_width(const UniChar* txt, int n, Fl_Font_Descriptor *fl_fontsize) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if (fl_mac_os_version >= 0x1050) {
double retval = 0;
@ -300,7 +286,7 @@ if (fl_mac_os_version >= 0x1050) {
for (i = 0; i < n; i++) { // loop over txt
uni = txt[i];
if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
retval += surrogate_width(txt + i);
retval += surrogate_width(txt + i, fl_fontsize);
i++; // because a pair of UniChar's represent a single character
continue;
}
@ -370,27 +356,23 @@ if (fl_mac_os_version >= 0x1050) {
return 0;
}
double fl_width(const char* txt, int n) {
double Fl_Quartz_Graphics_Driver::width(const char* txt, int n) {
int wc_len = n;
UniChar *uniStr = mac_Utf8_to_Utf16(txt, n, &wc_len);
return fl_width(uniStr, wc_len);
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
return fl_mac_width(uniStr, wc_len, font_descriptor());
}
double fl_width(unsigned int wc) {
double Fl_Quartz_Graphics_Driver::width(unsigned int wc) {
const UniChar uc = wc;
return fl_width(&uc, 1);
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
return fl_mac_width(&uc, 1, font_descriptor());
}
// text extent calculation
void fl_text_extents(const char *str8, int n, int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
if (!fl_fontsize) {
check_default_font(); // avoid a crash!
if (!fl_fontsize)
w = int(8.0 * n); // user must select a font first!
h = int(8.0);
return;
}
void Fl_Quartz_Graphics_Driver::text_extents(const char *str8, int n, int &dx, int &dy, int &w, int &h) {
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if (fl_mac_os_version >= 0x1050) {
CFStringRef str16 = CFStringCreateWithBytes(NULL, (const UInt8*)str8, n, kCFStringEncodingUTF8, false);
@ -443,14 +425,6 @@ else {
return;
} // fl_text_extents
void fl_draw(const char *str, int n, float x, float y);
void Fl_Quartz_Graphics_Driver::draw(const char* str, int n, int x, int y) {
fl_draw(str, n, (float)x-0.0f, (float)y+0.5f);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
static CGColorRef flcolortocgcolor(Fl_Color i)
{
@ -465,11 +439,7 @@ static CGColorRef flcolortocgcolor(Fl_Color i)
}
#endif
void fl_draw(const char *str, int n, float x, float y) {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
// avoid a crash if no font has been selected by user yet !
check_default_font();
static void fl_mac_draw(const char *str, int n, float x, float y, Fl_Font_Descriptor *fl_fontsize) {
// convert to UTF-16 first
UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
@ -512,16 +482,28 @@ void fl_draw(const char *str, int n, float x, float y) {
#endif
}
void Fl_Quartz_Graphics_Driver::draw(const char *str, int n, float x, float y) {
// avoid a crash if no font has been selected by user yet !
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
fl_mac_draw(str, n, x, y, font_descriptor());
}
void Fl_Quartz_Graphics_Driver::draw(const char* str, int n, int x, int y) {
// avoid a crash if no font has been selected by user yet !
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
fl_mac_draw(str, n, (float)x-0.0f, (float)y+0.5f, font_descriptor());
}
void Fl_Quartz_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
CGContextSaveGState(fl_gc);
CGContextTranslateCTM(fl_gc, x, y);
CGContextRotateCTM(fl_gc, - angle*(M_PI/180) );
fl_draw(str, n, (float)0., (float)0.);
draw(str, n, 0, 0);
CGContextRestoreGState(fl_gc);
}
void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
draw(c, n, int(x - fl_width(c, n)), y);
draw(c, n, int(x - width(c, n)), y);
}
//

View File

@ -146,14 +146,14 @@ void Fl_GDI_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
fl_font(this, fnum, size, 0);
}
int fl_height() {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
int Fl_GDI_Graphics_Driver::height() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
else return -1;
}
int fl_descent() {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
int Fl_GDI_Graphics_Driver::descent() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (fl_fontsize) return fl_fontsize->metr.tmDescent;
else return -1;
}
@ -163,9 +163,9 @@ static xchar *wstr = NULL;
static int wstr_len = 0;
double fl_width(const char* c, int n) {
double Fl_GDI_Graphics_Driver::width(const char* c, int n) {
int i = 0;
if (!fl_graphics_driver->font_descriptor()) return -1.0;
if (!font_descriptor()) return -1.0;
double w = 0.0;
char *end = (char *)&c[n];
while (i < n) {
@ -176,14 +176,14 @@ double fl_width(const char* c, int n) {
// if (l < 1) l = 1;
i += l;
if (!fl_nonspacing(ucs)) {
w += fl_width(ucs);
w += width(ucs);
}
}
return w;
}
double fl_width(unsigned int c) {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
double Fl_GDI_Graphics_Driver::width(unsigned int c) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
unsigned int r;
r = (c & 0xFC00) >> 10;
if (!fl_fontsize->width[r]) {
@ -255,8 +255,8 @@ static unsigned short *ext_buff = NULL; // UTF-16 converted version of input UTF
static unsigned wc_len = 0; // current string buffer dimension
static WORD *gi = NULL; // glyph indices array
// Function to determine the extent of the "inked" area of the glyphs in a string
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
void Fl_GDI_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (!fl_fontsize) {
w = 0; h = 0;
dx = dy = 0;
@ -326,10 +326,10 @@ void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
exit_error:
// some error here - just return fl_measure values
w = (int)fl_width(c, n);
h = fl_height();
w = (int)width(c, n);
h = height();
dx = 0;
dy = fl_descent() - h;
dy = descent() - h;
EXTENTS_UPDATE(dx, dy, w, h);
return;
} // fl_text_extents
@ -339,10 +339,10 @@ void Fl_GDI_Graphics_Driver::draw(const char* str, int n, int x, int y) {
int lx = 0;
char *end = (char *)&str[n];
COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
SelectObject(fl_gc, fl_graphics_driver->font_descriptor()->fid);
SelectObject(fl_gc, font_descriptor()->fid);
while (i < n) {
unsigned int u;
unsigned int u1;
unsigned int u1;
unsigned short ucs;
// int l = fl_utf2ucs((const unsigned char*)str + i, n - i, &u);
int l;
@ -351,7 +351,7 @@ void Fl_GDI_Graphics_Driver::draw(const char* str, int n, int x, int y) {
x -= lx;
u = u1;
} else {
lx = (int) fl_width(u);
lx = (int) width(u);
}
ucs = u;
if (l < 1) l = 1;
@ -367,7 +367,7 @@ void Fl_GDI_Graphics_Driver::draw(int angle, const char* str, int n, int x, int
int i = 0, i2=0;
char *end = (char *)&str[n];
COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
SelectObject(fl_gc, fl_graphics_driver->font_descriptor()->fid);
SelectObject(fl_gc, font_descriptor()->fid);
//unsigned short ucs[n]; //only GCC, but not MSVC
unsigned short* ucs = new unsigned short[n];
while (i < n) {
@ -395,12 +395,12 @@ void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
}
COLORREF oldColor = SetTextColor(fl_gc, fl_RGB());
SelectObject(fl_gc, fl_graphics_driver->font_descriptor()->fid);
SelectObject(fl_gc, font_descriptor()->fid);
#ifdef RTL_CHAR_BY_CHAR
int i = 0;
int lx = 0;
while (i < wn) { // output char by char is very bad for Arabic but coherent with fl_width()
lx = (int) fl_width(wstr[i]);
lx = (int) width(wstr[i]);
x -= lx;
TextOutW(fl_gc, x, y, (WCHAR*)wstr + i, 1);
if (fl_nonspacing(wstr[i])) {
@ -410,7 +410,7 @@ void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
}
#else
UINT old_align = SetTextAlign(fl_gc, TA_RIGHT | TA_RTLREADING);
TextOutW(fl_gc, x, y - fl_height() + fl_descent(), (WCHAR*)wstr, wn);
TextOutW(fl_gc, x, y - height() + descent(), (WCHAR*)wstr, wn);
SetTextAlign(fl_gc, old_align);
#endif
SetTextColor(fl_gc, oldColor);

View File

@ -278,36 +278,35 @@ void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
}
}
#define current_font (fl_graphics_driver->font_descriptor()->font)
int fl_height() {
if (fl_graphics_driver->font_descriptor()) return current_font->ascent + current_font->descent;
int Fl_Xlib_Graphics_Driver::height() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
else return -1;
}
int fl_descent() {
if (fl_graphics_driver->font_descriptor()) return current_font->descent;
int Fl_Xlib_Graphics_Driver::descent() {
if (font_descriptor()) return font_descriptor()->font->descent;
else return -1;
}
double fl_width(const char* c, int n) {
if (fl_graphics_driver->font_descriptor()) return (double) XUtf8TextWidth(current_font, c, n);
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_width(unsigned int c) {
if (fl_graphics_driver->font_descriptor()) return (double) XUtf8UcsWidth(current_font, c);
double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
else return -1;
}
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
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 (!fl_graphics_driver->font_descriptor()) fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = fl_gc;
XSetFont(fl_display, fl_gc, current_font->fid);
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, current_font, fl_gc, &xx, &yy, &ww, &hh, c, n);
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...

View File

@ -108,14 +108,12 @@ static Fl_Fontdesc built_in_table[] = {
Fl_Fontdesc* fl_fonts = built_in_table;
#define current_font (fl_graphics_driver->font_descriptor()->font)
Fl_XFont_On_Demand fl_xfont;
void *fl_xftfont = 0;
//const char* fl_encoding_ = "iso8859-1";
const char* fl_encoding_ = "iso10646-1";
static void fl_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) {
if (fnum==-1) { // special case to stop font caching
driver->Fl_Graphics_Driver::font(0, 0);
return;
@ -145,10 +143,10 @@ static void fl_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize s
}
void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
fl_font(this,fnum,size,0);
fl_xft_font(this,fnum,size,0);
}
static XftFont* fontopen(const char* name, bool core, int angle) {
static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angle) {
// Check: does it look like we have been passed an old-school XLFD fontname?
bool is_xlfd = false;
int hyphen_count = 0;
@ -225,7 +223,7 @@ static XftFont* fontopen(const char* name, bool core, int angle) {
// Construct a match pattern for the font we want...
XftPatternAddInteger(fnt_pat, XFT_WEIGHT, weight);
XftPatternAddInteger(fnt_pat, XFT_SLANT, slant);
XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)fl_graphics_driver->size());
XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)size);
XftPatternAddString (fnt_pat, XFT_ENCODING, fl_encoding_);
// rotate font if angle!=0
@ -285,7 +283,7 @@ static XftFont* fontopen(const char* name, bool core, int angle) {
// last chance, just open any font in the right size
the_font = XftFontOpen (fl_display, fl_screen,
XFT_FAMILY, XftTypeString, "sans",
XFT_SIZE, XftTypeDouble, (double)fl_graphics_driver->size(),
XFT_SIZE, XftTypeDouble, (double)size,
NULL);
XftPatternDestroy(fnt_pat);
if (!the_font) {
@ -342,7 +340,7 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int
#if HAVE_GL
listbase = 0;
#endif // HAVE_GL
font = fontopen(name, false, angle);
font = fontopen(name, fsize, false, angle);
}
Fl_Font_Descriptor::~Fl_Font_Descriptor() {
@ -373,57 +371,57 @@ static const wchar_t *utf8reformat(const char *str, int& n)
return buffer;
}
static void utf8extents(const char *str, int n, XGlyphInfo *extents)
static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents)
{
memset(extents, 0, sizeof(XGlyphInfo));
const wchar_t *buffer = utf8reformat(str, n);
#ifdef __CYGWIN__
XftTextExtents16(fl_display, current_font, (XftChar16 *)buffer, n, extents);
XftTextExtents16(fl_display, desc->font, (XftChar16 *)buffer, n, extents);
#else
XftTextExtents32(fl_display, current_font, (XftChar32 *)buffer, n, extents);
XftTextExtents32(fl_display, desc->font, (XftChar32 *)buffer, n, extents);
#endif
}
int fl_height() {
if (fl_graphics_driver->font_descriptor()) return current_font->ascent + current_font->descent;
int Fl_Xlib_Graphics_Driver::height() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
else return -1;
}
int fl_descent() {
if (fl_graphics_driver->font_descriptor()) return current_font->descent;
int Fl_Xlib_Graphics_Driver::descent() {
if (font_descriptor()) return font_descriptor()->font->descent;
else return -1;
}
double fl_width(const char *str, int n) {
if (!fl_graphics_driver->font_descriptor()) return -1.0;
double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
if (!font_descriptor()) return -1.0;
XGlyphInfo i;
utf8extents(str, n, &i);
utf8extents(font_descriptor(), str, n, &i);
return i.xOff;
}
double fl_width(uchar c) {
return fl_width((const char *)(&c), 1);
}
/*double fl_width(uchar c) {
return fl_graphics_driver->width((const char *)(&c), 1);
}*/
double fl_width(FcChar32 *str, int n) {
if (!fl_graphics_driver->font_descriptor()) return -1.0;
static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
if (!desc) return -1.0;
XGlyphInfo i;
XftTextExtents32(fl_display, current_font, str, n, &i);
XftTextExtents32(fl_display, desc->font, str, n, &i);
return i.xOff;
}
double fl_width(unsigned int c) {
return fl_width((FcChar32 *)(&c), 1);
double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
}
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
if (!fl_graphics_driver->font_descriptor()) {
void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
if (!font_descriptor()) {
w = h = 0;
dx = dy = 0;
return;
}
XGlyphInfo gi;
utf8extents(c, n, &gi);
utf8extents(font_descriptor(), c, n, &gi);
w = gi.width;
h = gi.height;
@ -453,10 +451,10 @@ void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
// original fltk code did.
// NOTE: On my test boxes (FC6, FC7, FC8, ubuntu8.04, 9.04, 9.10) this works
// well for the fltk "built-in" font names.
static XFontStruct* load_xfont_for_xft2(void) {
static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
XFontStruct* xgl_font = 0;
int size = fl_graphics_driver->size();
int fnum = fl_graphics_driver->font();
int size = driver->size();
int fnum = driver->font();
const char *wt_med = "medium";
const char *wt_bold = "bold";
const char *weight = wt_med; // no specifc weight requested - accept any
@ -521,7 +519,7 @@ static XFontStruct* load_xfont_for_xft2(void) {
} // end of load_xfont_for_xft2
# endif
XFontStruct* fl_xxfont() {
static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) {
# if XFT_MAJOR > 1
// kludge! XFT 2 and later does not provide core fonts for us to use with GL
// try to load a bitmap X font instead
@ -529,25 +527,27 @@ XFontStruct* fl_xxfont() {
static int glsize = 0;
static int glfont = -1;
// Do we need to load a new font?
if ((!xgl_font) || (glsize != fl_graphics_driver->size()) || (glfont != fl_graphics_driver->font())) {
if ((!xgl_font) || (glsize != driver->size()) || (glfont != driver->font())) {
// create a dummy XLFD for some font of the appropriate size...
if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea
glsize = fl_graphics_driver->size(); // record current font size
glfont = fl_graphics_driver->font(); // and face
xgl_font = load_xfont_for_xft2();
glsize = driver->size(); // record current font size
glfont = driver->font(); // and face
xgl_font = load_xfont_for_xft2(driver);
}
return xgl_font;
# else // XFT-1 provides a means to load a "core" font directly
if (current_font->core) return current_font->u.core.font; // is the current font a "core" font? If so, use it.
if (driver->font_descriptor()->font->core) {
return driver->font_descriptor()->font->u.core.font; // is the current font a "core" font? If so, use it.
}
static XftFont* xftfont;
if (xftfont) XftFontClose (fl_display, xftfont);
xftfont = fontopen(fl_fonts[fl_graphics_driver->font()].name, true); // else request XFT to load a suitable "core" font instead.
xftfont = fontopen(fl_fonts[driver->font()].name, driver->size(), true, 0); // else request XFT to load a suitable "core" font instead.
return xftfont->u.core.font;
# endif // XFT_MAJOR > 1
}
XFontStruct* Fl_XFont_On_Demand::value() {
if (!ptr) ptr = fl_xxfont();
if (!ptr) ptr = fl_xxfont(fl_graphics_driver);
return ptr;
}
@ -606,8 +606,8 @@ void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
// Use fltk's color allocator, copy the results to match what
// XftCollorAllocValue returns:
XftColor color;
color.pixel = fl_xpixel(fl_graphics_driver->color());
uchar r,g,b; Fl::get_color(fl_graphics_driver->color(), r,g,b);
color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
color.color.red = ((int)r)*0x101;
color.color.green = ((int)g)*0x101;
color.color.blue = ((int)b)*0x101;
@ -615,19 +615,19 @@ void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
const wchar_t *buffer = utf8reformat(str, n);
#ifdef __CYGWIN__
XftDrawString16(draw_, &color, current_font, x, y, (XftChar16 *)buffer, n);
XftDrawString16(draw_, &color, font_descriptor()->font, x, y, (XftChar16 *)buffer, n);
#else
XftDrawString32(draw_, &color, current_font, x, y, (XftChar32 *)buffer, n);
XftDrawString32(draw_, &color, font_descriptor()->font, x, y, (XftChar32 *)buffer, n);
#endif
}
void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
fl_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
this->draw(str, n, (int)x, (int)y);
this->font(this->Fl_Graphics_Driver::font(), this->size());
fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
}
static void fl_drawUCS4(const FcChar32 *str, int n, int x, int y) {
static void fl_drawUCS4(Fl_Graphics_Driver *driver, const FcChar32 *str, int n, int x, int y) {
#if USE_OVERLAY
XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
if (fl_overlay) {
@ -651,14 +651,14 @@ static void fl_drawUCS4(const FcChar32 *str, int n, int x, int y) {
// Use fltk's color allocator, copy the results to match what
// XftCollorAllocValue returns:
XftColor color;
color.pixel = fl_xpixel(fl_graphics_driver->color());
uchar r,g,b; Fl::get_color(fl_graphics_driver->color(), r,g,b);
color.pixel = fl_xpixel(driver->color());
uchar r,g,b; Fl::get_color(driver->color(), r,g,b);
color.color.red = ((int)r)*0x101;
color.color.green = ((int)g)*0x101;
color.color.blue = ((int)b)*0x101;
color.color.alpha = 0xffff;
XftDrawString32(draw_, &color, current_font, x, y, (FcChar32 *)str, n);
XftDrawString32(draw_, &color, driver->font_descriptor()->font, x, y, (FcChar32 *)str, n);
}
@ -694,8 +694,8 @@ void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
out = out - 1;
}
// Now we have a UCS4 version of the input text, reversed, in ucs_txt
int offs = (int)fl_width(ucs_txt, n);
fl_drawUCS4(ucs_txt, n, (x-offs), y);
int offs = (int)fl_xft_width(font_descriptor(), ucs_txt, n);
fl_drawUCS4(this, ucs_txt, n, (x-offs), y);
delete[] ucs_txt;
}

View File

@ -45,7 +45,7 @@
#endif
#if USE_XFT
extern XFontStruct* fl_xxfont();
//extern XFontStruct* fl_xxfont();
#endif // USE_XFT
/** Returns the current font's height */