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 #pragma once 00026 00027 #include "cinder/Cinder.h" 00028 #include "cinder/Xml.h" 00029 #include "cinder/Vector.h" 00030 #include "cinder/Color.h" 00031 #include "cinder/Shape2d.h" 00032 #include "cinder/PolyLine.h" 00033 #include "cinder/Exception.h" 00034 #include "cinder/MatrixAffine2.h" 00035 #include "cinder/Surface.h" 00036 #include "cinder/Font.h" 00037 #include "cinder/Function.h" 00038 00039 #include <map> 00040 00041 namespace cinder { namespace svg { 00042 00043 typedef enum { FILL_RULE_NONZERO, FILL_RULE_EVENODD } FillRule; 00044 typedef enum { LINE_CAP_BUTT, LINE_CAP_ROUND, LINE_CAP_SQUARE } LineCap; 00045 typedef enum { LINE_JOIN_MITER, LINE_JOIN_ROUND, LINE_JOIN_BEVEL } LineJoin; 00046 typedef enum { WEIGHT_100, WEIGHT_200, WEIGHT_300, WEIGHT_400, WEIGHT_NORMAL = WEIGHT_400, WEIGHT_500, WEIGHT_600, WEIGHT_700, WEIGHT_BOLD = WEIGHT_700, WEIGHT_800, WEIGHT_900 } FontWeight; 00047 00048 class Node; 00049 class Group; 00050 class Rect; 00051 class Circle; 00052 class Path; 00053 class TextSpan; 00054 class Style; 00055 class Line; 00056 class Ellipse; 00057 class Polyline; 00058 class Polygon; 00059 class Image; 00060 class ExcChildNotFound; 00061 00062 typedef std::function<bool(const Node&, svg::Style *)> RenderVisitor; 00063 00065 class Renderer { 00066 public: 00067 Renderer() {} 00068 00069 virtual ~Renderer() {} 00070 00071 void setVisitor( const RenderVisitor &visitor ) { mVisitor = visitor; } 00072 00073 virtual void pushGroup( const Group &group, float opacity ) {} 00074 virtual void popGroup() {} 00075 virtual void drawPath( const svg::Path &path ) {} 00076 virtual void drawPolyline( const svg::Polyline &polyline ) {} 00077 virtual void drawPolygon( const svg::Polygon &polygon ) {} 00078 virtual void drawLine( const svg::Line &line ) {} 00079 virtual void drawRect( const svg::Rect &rect ) {} 00080 virtual void drawCircle( const svg::Circle &circle ) {} 00081 virtual void drawEllipse( const svg::Ellipse &ellipse ) {} 00082 virtual void drawImage( const svg::Image &image ) {} 00083 virtual void drawTextSpan( const svg::TextSpan &span ) {} 00084 00085 virtual void pushMatrix( const MatrixAffine2f &m ) {} 00086 virtual void popMatrix() {} 00087 virtual void pushStyle( const svg::Style &style ) {} 00088 virtual void popStyle( const svg::Style &style ) {} 00089 virtual void pushFill( const class Paint &paint ) {} 00090 virtual void popFill() {} 00091 virtual void pushStroke( const class Paint &paint ) {} 00092 virtual void popStroke() {} 00093 virtual void pushFillOpacity( float opacity ) {} 00094 virtual void popFillOpacity() {} 00095 virtual void pushStrokeOpacity( float opacity ) {} 00096 virtual void popStrokeOpacity() {} 00097 virtual void pushStrokeWidth( float width ) {} 00098 virtual void popStrokeWidth() {} 00099 virtual void pushFillRule( FillRule rule ) {} 00100 virtual void popFillRule() {} 00101 virtual void pushLineCap( LineCap lineCap ) {} 00102 virtual void popLineCap() {} 00103 virtual void pushLineJoin( LineJoin lineJoin ) {} 00104 virtual void popLineJoin() {} 00105 virtual void pushTextPen( const Vec2f &penPos ) {} 00106 virtual void popTextPen() {} 00107 virtual void pushTextRotation( float rotation ) {} 00108 virtual void popTextRotation() {} 00109 00110 bool visit( const Node &node, svg::Style *style ) const { 00111 if( mVisitor ) 00112 return mVisitor( node, style ); 00113 else 00114 return true; 00115 } 00116 00117 protected: 00118 RenderVisitor mVisitor; 00119 00120 friend class svg::Node; 00121 }; 00122 00124 class Value { 00125 public: 00126 enum Unit { USER, PX, PERCENT, PT, PC, MM, CM, INCH, EM, EX }; 00127 00128 Value() : mValue( 0 ), mUnit( USER ) {} 00129 Value( float value, Unit unit = USER ) : mValue( value ), mUnit( unit ) {} 00130 00131 float asUser( float percentOf = 100, float dpi = 72, float fontSize = 12, float fontXHeight = 7 ) const; 00132 00133 bool isUser() const { return mUnit == USER; } 00134 bool isPercent() const { return mUnit == PERCENT; } 00135 bool isPixels() const { return mUnit == PX; } 00136 00137 static Value parse( const char **sInOut ); 00138 static Value parse( const std::string &s ); 00139 00140 Unit mUnit; 00141 float mValue; 00142 }; 00143 00145 class Paint { 00146 public: 00147 enum { NONE, COLOR, LINEAR_GRADIENT, RADIAL_GRADIENT }; 00148 00149 Paint(); 00150 Paint( uint8_t type ); 00151 Paint( const ColorA8u &color ); 00152 00153 static Paint parse( const char *value, bool *specified, const Node *parentNode ); 00154 00155 bool isNone() const { return mType == NONE; } 00156 bool isLinearGradient() const { return mType == LINEAR_GRADIENT; } 00157 bool isRadialGradient() const { return mType == RADIAL_GRADIENT; } 00158 const ColorA8u& getColor( size_t idx = 0 ) const { return mStops[idx].second; } 00159 float getOffset( size_t idx ) const { return mStops[idx].first; } 00160 size_t getNumColors() const { return mStops.size(); } 00161 00162 // only apply to gradients 00163 Vec2f getCoords0() const { return mCoords0; } // (x1,y1) on linear, (cx,cy) on radial 00164 Vec2f getCoords1() const { return mCoords1; } // (x2,y2) on linear, (fx,fy) on radial 00165 float getRadius() const { return mRadius; } // radial-only 00166 bool useObjectBoundingBox() const { return mUseObjectBoundingBox; } 00167 bool specifiesTransform() const { return mSpecifiesTransform; } 00168 MatrixAffine2f getTransform() const { return mTransform; } 00169 00170 uint8_t mType; 00171 std::vector<std::pair<float,ColorA8u> > mStops; 00172 00173 Vec2f mCoords0, mCoords1; 00174 float mRadius; 00175 bool mUseObjectBoundingBox; 00176 MatrixAffine2f mTransform; 00177 bool mSpecifiesTransform; 00178 }; 00179 00181 class Style { 00182 public: 00183 Style(); 00184 Style( const XmlTree &xml, const Node *parent ); 00185 00187 static Style makeGlobalDefaults(); 00189 void clear(); 00190 00191 bool specifiesFill() const { return mSpecifiesFill; } 00192 void unspecifyFill() { mSpecifiesFill = false; } 00193 const Paint& getFill() const { return mFill; } 00194 void setFill( const Paint &fill ) { mSpecifiesFill = true; mFill = fill; } 00195 static const Paint& getFillDefault() { return sPaintBlack; } 00196 00197 bool specifiesStroke() const { return mSpecifiesStroke; } 00198 void unspecifyStroke() { mSpecifiesStroke = false; } 00199 const Paint& getStroke() const { return mStroke; } 00200 void setStroke( const Paint &stroke ) { mSpecifiesStroke = true; mStroke = stroke; } 00201 static const Paint& getStrokeDefault() { return sPaintNone; } 00202 00203 bool specifiesOpacity() const { return mSpecifiesOpacity; } 00204 void unspecifyOpacity() { mSpecifiesOpacity = false; } 00205 float getOpacity() const { return mOpacity; } 00206 void setOpacity( float opacity ) { mSpecifiesOpacity = true; mOpacity = opacity; } 00207 static float getOpacityDefault() { return 1.0f; } 00208 00209 bool specifiesStrokeOpacity() const { return mSpecifiesStrokeOpacity; } 00210 void unspecifyStrokeOpacity() { mSpecifiesStrokeOpacity = false; } 00211 float getStrokeOpacity() const { return mStrokeOpacity; } 00212 void setStrokeOpacity( float strokeOpacity ) { mSpecifiesStrokeOpacity = true; mStrokeOpacity = strokeOpacity; } 00213 static float getStrokeOpacityDefault() { return 1.0f; } 00214 00215 bool specifiesFillOpacity() const { return mSpecifiesFillOpacity; } 00216 void unspecifyFillOpacity() { mSpecifiesFillOpacity = false; } 00217 float getFillOpacity() const { return mFillOpacity; } 00218 void setFillOpacity( float fillOpacity ) { mSpecifiesFillOpacity = true; mFillOpacity = fillOpacity; } 00219 static float getFillOpacityDefault() { return 1.0f; } 00220 00221 bool specifiesStrokeWidth() const { return mSpecifiesStrokeWidth; } 00222 void unspecifyStrokeWidth() { mSpecifiesStrokeWidth = false; } 00223 float getStrokeWidth() const { return mStrokeWidth; } 00224 void setStrokeWidth( float strokeWidth ) { mSpecifiesStrokeWidth = true; mStrokeWidth = strokeWidth; } 00225 static float getStrokeWidthDefault() { return 1.0f; } 00226 00227 bool specifiesFillRule() const { return mSpecifiesFillRule; } 00228 void unspecifyFillRule() { mSpecifiesFillRule = false; } 00229 FillRule getFillRule() const { return mFillRule; } 00230 void setFillRule( FillRule fillRule ) { mSpecifiesFillRule = true; mFillRule = fillRule; } 00231 static FillRule getFillRuleDefault() { return svg::FILL_RULE_NONZERO; } 00232 00233 bool specifiesLineCap() const { return mSpecifiesLineCap; } 00234 void unspecifyLineCap() { mSpecifiesLineCap = false; } 00235 LineCap getLineCap() const { return mLineCap; } 00236 void setLineCap( LineCap lineCap ) { mSpecifiesLineCap = true; mLineCap = lineCap; } 00237 static LineCap getLineCapDefault() { return svg::LINE_CAP_BUTT; } 00238 00239 bool specifiesLineJoin() const { return mSpecifiesLineJoin; } 00240 void unspecifyLineJoin() { mSpecifiesLineJoin = false; } 00241 LineJoin getLineJoin() const { return mLineJoin; } 00242 void setLineJoin( LineJoin lineJoin ) { mSpecifiesLineJoin = true; mLineJoin = lineJoin; } 00243 static LineJoin getLineJoinDefault() { return svg::LINE_JOIN_MITER; } 00244 00245 // fonts 00246 bool specifiesFontFamilies() const { return mSpecifiesFontFamilies; } 00247 void unspecifyFontFamilies() { mSpecifiesFontFamilies = false; } 00248 const std::vector<std::string>& getFontFamilies() const { return mFontFamilies; } 00249 std::vector<std::string>& getFontFamilies() { return mFontFamilies; } 00250 void setFontFamily( const std::string &family ) { mSpecifiesFontFamilies = true; mFontFamilies.clear(); mFontFamilies.push_back( family ); } 00251 void setFontFamilies( const std::vector<std::string> &families ) { mSpecifiesFontFamilies = true; mFontFamilies = families; } 00252 static const std::vector<std::string>& getFontFamiliesDefault(); 00253 00254 bool specifiesFontSize() const { return mSpecifiesFontSize; } 00255 void unspecifyFontSize() { mSpecifiesFontSize = false; } 00256 Value getFontSize() const { return mFontSize; } 00257 void setFontSize( const Value &fontSize ) { mSpecifiesFontSize = true; mFontSize = fontSize; } 00258 static Value getFontSizeDefault() { return Value( 12 ); } 00259 00260 bool specifiesFontWeight() const { return mSpecifiesFontWeight; } 00261 void unspecifyFontWeight() { mSpecifiesFontWeight = false; } 00262 FontWeight getFontWeight() const { return mFontWeight; } 00263 void setFontWeight( FontWeight weight ) { mSpecifiesFontWeight = true; mFontWeight = weight; } 00264 static FontWeight getFontWeightDefault() { return svg::WEIGHT_NORMAL; } 00265 00266 bool specifiesVisible() const { return mSpecifiesVisible; } 00267 bool isVisible() const { return mVisible; } 00268 void setVisible( bool visible ) { mSpecifiesVisible = true; mVisible = visible; } 00269 void unspecifyVisible() { mSpecifiesVisible = false; } 00270 00271 bool isDisplayNone() const { return mDisplayNone; } 00272 void setDisplayNone( bool displayNone ) { mDisplayNone = displayNone; } 00273 00274 void startRender( Renderer &renderer, bool isNodeDrawable ) const; 00275 void finishRender( Renderer &renderer, bool isNodeDrawable ) const; 00276 00277 void parseStyleAttribute( const std::string &stylePropertyString, const Node *parent ); 00278 bool parseProperty( const std::string &key, const std::string &value, const Node *parent ); 00279 00280 protected: 00281 bool mSpecifiesOpacity; 00282 float mOpacity; 00283 bool mSpecifiesFillOpacity, mSpecifiesStrokeOpacity; 00284 float mFillOpacity, mStrokeOpacity; 00285 00286 bool mSpecifiesFill, mSpecifiesStroke; 00287 Paint mFill, mStroke; 00288 bool mSpecifiesStrokeWidth; 00289 float mStrokeWidth; 00290 bool mSpecifiesFillRule; 00291 FillRule mFillRule; 00292 bool mSpecifiesLineCap; 00293 LineCap mLineCap; 00294 bool mSpecifiesLineJoin; 00295 LineJoin mLineJoin; 00296 00297 // fonts 00298 bool mSpecifiesFontFamilies, mSpecifiesFontSize, mSpecifiesFontWeight; 00299 std::vector<std::string> mFontFamilies; 00300 Value mFontSize; 00301 FontWeight mFontWeight; 00302 00303 // visibility 00304 bool mSpecifiesVisible, mVisible, mDisplayNone; 00305 00306 private: 00307 static Paint sPaintNone, sPaintBlack; 00308 }; 00309 00311 class Node { 00312 public: 00313 Node( const Node *parent ) : mParent( parent ), mSpecifiesTransform( false ), mBoundingBoxCached( false ) {} 00314 virtual ~Node() {} 00315 00317 class Doc* getDoc() const; 00319 const Node* getParent() const { return mParent; } 00321 const std::string& getId() const { return mId; } 00323 std::string getDomPath() const; 00325 const Style& getStyle() const { return mStyle; } 00327 void setStyle( const Style &style ) { mStyle = style; } 00329 Style calcInheritedStyle() const; 00330 00332 virtual bool containsPoint( const Vec2f &pt ) const { return false; } 00333 00335 void render( Renderer &renderer ) const; 00336 00338 virtual const Node* findInAncestors( const std::string &elementId ) const; 00340 Paint findPaintInAncestors( const std::string &paintName ) const; 00341 00343 bool specifiesTransform() const { return mSpecifiesTransform; } 00345 MatrixAffine2f getTransform() const { return mTransform; } 00347 void setTransform( const MatrixAffine2f &transform ) { mTransform = transform; mSpecifiesTransform = true; } 00349 void unspecifyTransform() { mSpecifiesTransform = false; } 00351 MatrixAffine2f getTransformInverse() const { return ( mSpecifiesTransform ) ? mTransform.invertCopy() : MatrixAffine2f::identity(); } 00353 MatrixAffine2f getTransformAbsolute() const; 00355 MatrixAffine2f getTransformAbsoluteInverse() const { return getTransformAbsolute().invertCopy(); } 00356 00358 Rectf getBoundingBox() const { if( ! mBoundingBoxCached ) { mBoundingBox = calcBoundingBox(); mBoundingBoxCached = true; } return mBoundingBox; } 00360 Rectf getBoundingBoxAbsolute() const { return getBoundingBox().transformCopy( getTransformAbsolute() ); } 00361 00363 virtual Shape2d getShape() const { return Shape2d(); } 00365 Shape2d getShapeAbsolute() const { return getShape().transformCopy( getTransformAbsolute() ); } 00366 00368 const Paint& getFill() const; 00370 const Paint& getStroke() const; 00372 float getOpacity() const; 00374 float getFillOpacity() const; 00376 float getStrokeOpacity() const; 00378 FillRule getFillRule() const; 00380 LineCap getLineCap() const; 00382 LineJoin getLineJoin() const; 00384 float getStrokeWidth() const; 00386 const std::vector<std::string>& getFontFamilies() const; 00388 Value getFontSize() const; 00390 bool isVisible() const; 00392 bool isDisplayNone() const { return mStyle.isDisplayNone(); } 00393 00394 00395 protected: 00396 Node( const Node *parent, const XmlTree &xml ); 00397 // returns whether this type of node directly renders anything. Everything but groups. 00398 virtual bool isDrawable() const { return true; } 00399 00400 void startRender( Renderer &renderer, const Style &style ) const; 00401 void finishRender( Renderer &renderer, const Style &style ) const; 00402 virtual void renderSelf( Renderer &renderer ) const = 0; 00403 00404 virtual Rectf calcBoundingBox() const { return Rectf( 0, 0, 0, 0 ); } 00405 00406 static Paint parsePaint( const char *value, bool *specified, const Node *parentNode ); 00407 static MatrixAffine2f parseTransform( const std::string &value ); 00408 static bool parseTransformComponent( const char **c, MatrixAffine2f *result ); 00409 00410 static std::string findStyleValue( const std::string &styleString, const std::string &key ); 00411 void parseStyle( const std::string &value ); 00412 00413 protected: 00414 const Node *mParent; 00415 std::string mId; 00416 Style mStyle; 00417 bool mSpecifiesTransform; 00418 MatrixAffine2f mTransform; 00419 mutable bool mBoundingBoxCached; 00420 mutable Rectf mBoundingBox; 00421 00422 private: 00423 void firstStartRender( Renderer &renderer ) const; 00424 00425 friend class Group; 00426 friend class Use; 00427 }; 00428 00430 class Gradient : public Node { 00431 public: 00432 Gradient( const Node *parent, const XmlTree &xml ); 00433 00434 class Stop { 00435 public: 00436 Stop( const Node *parent, const XmlTree &xml ); 00437 00438 float mOffset; // normalized 0-1 00439 ColorA8u mColor; 00440 float mOpacity; 00441 bool mSpecifiesColor, mSpecifiesOpacity; 00442 }; 00443 00444 bool useObjectBoundingBox() const { return mUseObjectBoundingBox; } 00445 bool specifiesTransform() const { return mSpecifiesTransform; } 00446 00447 protected: 00448 virtual void renderSelf( Renderer &renderer ) const {} 00449 00450 void parse( const Node *parent, const XmlTree &xml ); 00451 void copyAttributesFrom( const Gradient &rhs ); 00452 Paint asPaint() const; 00453 00454 std::vector<Stop> mStops; 00455 Vec2f mCoords0, mCoords1; 00456 bool mUseObjectBoundingBox; 00457 bool mSpecifiesTransform; 00458 MatrixAffine2f mTransform; 00459 }; 00460 00462 class LinearGradient : public Gradient { 00463 public: 00464 LinearGradient( const Node *parent, const XmlTree &xml ); 00465 00466 Paint asPaint() const; 00467 00468 protected: 00469 void parse( const XmlTree &xml ); 00470 00471 virtual bool isDrawable() const { return false; } 00472 }; 00473 00475 class RadialGradient : public Gradient { 00476 public: 00477 RadialGradient( const Node *parent, const XmlTree &xml ); 00478 00479 Paint asPaint() const; 00480 00481 protected: 00482 void parse( const XmlTree &xml ); 00483 00484 virtual bool isDrawable() const { return false; } 00485 float mRadius; 00486 }; 00487 00489 class Circle : public Node { 00490 public: 00491 Circle( const Node *parent ) : Node( parent ) {} 00492 Circle( const Node *parent, const XmlTree &xml ); 00493 00494 Vec2f getCenter() const { return mCenter; } 00495 float getRadius() const { return mRadius; } 00496 00497 virtual bool containsPoint( const Vec2f &pt ) const { return pt.distanceSquared( mCenter ) < mRadius * mRadius; } 00498 00499 virtual Shape2d getShape() const; 00500 00501 protected: 00502 virtual void renderSelf( Renderer &renderer ) const; 00503 virtual Rectf calcBoundingBox() const { return Rectf( mCenter.x - mRadius, mCenter.y - mRadius, mCenter.x + mRadius, mCenter.y + mRadius ); } 00504 00505 Vec2f mCenter; 00506 float mRadius; 00507 }; 00508 00510 class Ellipse : public Node { 00511 public: 00512 Ellipse( const Node *parent ) : Node( parent ) {} 00513 Ellipse( const Node *parent, const XmlTree &xml ); 00514 00515 Vec2f getCenter() const { return mCenter; } 00516 float getRadiusX() const { return mRadiusX; } 00517 float getRadiusY() const { return mRadiusY; } 00518 00519 bool containsPoint( const Vec2f &pt ) const; 00520 00521 virtual Shape2d getShape() const; 00522 00523 protected: 00524 virtual void renderSelf( Renderer &renderer ) const; 00525 virtual Rectf calcBoundingBox() const { return Rectf( mCenter.x - mRadiusX, mCenter.y - mRadiusY, mCenter.x + mRadiusX, mCenter.y + mRadiusY ); } 00526 00527 Vec2f mCenter; 00528 float mRadiusX, mRadiusY; 00529 }; 00530 00532 class Path : public Node { 00533 public: 00534 Path( const Node *parent ) : Node( parent ) {} 00535 Path( const Node *parent, const XmlTree &xml ); 00536 00537 const Shape2d& getShape2d() const { return mPath; } 00538 void appendShape2d( Shape2d *appendTo ) const; 00539 00540 virtual bool containsPoint( const Vec2f &pt ) const { return mPath.contains( pt ); } 00541 00542 virtual Shape2d getShape() const { return mPath; } 00543 00544 protected: 00545 virtual void renderSelf( Renderer &renderer ) const; 00546 virtual Rectf calcBoundingBox() const { return mPath.calcPreciseBoundingBox(); } 00547 00548 Shape2d mPath; 00549 }; 00550 00552 class Line : public Node { 00553 public: 00554 Line( const Node *parent ) : Node( parent ) {} 00555 Line( const Node *parent, const XmlTree &xml ); 00556 00557 const Vec2f& getPoint1() const { return mPoint1; } 00558 const Vec2f& getPoint2() const { return mPoint2; } 00559 00560 virtual Shape2d getShape() const; 00561 00562 protected: 00563 virtual void renderSelf( Renderer &renderer ) const; 00564 virtual Rectf calcBoundingBox() const { return Rectf( mPoint1, mPoint2 ); } 00565 00566 Vec2f mPoint1, mPoint2; 00567 }; 00568 00570 class Rect : public Node { 00571 public: 00572 Rect( const Node *parent ) : Node( parent ) {} 00573 Rect( const Node *parent, const XmlTree &xml ); 00574 00575 const Rectf& getRect() const { return mRect; } 00576 00577 virtual bool containsPoint( const Vec2f &pt ) const { return mRect.contains( pt ); } 00578 00579 virtual Shape2d getShape() const; 00580 00581 protected: 00582 virtual void renderSelf( Renderer &renderer ) const; 00583 virtual Rectf calcBoundingBox() const { return mRect; } 00584 00585 Rectf mRect; 00586 }; 00587 00589 class Polygon : public Node { 00590 public: 00591 Polygon( const Node *parent ) : Node( parent ) {} 00592 Polygon( const Node *parent, const XmlTree &xml ); 00593 00594 const PolyLine2f& getPolyLine() const { return mPolyLine; } 00595 PolyLine2f& getPolyLine() { return mPolyLine; } 00596 00597 virtual bool containsPoint( const Vec2f &pt ) const { return mPolyLine.contains( pt ); } 00598 00599 virtual Shape2d getShape() const; 00600 00601 protected: 00602 virtual void renderSelf( Renderer &renderer ) const; 00603 virtual Rectf calcBoundingBox() const { return Rectf( mPolyLine.getPoints() ); } 00604 00605 PolyLine2f mPolyLine; 00606 }; 00607 00609 class Polyline : public Node { 00610 public: 00611 Polyline( const Node *parent ) : Node( parent ) {} 00612 Polyline( const Node *parent, const XmlTree &xml ); 00613 00614 const PolyLine2f& getPolyLine() const { return mPolyLine; } 00615 PolyLine2f& getPolyLine() { return mPolyLine; } 00616 00617 virtual bool containsPoint( const Vec2f &pt ) const { return mPolyLine.contains( pt ); } 00618 00619 virtual Shape2d getShape() const; 00620 00621 protected: 00622 virtual void renderSelf( Renderer &renderer ) const; 00623 virtual Rectf calcBoundingBox() const { return Rectf( mPolyLine.getPoints() ); } 00624 00625 PolyLine2f mPolyLine; 00626 }; 00627 00629 class Use : public Node { 00630 public: 00631 Use( const Node *parent, const XmlTree &xml ); 00632 00633 virtual bool isDrawable() const { return false; } 00634 00635 virtual Shape2d getShape() const{ if( mReferenced ) return mReferenced->getShape(); else return Shape2d(); } 00636 00637 protected: 00638 virtual void renderSelf( Renderer &renderer ) const; 00639 virtual Rectf calcBoundingBox() const { if( mReferenced ) return mReferenced->getBoundingBox(); else return Rectf(0,0,0,0); } 00640 00641 void parse( const XmlTree &xml ); 00642 00643 const Node *mReferenced; 00644 }; 00645 00647 class Image : public Node { 00648 public: 00649 Image( const Node *parent, const XmlTree &xml ); 00650 00651 const Rectf& getRect() const { return mRect; } 00652 const std::shared_ptr<Surface8u> getSurface() const { return mImage; } 00653 00654 virtual bool containsPoint( const Vec2f &pt ) const { return mRect.contains( pt ); } 00655 00656 protected: 00657 virtual void renderSelf( Renderer &renderer ) const; 00658 virtual Rectf calcBoundingBox() const { return mRect; } 00659 00660 static std::shared_ptr<Surface8u> parseDataImage( const std::string &data ); 00661 00662 Rectf mRect; 00663 fs::path mFilePath; 00664 std::shared_ptr<Surface8u> mImage; 00665 }; 00666 00667 typedef std::shared_ptr<TextSpan> TextSpanRef; 00668 00670 class TextSpan : public Node { 00671 public: 00672 class Attributes { 00673 public: 00674 Attributes() {} 00675 Attributes( const XmlTree &xml ); 00676 00677 void startRender( Renderer &renderer ) const; 00678 void finishRender( Renderer &renderer ) const; 00679 00680 std::vector<Value> mX, mY; 00681 float mDx, mDy; 00682 std::vector<Value> mRotate; 00683 float mTextLength; 00684 float mLengthAdjust; 00685 }; 00686 00687 TextSpan( const Node *parent, const XmlTree &xml ); 00688 TextSpan( const Node *parent, const std::string &spanString ); 00689 00690 const std::string& getString() const { return mString; } 00691 const std::shared_ptr<Font> getFont() const; 00693 std::vector<std::pair<uint16_t,Vec2f> > getGlyphMeasures() const; 00694 Vec2f getTextPen() const; 00695 float getRotation() const; 00696 00697 protected: 00698 virtual void renderSelf( Renderer &renderer ) const; 00699 00700 bool mIgnoreAttributes; // TextSpans that are actually the contents of Text's attributes should be ignored 00701 Attributes mAttributes; 00702 std::string mString; 00703 mutable std::shared_ptr<Font> mFont; 00704 mutable std::shared_ptr<std::vector<std::pair<uint16_t,Vec2f> > > mGlyphMeasures; 00705 mutable std::shared_ptr<Shape2d> mShape; 00706 00707 std::vector<TextSpanRef> mSpans; 00708 00709 friend class Text; 00710 }; 00711 00713 class Text : public Node { 00714 public: 00715 Text( const Node *parent, const XmlTree &xml ); 00716 00717 Vec2f getTextPen() const; 00718 float getRotation() const; 00719 00720 protected: 00721 virtual void renderSelf( Renderer &renderer ) const; 00722 00723 TextSpan::Attributes mAttributes; 00724 00725 std::vector<TextSpanRef> mSpans; 00726 }; 00727 00729 class Group : public Node { 00730 public: 00731 Group( const Node *parent ) : Node( parent ) {} 00732 Group( const Node *parent, const XmlTree &xml ); 00733 ~Group(); 00734 00736 template<typename T> 00737 const T* find( const std::string &id ) { return dynamic_cast<const T*>( findNode( id ) ); } 00739 const Node* findNode( const std::string &id, bool recurse = true ) const; 00740 virtual const Node* findInAncestors( const std::string &elementId ) const; 00742 const Node& getChild( const std::string &id ) const; 00744 const Node& operator/( const std::string &id ) const { return getChild( id ); } 00745 00747 virtual Shape2d getShape() const { return getMergedShape2d(); } 00748 00750 void appendMergedShape2d( Shape2d *appendTo ) const; 00751 00753 const std::list<Node*>& getChildren() const { return mChildren; } 00755 std::list<Node*>& getChildren() { return mChildren; } 00756 00757 protected: 00758 Node* nodeUnderPoint( const Vec2f &absolutePoint, const MatrixAffine2f &parentInverseMatrix ) const; 00759 Shape2d getMergedShape2d() const; 00760 00761 virtual void renderSelf( Renderer &renderer ) const; 00762 virtual Rectf calcBoundingBox() const; 00763 00764 virtual bool isDrawable() const { return false; } 00765 void parse( const XmlTree &xml ); 00766 00767 std::list<Node*> mChildren; 00768 std::shared_ptr<Group> mDefs; 00769 }; 00770 00771 00772 typedef std::shared_ptr<Doc> DocRef; 00774 class Doc : public Group { 00775 public: 00776 Doc() : Group( 0 ), mWidth( 0 ), mHeight( 0 ) {} 00777 Doc( const fs::path &filePath ); 00778 Doc( DataSourceRef dataSource, const fs::path &filePath = fs::path() ); 00779 00780 static DocRef create( const fs::path &filePath ); 00781 static DocRef create( DataSourceRef dataSource, const fs::path &filePath = fs::path() ); 00782 static DocRef createFromSvgz( DataSourceRef dataSource, const fs::path &filePath = fs::path() ); 00783 00785 int32_t getWidth() const { return mWidth; } 00787 int32_t getHeight() const { return mHeight; } 00789 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00791 float getAspectRatio() const { return getWidth() / (float)getHeight(); } 00793 Area getBounds() const { return Area( 0, 0, mWidth, mHeight ); } 00794 00796 float getDpi() const { return 72.0f; } 00797 00799 Node* nodeUnderPoint( const Vec2f &pt ); 00800 00802 std::shared_ptr<Surface8u> loadImage( fs::path relativePath ); 00803 private: 00804 void loadDoc( DataSourceRef source, fs::path filePath ); 00805 00806 virtual void renderSelf( Renderer &renderer ) const; 00807 00808 std::shared_ptr<XmlTree> mXmlTree; 00809 std::map<fs::path,std::shared_ptr<Surface8u> > mImageCache; 00810 00811 fs::path mFilePath; 00812 Area mViewBox; 00813 int32_t mWidth, mHeight; 00814 }; 00815 00817 class Exc : public Exception 00818 {}; 00819 00820 class ValueExc : public Exc 00821 {}; 00822 00823 class FloatParseExc : public Exc 00824 {}; 00825 00826 class PathParseExc : public Exc 00827 {}; 00828 00829 class TransformParseExc : public Exc 00830 {}; 00831 00832 class ExcChildNotFound : public Exc { 00833 public: 00834 ExcChildNotFound( const std::string &child ) throw(); 00835 00836 virtual const char* what() const throw() { return mMessage; } 00837 00838 private: 00839 char mMessage[2048]; 00840 }; 00841 00842 00843 } } // namespace cinder::svg