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