00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_GFX_GLXRASTERFONT_H_UTC20050626084025_DEFINED
00035 #define GROOVX_GFX_GLXRASTERFONT_H_UTC20050626084025_DEFINED
00036
00037 #include "geom/rect.h"
00038 #include "geom/vec3.h"
00039
00040 #include "gfx/bbox.h"
00041 #include "gfx/fontspec.h"
00042 #include "gfx/glcanvas.h"
00043 #include "gfx/gxrasterfont.h"
00044
00045 #include "rutz/error.h"
00046 #include "rutz/fstring.h"
00047 #include "rutz/sfmt.h"
00048
00049 #include <cctype>
00050 #include <cstdio>
00051 #include <cstdlib>
00052 #include <cstring>
00053 #include <GL/gl.h>
00054 #include <GL/glx.h>
00055 #include <X11/Xlib.h>
00056
00057 #include "rutz/trace.h"
00058 #include "rutz/debug.h"
00059 GVX_DBG_REGISTER
00060
00061 class GlxRasterFont : public GxRasterFont
00062 {
00063 public:
00064 GlxRasterFont(const char* n);
00065 virtual ~GlxRasterFont() throw();
00066
00067 static rutz::fstring pickXFont(const char* spec);
00068
00069 virtual const char* fontName() const;
00070
00071 virtual unsigned int listBase() const;
00072
00073 virtual void bboxOf(const char* text, Gfx::Bbox& bbox) const;
00074
00075 virtual void drawText(const char* text, Gfx::Canvas& canvas) const;
00076
00078 virtual int rasterHeight() const;
00079
00080 private:
00081 XFontStruct* itsFontInfo;
00082 rutz::fstring itsFontName;
00083 unsigned int itsListBase;
00084 unsigned int itsListCount;
00085 };
00086
00087 GlxRasterFont::GlxRasterFont(const char* fontname) :
00088 itsFontInfo(0),
00089 itsFontName(fontname ? fontname : "fixed"),
00090 itsListBase(0),
00091 itsListCount(0)
00092 {
00093 GVX_TRACE("GlxRasterFont::GlxRasterFont");
00094
00095 static Display* dpy = 0;
00096
00097 if (dpy == 0)
00098 {
00099 dpy = XOpenDisplay(getenv("DISPLAY"));
00100 if (dpy == 0)
00101 throw rutz::error("couldn't open X server connection", SRC_POS);
00102 }
00103
00104 rutz::fstring xname = pickXFont(fontname);
00105
00106 dbg_eval_nl(2, xname.c_str());
00107 dbg_eval_nl(2, xname);
00108
00109 itsFontInfo = XLoadQueryFont( dpy, xname.c_str() );
00110
00111 dbg_eval_nl(2, itsFontInfo);
00112
00113 if (itsFontInfo == 0)
00114 {
00115 throw rutz::error(rutz::sfmt("couldn't load X font '%s'",
00116 xname.c_str()),
00117 SRC_POS);
00118 }
00119
00120 dbg_eval_nl(2, itsFontInfo->fid);
00121
00122 const int first = itsFontInfo->min_char_or_byte2; dbg_eval(2, first);
00123 const int last = itsFontInfo->max_char_or_byte2; dbg_eval(2, last);
00124
00125 itsListCount = last-first+1;
00126 itsListBase = GLCanvas::genLists( last+1 );
00127
00128 dbg_eval_nl(2, itsListCount);
00129 dbg_eval_nl(2, itsListBase);
00130
00131 if (itsListBase==0)
00132 {
00133 XFreeFontInfo(NULL, itsFontInfo, 1);
00134 throw rutz::error("couldn't allocate GL display lists", SRC_POS);
00135 }
00136
00137 glXUseXFont(itsFontInfo->fid,
00138 first,
00139 itsListCount,
00140 static_cast<int>(itsListBase+first));
00141
00142 #if 0
00143
00144 for (int l = first; l < first+itsListCount; ++l)
00145 {
00146 double p = 4*double((l-first-1)-48)/42.0 - 2.0;
00147 glRasterPos2d(-1.0, p);
00148 glCallList(l);
00149 }
00150 glFlush();
00151 #endif
00152 }
00153
00154 GlxRasterFont::~GlxRasterFont() throw()
00155 {
00156 GVX_TRACE("GlxRasterFont::~GlxRasterFont");
00157
00158 GLCanvas::deleteLists(itsListBase, itsListCount);
00159 XFreeFontInfo(NULL, itsFontInfo, 1);
00160 }
00161
00162 rutz::fstring GlxRasterFont::pickXFont(const char* spec)
00163 {
00164 GVX_TRACE("GlxRasterFont::pickXFont");
00165
00166 if (isdigit(spec[0]))
00167 {
00168
00169 return rutz::fstring(spec);
00170 }
00171 else if (spec[0] == '-')
00172 {
00173
00174 return rutz::fstring(spec);
00175 }
00176 else
00177 {
00178 const char* foundry = "*";
00179 rutz::fstring family= "helvetica";
00180 const char* weight = "medium";
00181 const char* slant = "r";
00182 const char* width = "normal";
00183 const char* style = "*";
00184 rutz::fstring pxlsize= "12";
00185 const char* ptsize = "*";
00186 const char* resx = "*";
00187 const char* resy = "*";
00188 const char* spc = "*";
00189 const char* avgwid = "*";
00190 const char* rgstry = "*";
00191 const char* encdng = "*";
00192
00193 rutz::fstring mods = "";
00194
00195 parseFontSpec(spec, &family, &pxlsize, &mods);
00196
00197 const char* mod = mods.c_str();
00198 while (*mod != '\0')
00199 {
00200 switch (*mod)
00201 {
00202 case 'b': weight = "bold"; break;
00203 case 'i': slant = "i"; break;
00204 case 'o': slant = "o"; break;
00205 }
00206 ++mod;
00207 }
00208
00209 char buf[256];
00210
00211 snprintf(buf, 256, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
00212 foundry,
00213 family.c_str(),
00214 weight,
00215 slant,
00216 width,
00217 style,
00218 pxlsize.c_str(),
00219 ptsize,
00220 resx,
00221 resy,
00222 spc,
00223 avgwid,
00224 rgstry,
00225 encdng);
00226 dbg_eval_nl(2, buf);
00227 return rutz::fstring(buf);
00228 }
00229 }
00230
00231 const char* GlxRasterFont::fontName() const
00232 {
00233 GVX_TRACE("GlxRasterFont::fontName");
00234 return itsFontName.c_str();
00235 }
00236
00237 unsigned int GlxRasterFont::listBase() const
00238 {
00239 GVX_TRACE("GlxRasterFont::listBase");
00240 return itsListBase;
00241 }
00242
00243 namespace
00244 {
00245 int linelength(const char* p)
00246 {
00247 int n = 0;
00248 while (p[n] != '\n' && p[n] != '\0')
00249 {
00250 ++n;
00251 }
00252 return n;
00253 }
00254 }
00255
00256 void GlxRasterFont::bboxOf(const char* text, Gfx::Bbox& bbox) const
00257 {
00258 GVX_TRACE("GlxRasterFont::bboxOf");
00259
00260 const int asc = itsFontInfo->max_bounds.ascent;
00261 const int desc = itsFontInfo->max_bounds.descent;
00262
00263 int maxwid = 0;
00264
00265 int lines = 0;
00266
00267 while (1)
00268 {
00269 int len = linelength(text);
00270 int wid = XTextWidth(itsFontInfo, text, len);
00271 text += len;
00272 if (wid > maxwid)
00273 maxwid = wid;
00274
00275 ++lines;
00276
00277 if (*text == '\0')
00278 break;
00279
00280 GVX_ASSERT(*text == '\n');
00281 ++text;
00282 }
00283
00284 dbg_eval(2, lines);
00285 dbg_eval(2, asc);
00286 dbg_eval(2, desc);
00287 dbg_eval_nl(2, maxwid);
00288
00289 const int l = 0;
00290 const int r = maxwid;
00291 const int b = -(desc + (lines - 1) * (asc+desc));
00292 const int t = asc;
00293
00294 dbg_eval(2, l);
00295 dbg_eval(2, r);
00296 dbg_eval(2, b);
00297 dbg_eval_nl(2, t);
00298
00299 GVX_ASSERT(r >= 0);
00300 GVX_ASSERT(b <= 0);
00301 GVX_ASSERT(t >= 0);
00302
00303 bbox.drawScreenRect(geom::vec3d::zeros(),
00304 geom::rect<int>::ltrb(l,t,r,b));
00305 }
00306
00307 void GlxRasterFont::drawText(const char* text,
00308 Gfx::Canvas& canvas) const
00309 {
00310 GVX_TRACE("GlxRasterFont::drawText");
00311
00312 canvas.drawRasterText(text, *this);
00313 }
00314
00315 int GlxRasterFont::rasterHeight() const
00316 {
00317 GVX_TRACE("GlxRasterFont::rasterHeight");
00318 const int asc = itsFontInfo->max_bounds.ascent;
00319 const int desc = itsFontInfo->max_bounds.descent;
00320
00321 return asc + desc;
00322 }
00323
00324 static const char __attribute__((used)) vcid_groovx_gfx_glxrasterfont_h_utc20050626084025[] = "$Id: glxrasterfont.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00325 #endif // !GROOVX_GFX_GLXRASTERFONT_H_UTC20050626084025_DEFINED