vgfx-opengl-draw.cpp

Go to the documentation of this file.
00001 /*
00002  * vgfx-opengl-draw.cpp
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Implementation of an OpenGL-based vgfx drawer.  See vgfx-opengl-draw.h
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "vgfx-opengl-draw.h"           // always include our own header first!
00036 
00037 #include "color/color.h"
00038 #include "common/wave_ex.h"
00039 #include "glut-font/glut-font.h"
00040 #include "perf/perf.h"
00041 #include "wave-glut/glut_2d.h"
00042 #include "wave-glut/wave-glut.h"
00043 
00044 
00045 namespace vgfx {
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 //
00050 //      static helper methods
00051 //
00052 ////////////////////////////////////////////////////////////////////////////////
00053 
00054 static void
00055 getOpenGLColorFromString
00056 (
00057 IN const char * text,
00058 OUT glut_color_t& color
00059 )
00060 {
00061         ASSERT(text, "null");
00062         color.clear();
00063 
00064         img_color_t img;
00065         getImgColorFromString(text, img);
00066 
00067 //      DPRINTF("Color string: '%s'", text);
00068 //      img.dump("  img color result");
00069 
00070         float inv = 1.0 / 255.0;
00071         color.set(inv * img.red, inv * img.green, inv * img.blue,
00072             inv * img.alpha);
00073 //      color.dump("  glut color result");
00074 }
00075 
00076 
00077 
00078 ////////////////////////////////////////////////////////////////////////////////
00079 //
00080 //      OGLDrawer -- implementation for the vgfx::Drawer interface
00081 //
00082 ////////////////////////////////////////////////////////////////////////////////
00083 
00084 class OGLDrawer : public Drawer {
00085 public:
00086         ~OGLDrawer(void) throw() { }
00087 
00088         // public class methods ------------------------------------------------
00089         void initialize(void);
00090 
00091         // vgfx::Drawer class interface methods --------------------------------
00092         void pushBrush(IN dword_t key);
00093         void popBrush(IN dword_t key) throw();
00094         void endPath(void);
00095         void refreshBrush(void);
00096         void setTransform(IN const xform_2d_t& T) throw();
00097         void setBrushAttribute(IN eBrushAttribute attrib,
00098                                 IN const char * value);
00099         void setClipRect(IN float left, IN float top,
00100                                 IN float right, IN float bottom);
00101         void drawBezier(IN const bezier::curve_t& curve); 
00102         void drawQuadBezier(IN const bezier::quad_bezier_t& quad);
00103         void drawLine(IN const point_t& p0, IN const point_t& p1);
00104         void drawRect(IN const rect_t& r);
00105         void fillRect(IN const rect_t& r);
00106         void drawText(IN const rect_t& r,
00107                                 IN const char * text);
00108         void getBoundingRect(IN const char * text,
00109                                 OUT rect_t& r);
00110         void getRootTransform(OUT xform_2d_t& T) throw();
00111         bool isPrinter(void) const throw();
00112 
00113 private:
00114         // private typedefs ----------------------------------------------------
00115         struct brush_data_t {
00116                 dword_t         id;
00117                 glut_color_t    color;
00118                 float           lineWidth;
00119         };
00120 
00121         typedef std::vector<brush_data_t> brush_stack_t;
00122 
00123         // private helper methods ----------------------------------------------
00124         // private member data -------------------------------------------------
00125         xform_2d_t              m_T;    // current transform
00126         brush_stack_t           m_brushes;
00127 };
00128 
00129 
00130 
00131 void
00132 OGLDrawer::initialize
00133 (
00134 void
00135 )
00136 {
00137 }
00138 
00139 
00140 
00141 ////////////////////////////////////////////////////////////////////////////////
00142 //
00143 //      OGLDrawer -- vgfx::Drawer class interface methods
00144 //
00145 ////////////////////////////////////////////////////////////////////////////////
00146 
00147 void
00148 OGLDrawer::pushBrush
00149 (
00150 IN dword_t key
00151 )
00152 {
00153 //      DPRINTF("pushBrush: 0x%08x", key);
00154 
00155         brush_data_t bd;
00156         bd.id = key;
00157 
00158         glGetFloatv(GL_CURRENT_COLOR, (GLfloat *) &bd.color.red);
00159 //      bd.color.dump("Just extracted glut color");
00160 
00161         glGetFloatv(GL_LINE_WIDTH, (GLfloat *) &bd.lineWidth);
00162 //      DPRINTF("Just extracted line width: %f", bd.lineWidth);
00163 
00164         m_brushes.push_back(bd);
00165 }
00166 
00167 
00168 
00169 void
00170 OGLDrawer::popBrush
00171 (
00172 IN dword_t key
00173 )
00174 throw()
00175 {
00176 //      DPRINTF("popBrush: 0x%08x", key);
00177 
00178         if (!m_brushes.size()) {
00179                 DPRINTF("ERROR: calling popBrush() on empty brush stack?");
00180                 return;
00181         }
00182 
00183         brush_data_t bd = m_brushes.back();
00184         m_brushes.pop_back();
00185 
00186         // now restore
00187         glut_color_t& gc = bd.color;
00188         glColor4f(gc.red, gc.green, gc.blue, gc.alpha);
00189         glLineWidth(bd.lineWidth);
00190 }
00191 
00192 
00193 
00194 void
00195 OGLDrawer::endPath
00196 (
00197 void
00198 )
00199 {
00200 //      DPRINTF("endPath() NYI");
00201 }
00202 
00203 
00204 
00205 void
00206 OGLDrawer::refreshBrush
00207 (
00208 void
00209 )
00210 {
00211         DPRINTF("refreshBrush() NYI");
00212 }
00213 
00214 
00215 
00216 void
00217 OGLDrawer::setTransform
00218 (
00219 IN const xform_2d_t& T
00220 )
00221 throw()
00222 {
00223         m_T = T;
00224 }
00225 
00226 
00227 
00228 void
00229 OGLDrawer::setBrushAttribute
00230 (
00231 IN eBrushAttribute attrib,
00232 IN const char * value
00233 )
00234 {
00235 //      DPRINTF("setBrushAttribute(%d) = '%s'", attrib, value);
00236 
00237         if (eBrush_PenColor == attrib) {
00238                 glut_color_t color;
00239                 getOpenGLColorFromString(value, color);
00240                 glColor4f(color.red, color.green, color.blue, color.alpha);
00241         } else if (eBrush_PenThickness == attrib) {
00242                 const float pixelsPerCM = 25.0; // using this for now!
00243                 float cmWidth = atof(value);
00244                 if (cmWidth <= 0) {
00245                         DPRINTF("Bad pen width: %f", cmWidth);
00246                         DPRINTF("From value: '%s'", value);
00247                         return;
00248                 }
00249                 float pixWidth = pixelsPerCM * cmWidth;
00250 //              DPRINTF("Setting raster line width: %f", pixWidth);
00251                 glLineWidth(pixWidth);
00252         } else {
00253                 DPRINTF("Unknown attribute %d = '%s'", attrib, value);
00254         }
00255 }
00256 
00257 
00258 
00259 void
00260 OGLDrawer::setClipRect
00261 (
00262 IN float left,
00263 IN float top,
00264 IN float right,
00265 IN float bottom
00266 )
00267 {
00268         DPRINTF("setClipRect() NYI");
00269 }
00270 
00271 
00272 
00273 void
00274 OGLDrawer::drawBezier
00275 (
00276 IN const bezier::curve_t& curve
00277 )
00278 {
00279         DPRINTF("drawBezier NYI");
00280 }
00281 
00282 
00283 
00284 void
00285 OGLDrawer::drawQuadBezier
00286 (
00287 IN const bezier::quad_bezier_t& quad
00288 )
00289 {
00290         // dumb bezier drawing!  Draw as an n-element bezier!
00291         const int N = 1;
00292         const float dt = 1.0 / N;
00293         float t = 0;
00294         glBegin(GL_LINE_STRIP);
00295         for (int i = 0; i < N + 1; ++i, t += dt) {
00296                 point_t p = quad.getPointAt(t);
00297 //              DPRINTF("  pt[%f] = (%f, %f)", t, p.x, p.y);
00298                 point_t q = m_T * p;
00299                 glVertex2f(q.x, q.y);
00300         }
00301         glEnd();
00302 }
00303 
00304 
00305 
00306 void
00307 OGLDrawer::drawLine
00308 (
00309 IN const point_t& p0,
00310 IN const point_t& p1
00311 )
00312 {
00313         point_t q0, q1;
00314 
00315         // transform points
00316         q0 = m_T * p0;
00317         q1 = m_T * p1;
00318 
00319         // draw
00320 //      DPRINTF("Drawing line: (%f, %f) - (%f, %f)", q0.x, q0.y, q1.x, q1.y);
00321 
00322         glBegin(GL_LINES);
00323                 glVertex2f(q0.x, q0.y);
00324                 glVertex2f(q1.x, q1.y);
00325         glEnd();
00326 }
00327 
00328 
00329 
00330 void
00331 OGLDrawer::drawRect
00332 (
00333 IN const rect_t& r
00334 )
00335 {
00336         DPRINTF("drawRect NYI");
00337 }
00338 
00339 
00340 
00341 void
00342 OGLDrawer::fillRect
00343 (
00344 IN const rect_t& r
00345 )
00346 {
00347         DPRINTF("fillRect NYI");
00348 }
00349 
00350 
00351 
00352 void
00353 OGLDrawer::drawText
00354 (
00355 IN const rect_t& r,
00356 IN const char * text
00357 )
00358 {
00359         DPRINTF("drawText('%s') NYI", text);
00360 }
00361 
00362 
00363 
00364 void
00365 OGLDrawer::getBoundingRect
00366 (
00367 IN const char * text,
00368 OUT rect_t& r
00369 )
00370 {
00371         DPRINTF("getBoundingRect('%s') NYI", text);
00372 }
00373 
00374 
00375 
00376 void
00377 OGLDrawer::getRootTransform
00378 (
00379 OUT xform_2d_t& T
00380 )
00381 throw()
00382 {
00383         DPRINTF("getRootTransform() NYI");
00384 }
00385 
00386 
00387 
00388 bool
00389 OGLDrawer::isPrinter
00390 (
00391 void
00392 )
00393 const
00394 throw()
00395 {
00396         return false;
00397 }
00398 
00399 
00400 
00401 ////////////////////////////////////////////////////////////////////////////////
00402 //
00403 //      OGLDrawer -- private helper methods
00404 //
00405 ////////////////////////////////////////////////////////////////////////////////
00406 
00407 ////////////////////////////////////////////////////////////////////////////////
00408 //
00409 //      public API
00410 //
00411 ////////////////////////////////////////////////////////////////////////////////
00412 
00413 smart_ptr<Drawer>
00414 createOpenGLDrawer
00415 (
00416 void
00417 )
00418 {
00419         smart_ptr<OGLDrawer> local = new OGLDrawer;
00420         ASSERT(local, "out of memory");
00421 
00422         local->initialize();
00423 
00424         return local;
00425 }
00426 
00427 
00428 
00429 };      // vgfx namespace
00430