STR 2076: experimental fl_text_extents patch applied. Please feedback comments.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6529 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Ian MacArthur 2008-11-19 20:34:27 +00:00
parent 9c7af9b2cf
commit 865f3d8e61
6 changed files with 171 additions and 18 deletions

View File

@ -194,12 +194,16 @@ inline int fl_height(int, int size) {return size;}
draw the text at so it looks centered vertically in that box.
*/
FL_EXPORT int fl_descent();
/** Return the pixel width of a nul-terminated string */
/** Return the typographical width of a nul-terminated string */
FL_EXPORT double fl_width(const char* txt);
/** Return the pixel width of a sequence of \a n characters */
/** Return the typographical width of a sequence of \a n characters */
FL_EXPORT double fl_width(const char* txt, int n);
/** Return the pixed width of a single character */
/** Return the typographical width of a single character */
FL_EXPORT double fl_width(Fl_Unichar);
/** Determine the minimum pixel dimensions of a nul-terminated string */
FL_EXPORT void fl_text_extents(const char*, int& dx, int& dy, int& w, int& h); // NO fltk symbol expansion
/** Determine the minimum pixel dimensions of a sequence of \a n characters */
FL_EXPORT void fl_text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
/**
Draw a nul-terminated string starting at the given location.

View File

@ -25,6 +25,17 @@
// http://www.fltk.org/str.php
//
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features such as GetGlyphIndices */
# if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
# endif
# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
# endif
#endif
// Select fonts from the FLTK font table.
#include "flstring.h"
#include <FL/Fl.H>
@ -55,6 +66,14 @@ void fl_draw(const char* str, int x, int y) {
fl_draw(str, strlen(str), x, y);
}
void fl_text_extents(const char *c, int &dx, int &dy, int &w, int &h) {
if (c) return fl_text_extents(c, strlen(c), dx, dy, w, h);
// else
w = 0; h = 0;
dx = 0; dy = 0;
} // fl_text_extents
#if !USE_XFT && !__APPLE__
void fl_draw(const char* str, int l, float x, float y) {
fl_draw(str, l, (int)x, (int)y);

View File

@ -268,6 +268,48 @@ double fl_width(unsigned int wc) {
return fl_width((const UniChar*)(&wc), 1);
}
// text extent calculation
void fl_text_extents(const UniChar* txt, int n, int &dx, int &dy, int &w, int &h) {
if (!fl_fontsize) {
check_default_font(); // avoid a crash!
if (!fl_fontsize)
w = 8.0 * n; // user must select a font first!
h = 8.0;
return;
}
OSStatus err;
ATSUTextLayout layout;
ByteCount iSize;
ATSUAttributeTag iTag;
ATSUAttributeValuePtr iValuePtr;
// Here's my ATSU text measuring attempt... This seems to do the Right Thing
// now collect our ATSU resources and measure our text string
layout = fl_fontsize->layout;
// activate the current GC
iSize = sizeof(CGContextRef);
iTag = kATSUCGContextTag;
iValuePtr = &fl_gc;
ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr);
// now measure the bounding box
err = ATSUSetTextPointerLocation(layout, txt, kATSUFromTextBeginning, n, n);
Rect bbox;
err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, n, 0, 0, &bbox);
w = bbox.right - bbox.left;
h = bbox.bottom - bbox.top;
dx = bbox.left;
dy = -bbox.bottom;
//printf("r: %d l: %d t: %d b: %d w: %d h: %d\n", bbox.right, bbox.left, bbox.top, bbox.bottom, w, h);
return;
} // fl_text_extents
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
int wc_len = n;
UniChar *uniStr = mac_Utf8_to_Utf16(c, n, &wc_len);
fl_text_extents(uniStr, wc_len, dx, dy, w, h);
} // fl_text_extents
void fl_draw(const char *str, int n, float x, float y);
void fl_draw(const char* str, int n, int x, int y) {

View File

@ -37,19 +37,19 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize size) {
}
fid = CreateFont(
-size, // negative makes it use "char size"
0, // logical average character width
0, // angle of escapement
0, // base-line orientation angle
0, // logical average character width
0, // angle of escapement
0, // base-line orientation angle
weight,
italic,
FALSE, // underline attribute flag
FALSE, // strikeout attribute flag
DEFAULT_CHARSET, // character set identifier
OUT_DEFAULT_PRECIS, // output precision
CLIP_DEFAULT_PRECIS,// clipping precision
DEFAULT_QUALITY, // output quality
DEFAULT_PITCH, // pitch and family
name // pointer to typeface name string
FALSE, // underline attribute flag
FALSE, // strikeout attribute flag
DEFAULT_CHARSET, // character set identifier
OUT_DEFAULT_PRECIS, // output precision
CLIP_DEFAULT_PRECIS,// clipping precision
DEFAULT_QUALITY, // output quality
DEFAULT_PITCH, // pitch and family
name // pointer to typeface name string
);
if (!fl_gc) fl_GetDC(0);
SelectObject(fl_gc, fid);
@ -191,6 +191,66 @@ double fl_width(unsigned int c) {
return (double) fl_fontsize->width[r][c & 0x03FF];
}
static unsigned short *ext_buff = NULL; // UTF-16 converted string
static unsigned wc_len = 0; // current string buffer dimension
static WORD *gi = NULL; // glyph indices array
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
if (!fl_fontsize) {
w = 0; h = 0;
dx = dy = 0;
return;
}
static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
GLYPHMETRICS metrics;
int maxw = 0, maxh = 0, dh;
int minx = 0, miny = -999999;
// now convert the string to WCHAR and measure it
unsigned len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
if(len >= wc_len) {
if(ext_buff) {delete [] ext_buff;}
if(gi) {delete [] gi;}
wc_len = len + 64;
ext_buff = new unsigned short[wc_len];
gi = new WORD[wc_len];
len = fl_utf8toUtf16(c, n, ext_buff, wc_len);
}
SelectObject(fl_gc, fl_fontsize->fid);
if (GetGlyphIndicesW(fl_gc, (WCHAR*)ext_buff, len, gi, 0) == GDI_ERROR) {
// some error occured here - just return fl_measure values?
goto exit_error;
}
// now we have the glyph array we measure each glyph in turn...
for(unsigned idx = 0; idx < len; idx++){
if (GetGlyphOutlineW (fl_gc, gi[idx], GGO_METRICS | GGO_GLYPH_INDEX,
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
goto exit_error;
}
maxw += metrics.gmCellIncX;
if(idx == 0) minx = metrics.gmptGlyphOrigin.x;
dh = metrics.gmBlackBoxY - metrics.gmptGlyphOrigin.y;
if(dh > maxh) maxh = dh;
if(miny < metrics.gmptGlyphOrigin.y) miny = metrics.gmptGlyphOrigin.y;
}
// for the last cell, we only want the bounding X-extent, not the glyphs increment step
maxw = maxw - metrics.gmCellIncX + metrics.gmBlackBoxX + metrics.gmptGlyphOrigin.x;
w = maxw - minx;
h = maxh + miny;
dx = minx;
dy = -miny;
return; // normal exit
exit_error:
// some error here - just return fl_measure values
w = (int)fl_width(c, n);
h = fl_height();
dx = 0;
dy = fl_descent() - h;
return;
} // fl_text_extents
void fl_draw(const char* str, int n, int x, int y) {
int i = 0;
int lx = 0;

View File

@ -296,6 +296,16 @@ double fl_width(unsigned int c) {
else return -1;
}
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
#warning fl_text_extents is only a test stub in Xlib build at present
w = 0; h = 0;
fl_measure(c, &w, &h, 0);
dx = 0;
dy = fl_descent() - h;
} // fl_text_extents
void fl_draw(const char* c, int n, int x, int y) {
if (font_gc != fl_gc) {
if (!fl_xfont) fl_font(FL_HELVETICA, 14);

View File

@ -338,6 +338,22 @@ double fl_width(unsigned int c) {
return fl_width((FcChar32 *)(&c), 1);
}
void fl_text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
if (!current_font) {
w = h = 0;
dx = dy = 0;
return;
}
XGlyphInfo gi;
XftTextExtentsUtf8(fl_display, current_font, (XftChar8 *)c, n, &gi);
w = gi.width;
h = gi.height;
dx = -gi.x;
dy = -gi.y;
} // fl_text_extents
#if HAVE_GL
/* This code is used by opengl to get a bitmapped font. The original XFT-1 code
* used XFT's "core" fonts methods to load an XFT font that was actually a
@ -358,12 +374,14 @@ double fl_width(unsigned int c) {
// If this code fails to load the requested font, it falls back through a
// series of tried 'n tested alternatives, ultimately resorting to what the
// original fltk code did.
// NOTE:
// On my test boxes (FC6, FC7) this works well for the fltk "built-in" font names.
// NOTE: On my test boxes (FC6, FC7, FC8, ubuntu8.04) this works well for the
// fltk "built-in" font names.
static XFontStruct* load_xfont_for_xft2(void) {
XFontStruct* xgl_font = 0;
int size = fl_size_;
char *weight = "medium"; // no specifc weight requested - accept any
const char *wt_med = "medium";
const char *wt_bold = "bold";
char *weight = (char *)wt_med; // no specifc weight requested - accept any
char slant = 'r'; // regular non-italic by default
char xlfd[128]; // we will put our synthetic XLFD in here
char *pc = strdup(fl_fonts[fl_font_].name); // what font were we asked for?
@ -372,7 +390,7 @@ static XFontStruct* load_xfont_for_xft2(void) {
switch (*name++) {
case 'I': slant = 'i'; break; // italic
case 'P': slant = 'i'; // bold-italic (falls-through)
case 'B': weight = "bold"; break; // bold
case 'B': weight = (char*)wt_bold; break; // bold
case ' ': break; // regular
default: name--; // no prefix, restore name
}