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/svg/Svg.h" 00030 #include "cinder/Triangulate.h" 00031 00032 namespace cinder { 00033 00034 class SvgRendererGl : public svg::Renderer { 00035 public: 00036 SvgRendererGl() : svg::Renderer() { 00037 mFillStack.push_back( svg::Paint( Color::black() ) ); 00038 mStrokeStack.push_back( svg::Paint() ); 00039 mFillOpacityStack.push_back( 1.0f ); 00040 mStrokeOpacityStack.push_back( 1.0f ); 00041 mStrokeWidthStack.push_back( 1.0f ); 00042 glLineWidth( 1.0f ); 00043 glMatrixMode( GL_MODELVIEW ); 00044 glPushMatrix(); 00045 mFillRuleStack.push_back( svg::FILL_RULE_NONZERO ); 00046 } 00047 00048 ~SvgRendererGl() { 00049 glPopMatrix(); 00050 } 00051 00052 void pushGroup( const svg::Group &group, float opacity ) {} 00053 00054 void drawPath( const svg::Path &path ) { 00055 if( ! mFillStack.back().isNone() ) { 00056 gl::color( getCurFillColor() ); 00057 Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD; 00058 gl::draw( Triangulator( path.getShape2d() ).calcMesh( winding ) ); 00059 } 00060 if( ! mStrokeStack.back().isNone() ) { 00061 gl::color( getCurStrokeColor() ); 00062 gl::draw( path.getShape2d() ); 00063 } 00064 } 00065 00066 void drawPolygon( const svg::Polygon &polygon ) { 00067 if( ! mFillStack.back().isNone() ) { 00068 gl::color( getCurFillColor() ); 00069 Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD; 00070 gl::draw( Triangulator( polygon.getPolyLine() ).calcMesh( winding ) ); 00071 00072 } 00073 if( ! mStrokeStack.back().isNone() ) { 00074 gl::color( getCurStrokeColor() ); 00075 gl::draw( polygon.getPolyLine() ); 00076 } 00077 } 00078 00079 void drawPolyline( const svg::Polyline &polyline ) { 00080 if( ! mFillStack.back().isNone() ) { 00081 gl::color( getCurFillColor() ); 00082 Triangulator::Winding winding = ( mFillRuleStack.back() == svg::FILL_RULE_NONZERO ) ? Triangulator::WINDING_NONZERO : Triangulator::WINDING_ODD; 00083 gl::draw( Triangulator( polyline.getPolyLine() ).calcMesh( winding ) ); 00084 00085 } 00086 if( ! mStrokeStack.back().isNone() ) { 00087 gl::color( getCurStrokeColor() ); 00088 gl::draw( polyline.getPolyLine() ); 00089 } 00090 } 00091 00092 void drawLine( const svg::Line &line ) { 00093 if( ! mStrokeStack.back().isNone() ) { 00094 gl::color( getCurStrokeColor() ); 00095 gl::drawLine( line.getPoint1(), line.getPoint2() ); 00096 } 00097 } 00098 00099 void drawRect( const svg::Rect &rect ) { 00100 if( ! mFillStack.back().isNone() ) { 00101 gl::color( getCurFillColor() ); 00102 gl::drawSolidRect( rect.getRect() ); 00103 } 00104 if( ! mStrokeStack.back().isNone() ) { 00105 gl::color( getCurStrokeColor() ); 00106 gl::drawStrokedRect( rect.getRect() ); 00107 } 00108 } 00109 00110 void drawCircle( const svg::Circle &circle ) { 00111 if( ! mFillStack.back().isNone() ) { 00112 gl::color( getCurFillColor() ); 00113 gl::drawSolidCircle( circle.getCenter(), circle.getRadius() ); 00114 } 00115 if( ! mStrokeStack.back().isNone() ) { 00116 gl::color( getCurStrokeColor() ); 00117 gl::drawStrokedCircle( circle.getCenter(), circle.getRadius() ); 00118 } 00119 } 00120 00121 void drawEllipse( const svg::Ellipse &ellipse ) { 00122 if( ! mFillStack.back().isNone() ) { 00123 gl::color( getCurFillColor() ); 00124 gl::drawSolidEllipse( ellipse.getCenter(), ellipse.getRadiusX(), ellipse.getRadiusY() ); 00125 } 00126 if( ! mStrokeStack.back().isNone() ) { 00127 gl::color( getCurStrokeColor() ); 00128 gl::drawStrokedEllipse( ellipse.getCenter(), ellipse.getRadiusX(), ellipse.getRadiusY() ); 00129 } 00130 } 00131 00132 void drawImage( const Surface8u &surface, const Rectf &drawRect ) { 00133 gl::color( Color::white() ); 00134 gl::draw( gl::Texture( surface ), drawRect ); 00135 } 00136 00137 void drawTextSpan( const svg::TextSpan &span ) { 00138 00139 } 00140 00141 void popGroup() {} 00142 00143 void pushMatrix( const MatrixAffine2f &m ) { 00144 glPushMatrix(); 00145 glMultMatrixf( Matrix44f( m ) ); 00146 } 00147 void popMatrix() { 00148 glPopMatrix(); 00149 } 00150 00151 void pushFill( const svg::Paint &paint ) { mFillStack.push_back( paint ); } 00152 void popFill() { mFillStack.pop_back(); } 00153 void pushStroke( const svg::Paint &paint ) { mStrokeStack.push_back( paint ); } 00154 void popStroke() { mStrokeStack.pop_back(); } 00155 void pushFillOpacity( float opacity ) { mFillOpacityStack.push_back( opacity ); } 00156 void popFillOpacity() { mFillOpacityStack.pop_back(); } 00157 void pushStrokeOpacity( float opacity ) { mStrokeOpacityStack.push_back( opacity ); } 00158 void popStrokeOpacity() { mStrokeOpacityStack.pop_back(); } 00159 00160 ColorA getCurFillColor() { ColorA result( mFillStack.back().getColor() ); result.a = mFillOpacityStack.back(); return result; } 00161 ColorA getCurStrokeColor() { ColorA result( mStrokeStack.back().getColor() ); result.a = mStrokeOpacityStack.back(); return result; } 00162 00163 00164 void pushStrokeWidth( float width ) { mStrokeWidthStack.push_back( width ); glLineWidth( width ); } 00165 void popStrokeWidth() { mStrokeWidthStack.pop_back(); glLineWidth( mStrokeWidthStack.back() ); } 00166 void pushFillRule( svg::FillRule rule ) { mFillRuleStack.push_back( rule ); } 00167 void popFillRule() { mFillRuleStack.pop_back(); } 00168 00169 00170 std::vector<svg::Paint> mFillStack, mStrokeStack; 00171 std::vector<float> mFillOpacityStack, mStrokeOpacityStack; 00172 std::vector<float> mStrokeWidthStack; 00173 std::vector<svg::FillRule> mFillRuleStack; 00174 }; 00175 00176 namespace gl { 00177 inline void draw( const svg::Doc &svg ) 00178 { 00179 SvgRendererGl renderGl; 00180 svg.render( renderGl ); 00181 } 00182 } // namespace gl 00183 00184 } // namespace cinder