summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan MacArthur <imacarthur@gmail.com>2008-11-19 20:34:27 +0000
committerIan MacArthur <imacarthur@gmail.com>2008-11-19 20:34:27 +0000
commit865f3d8e61f5fe7a582f1233b90bd2ef8260c827 (patch)
tree09421807f61cff4476a26387880c9bcef15e0e27
parent9c7af9b2cf586dd9aaf0b11793514f458d09afed (diff)
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
-rw-r--r--FL/fl_draw.H10
-rw-r--r--src/fl_font.cxx19
-rw-r--r--src/fl_font_mac.cxx42
-rw-r--r--src/fl_font_win32.cxx82
-rw-r--r--src/fl_font_x.cxx10
-rw-r--r--src/fl_font_xft.cxx26
6 files changed, 171 insertions, 18 deletions
diff --git a/FL/fl_draw.H b/FL/fl_draw.H
index 4511ccc4f..4a17bdec1 100644
--- a/FL/fl_draw.H
+++ b/FL/fl_draw.H
@@ -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.
diff --git a/src/fl_font.cxx b/src/fl_font.cxx
index bb65303b7..20bdc198b 100644
--- a/src/fl_font.cxx
+++ b/src/fl_font.cxx
@@ -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);
diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx
index c5d04c6ed..15791f0e1 100644
--- a/src/fl_font_mac.cxx
+++ b/src/fl_font_mac.cxx
@@ -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) {
diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx
index f55389126..eda3d7878 100644
--- a/src/fl_font_win32.cxx
+++ b/src/fl_font_win32.cxx
@@ -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;
diff --git a/src/fl_font_x.cxx b/src/fl_font_x.cxx
index 04b3738d8..aeabe6765 100644
--- a/src/fl_font_x.cxx
+++ b/src/fl_font_x.cxx
@@ -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);
diff --git a/src/fl_font_xft.cxx b/src/fl_font_xft.cxx
index 6d73de6b4..970db3ccd 100644
--- a/src/fl_font_xft.cxx
+++ b/src/fl_font_xft.cxx
@@ -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
}