Skip to content

Commit

Permalink
Added virtual width(), height(), descent() and text_extents() functio…
Browse files Browse the repository at this point in the history
…ns 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
  • Loading branch information
Manolo Gouy authored and Manolo Gouy committed Feb 18, 2011
1 parent 2c129b4 commit 199b32d
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 171 deletions.
36 changes: 35 additions & 1 deletion FL/Fl_Device.H
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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). */
Expand Down Expand Up @@ -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 */
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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))
Expand All @@ -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

Expand Down
7 changes: 7 additions & 0 deletions FL/Fl_PostScript.H
Expand Up @@ -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
Expand Down Expand Up @@ -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);};
Expand Down
11 changes: 6 additions & 5 deletions FL/fl_draw.H
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions src/Fl_Device.cxx
Expand Up @@ -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$".
//
66 changes: 43 additions & 23 deletions src/Fl_PostScript.cxx
Expand Up @@ -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;
Expand All @@ -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_);
Expand Down Expand Up @@ -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++){
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions src/fl_font.cxx
Expand Up @@ -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$".
//

0 comments on commit 199b32d

Please sign in to comment.