include/cinder/svg/SvgGl.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2012, The Cinder Project
00003  All rights reserved.
00004  
00005  This code is designed for use with the Cinder C++ library, http://libcinder.org
00006 
00007  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00008  the following conditions are met:
00009 
00010     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00011     the following disclaimer.
00012     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00013     the following disclaimer in the documentation and/or other materials provided with the distribution.
00014 
00015  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00016  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00017  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00018  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00019  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00020  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00021  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00022  POSSIBILITY OF SUCH DAMAGE.
00023 */
00024 
00025 
00026 #pragma once
00027 
00028 #include "cinder/gl/gl.h"
00029 #include "cinder/gl/Texture.h"
00030 #include "cinder/svg/Svg.h"
00031 #include "cinder/Triangulate.h"
00032 
00033 namespace cinder {
00034 
00035 class SvgRendererGl : public svg::Renderer {
00036   public:
00037     SvgRendererGl() : svg::Renderer() { 
00038         mFillStack.push_back( svg::Paint( Color::black() ) );
00039         mStrokeStack.push_back( svg::Paint() );
00040         mFillOpacityStack.push_back( 1.0f );
00041         mStrokeOpacityStack.push_back( 1.0f );
00042         mStrokeWidthStack.push_back( 1.0f );
00043         glLineWidth( 1.0f );
00044         glMatrixMode( GL_MODELVIEW );
00045         glPushMatrix();
00046         mFillRuleStack.push_back( svg::FILL_RULE_NONZERO );
00047     }
00048     
00049     ~SvgRendererGl() {
00050         glPopMatrix();
00051     }
00052   
00053     void    pushGroup( const svg::Group &group, float opacity ) {}
00054     
00055     void    drawPath( const svg::Path &path ) {
00056         if( ! mFillStack.back().isNone() ) {
00057             gl::color( getCurFillColor() );
00058             Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD;
00059             gl::draw( Triangulator( path.getShape2d() ).calcMesh( winding ) );
00060         }
00061         if( ! mStrokeStack.back().isNone() ) {
00062             gl::color( getCurStrokeColor() );
00063             gl::draw( path.getShape2d() );
00064         }
00065     }
00066 
00067     void    drawPolygon( const svg::Polygon &polygon ) {
00068         if( ! mFillStack.back().isNone() ) {
00069             gl::color( getCurFillColor() );
00070             Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD;
00071             gl::draw( Triangulator( polygon.getPolyLine() ).calcMesh( winding ) );
00072 
00073         }
00074         if( ! mStrokeStack.back().isNone() ) {
00075             gl::color( getCurStrokeColor() );
00076             gl::draw( polygon.getPolyLine() );
00077         }
00078     }
00079 
00080     void    drawPolyline( const svg::Polyline &polyline ) {
00081         if( ! mFillStack.back().isNone() ) {
00082             gl::color( getCurFillColor() );
00083             Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD;
00084             gl::draw( Triangulator( polyline.getPolyLine() ).calcMesh( winding ) );
00085 
00086         }
00087         if( ! mStrokeStack.back().isNone() ) {
00088             gl::color( getCurStrokeColor() );
00089             gl::draw( polyline.getPolyLine() );
00090         }
00091     }
00092 
00093     void    drawLine( const svg::Line &line ) {
00094         if( ! mStrokeStack.back().isNone() ) {
00095             gl::color( getCurStrokeColor() );
00096             gl::drawLine( line.getPoint1(), line.getPoint2() );
00097         }
00098     }
00099 
00100     void    drawRect( const svg::Rect &rect ) {
00101         if( ! mFillStack.back().isNone() ) {
00102             gl::color( getCurFillColor() );
00103             gl::drawSolidRect( rect.getRect() );
00104         }
00105         if( ! mStrokeStack.back().isNone() ) {
00106             gl::color( getCurStrokeColor() );
00107             gl::drawStrokedRect( rect.getRect() );
00108         }
00109     }
00110 
00111     void    drawCircle( const svg::Circle &circle ) {
00112         if( ! mFillStack.back().isNone() ) {
00113             gl::color( getCurFillColor() );
00114             gl::drawSolidCircle( circle.getCenter(), circle.getRadius() );
00115         }
00116         if( ! mStrokeStack.back().isNone() ) {
00117             gl::color( getCurStrokeColor() );
00118             gl::drawStrokedCircle( circle.getCenter(), circle.getRadius() );
00119         }
00120     }
00121 
00122     void    drawEllipse( const svg::Ellipse &ellipse ) {
00123         if( ! mFillStack.back().isNone() ) {
00124             gl::color( getCurFillColor() );
00125             gl::drawSolidEllipse( ellipse.getCenter(), ellipse.getRadiusX(), ellipse.getRadiusY() );
00126         }
00127         if( ! mStrokeStack.back().isNone() ) {
00128             gl::color( getCurStrokeColor() );
00129             gl::drawStrokedEllipse( ellipse.getCenter(), ellipse.getRadiusX(), ellipse.getRadiusY() );
00130         }
00131     }   
00132     
00133     void    drawImage( const Surface8u &surface, const Rectf &drawRect ) {
00134         gl::color( Color::white() );
00135         gl::draw( gl::Texture( surface ), drawRect );
00136     }
00137 
00138     void    drawTextSpan( const svg::TextSpan &span ) {
00139     
00140     }
00141 
00142     void    popGroup() {}
00143 
00144     void    pushMatrix( const MatrixAffine2f &m ) {
00145         glPushMatrix();
00146         glMultMatrixf( Matrix44f( m ) );
00147     }
00148     void    popMatrix() {
00149         glPopMatrix();
00150     }
00151     
00152     void    pushFill( const svg::Paint &paint ) { mFillStack.push_back( paint ); }
00153     void    popFill() { mFillStack.pop_back(); }
00154     void    pushStroke( const svg::Paint &paint ) { mStrokeStack.push_back( paint ); }
00155     void    popStroke() { mStrokeStack.pop_back(); }
00156     void    pushFillOpacity( float opacity ) { mFillOpacityStack.push_back( opacity ); }
00157     void    popFillOpacity() { mFillOpacityStack.pop_back(); }
00158     void    pushStrokeOpacity( float opacity ) { mStrokeOpacityStack.push_back( opacity ); }
00159     void    popStrokeOpacity() { mStrokeOpacityStack.pop_back(); }
00160 
00161     ColorA  getCurFillColor() { ColorA result( mFillStack.back().getColor() ); result.a = mFillOpacityStack.back(); return result; }
00162     ColorA  getCurStrokeColor() { ColorA result( mStrokeStack.back().getColor() ); result.a = mStrokeOpacityStack.back(); return result; }
00163 
00164 
00165     void    pushStrokeWidth( float width ) { mStrokeWidthStack.push_back( width ); glLineWidth( width ); }
00166     void    popStrokeWidth() { mStrokeWidthStack.pop_back(); glLineWidth( mStrokeWidthStack.back() ); }
00167     void    pushFillRule( svg::FillRule rule ) { mFillRuleStack.push_back( rule ); }
00168     void    popFillRule() { mFillRuleStack.pop_back(); }    
00169 
00170 
00171     std::vector<svg::Paint>     mFillStack, mStrokeStack;
00172     std::vector<float>          mFillOpacityStack, mStrokeOpacityStack;
00173     std::vector<float>          mStrokeWidthStack;
00174     std::vector<svg::FillRule>  mFillRuleStack;
00175 };
00176 
00177 namespace gl {
00178 inline void draw( const svg::Doc &svg )
00179 {
00180     SvgRendererGl renderGl;
00181     svg.render( renderGl );
00182 }
00183 } // namespace gl
00184 
00185 } // namespace cinder