glxrasterfont.h

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2004-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Tue Jul 20 20:09:41 2004
00010 // commit: $Id: glxrasterfont.h 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/gfx/glxrasterfont.h $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
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> // for getenv()
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   // for debugging
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       // e.g. 8x13, 9x15
00169       return rutz::fstring(spec);
00170     }
00171   else if (spec[0] == '-')
00172     {
00173       // e.g. a full X font name "-adobe-..."
00174       return rutz::fstring(spec);
00175     }
00176   else
00177     {
00178       const char* foundry = "*";
00179       rutz::fstring family= "helvetica";
00180       const char* weight  = "medium"; // black, bold, demibold, light, medium, regular
00181       const char* slant   = "r"; // 'i', 'o', 'r'
00182       const char* width   = "normal"; // condensed, normal
00183       const char* style   = "*"; // could by '', 'ja', 'ko', 'medium', 'sans'
00184       rutz::fstring pxlsize= "12";
00185       const char* ptsize  = "*";
00186       const char* resx    = "*"; // could be 72, 75, 100
00187       const char* resy    = "*"; // could be 72, 75, 100
00188       const char* spc     = "*"; // could be 'c', 'm', 'p'
00189       const char* avgwid  = "*";
00190       const char* rgstry  = "*"; // e.g. iso8859
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

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:38 2008 by Doxygen version 1.5.5.