The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

738 lines
32KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_PATH_JUCEHEADER__
  19. #define __JUCE_PATH_JUCEHEADER__
  20. #include "juce_AffineTransform.h"
  21. #include "juce_Line.h"
  22. #include "juce_Rectangle.h"
  23. #include "../contexts/juce_Justification.h"
  24. #include "../../../containers/juce_Array.h"
  25. #include "../../../io/streams/juce_InputStream.h"
  26. #include "../../../io/streams/juce_OutputStream.h"
  27. class Image;
  28. //==============================================================================
  29. /**
  30. A path is a sequence of lines and curves that may either form a closed shape
  31. or be open-ended.
  32. To use a path, you can create an empty one, then add lines and curves to it
  33. to create shapes, then it can be rendered by a Graphics context or used
  34. for geometric operations.
  35. e.g. @code
  36. Path myPath;
  37. myPath.startNewSubPath (10.0f, 10.0f); // move the current position to (10, 10)
  38. myPath.lineTo (100.0f, 200.0f); // draw a line from here to (100, 200)
  39. myPath.quadraticTo (0.0f, 150.0f, 5.0f, 50.0f); // draw a curve that ends at (5, 50)
  40. myPath.closeSubPath(); // close the subpath with a line back to (10, 10)
  41. // add an ellipse as well, which will form a second sub-path within the path..
  42. myPath.addEllipse (50.0f, 50.0f, 40.0f, 30.0f);
  43. // double the width of the whole thing..
  44. myPath.applyTransform (AffineTransform::scale (2.0f, 1.0f));
  45. // and draw it to a graphics context with a 5-pixel thick outline.
  46. g.strokePath (myPath, PathStrokeType (5.0f));
  47. @endcode
  48. A path object can actually contain multiple sub-paths, which may themselves
  49. be open or closed.
  50. @see PathFlatteningIterator, PathStrokeType, Graphics
  51. */
  52. class JUCE_API Path
  53. {
  54. public:
  55. //==============================================================================
  56. /** Creates an empty path. */
  57. Path();
  58. /** Creates a copy of another path. */
  59. Path (const Path& other);
  60. /** Destructor. */
  61. ~Path();
  62. /** Copies this path from another one. */
  63. Path& operator= (const Path& other);
  64. bool operator== (const Path& other) const throw();
  65. bool operator!= (const Path& other) const throw();
  66. //==============================================================================
  67. /** Returns true if the path doesn't contain any lines or curves. */
  68. bool isEmpty() const throw();
  69. /** Returns the smallest rectangle that contains all points within the path.
  70. */
  71. const Rectangle<float> getBounds() const throw();
  72. /** Returns the smallest rectangle that contains all points within the path
  73. after it's been transformed with the given tranasform matrix.
  74. */
  75. const Rectangle<float> getBoundsTransformed (const AffineTransform& transform) const throw();
  76. /** Checks whether a point lies within the path.
  77. This is only relevent for closed paths (see closeSubPath()), and
  78. may produce false results if used on a path which has open sub-paths.
  79. The path's winding rule is taken into account by this method.
  80. The tolerence parameter is passed to the PathFlatteningIterator that
  81. is used to trace the path - for more info about it, see the notes for
  82. the PathFlatteningIterator constructor.
  83. @see closeSubPath, setUsingNonZeroWinding
  84. */
  85. bool contains (float x, float y,
  86. float tolerence = 10.0f) const;
  87. /** Checks whether a point lies within the path.
  88. This is only relevent for closed paths (see closeSubPath()), and
  89. may produce false results if used on a path which has open sub-paths.
  90. The path's winding rule is taken into account by this method.
  91. The tolerence parameter is passed to the PathFlatteningIterator that
  92. is used to trace the path - for more info about it, see the notes for
  93. the PathFlatteningIterator constructor.
  94. @see closeSubPath, setUsingNonZeroWinding
  95. */
  96. bool contains (const Point<float>& point,
  97. float tolerence = 10.0f) const;
  98. /** Checks whether a line crosses the path.
  99. This will return positive if the line crosses any of the paths constituent
  100. lines or curves. It doesn't take into account whether the line is inside
  101. or outside the path, or whether the path is open or closed.
  102. The tolerence parameter is passed to the PathFlatteningIterator that
  103. is used to trace the path - for more info about it, see the notes for
  104. the PathFlatteningIterator constructor.
  105. */
  106. bool intersectsLine (const Line<float>& line,
  107. float tolerence = 10.0f);
  108. /** Cuts off parts of a line to keep the parts that are either inside or
  109. outside this path.
  110. Note that this isn't smart enough to cope with situations where the
  111. line would need to be cut into multiple pieces to correctly clip against
  112. a re-entrant shape.
  113. @param line the line to clip
  114. @param keepSectionOutsidePath if true, it's the section outside the path
  115. that will be kept; if false its the section inside
  116. the path
  117. */
  118. const Line<float> getClippedLine (const Line<float>& line, bool keepSectionOutsidePath) const;
  119. /** Returns the length of the path.
  120. @see getPointAlongPath
  121. */
  122. float getLength (const AffineTransform& transform = AffineTransform::identity) const;
  123. /** Returns a point that is the specified distance along the path.
  124. If the distance is greater than the total length of the path, this will return the
  125. end point.
  126. @see getLength
  127. */
  128. const Point<float> getPointAlongPath (float distanceFromStart,
  129. const AffineTransform& transform = AffineTransform::identity) const;
  130. /** Finds the point along the path which is nearest to a given position.
  131. This sets pointOnPath to the nearest point, and returns the distance of this point from the start
  132. of the path.
  133. */
  134. float getNearestPoint (const Point<float>& targetPoint,
  135. Point<float>& pointOnPath,
  136. const AffineTransform& transform = AffineTransform::identity) const;
  137. //==============================================================================
  138. /** Removes all lines and curves, resetting the path completely. */
  139. void clear() throw();
  140. /** Begins a new subpath with a given starting position.
  141. This will move the path's current position to the co-ordinates passed in and
  142. make it ready to draw lines or curves starting from this position.
  143. After adding whatever lines and curves are needed, you can either
  144. close the current sub-path using closeSubPath() or call startNewSubPath()
  145. to move to a new sub-path, leaving the old one open-ended.
  146. @see lineTo, quadraticTo, cubicTo, closeSubPath
  147. */
  148. void startNewSubPath (float startX, float startY);
  149. /** Begins a new subpath with a given starting position.
  150. This will move the path's current position to the co-ordinates passed in and
  151. make it ready to draw lines or curves starting from this position.
  152. After adding whatever lines and curves are needed, you can either
  153. close the current sub-path using closeSubPath() or call startNewSubPath()
  154. to move to a new sub-path, leaving the old one open-ended.
  155. @see lineTo, quadraticTo, cubicTo, closeSubPath
  156. */
  157. void startNewSubPath (const Point<float>& start);
  158. /** Closes a the current sub-path with a line back to its start-point.
  159. When creating a closed shape such as a triangle, don't use 3 lineTo()
  160. calls - instead use two lineTo() calls, followed by a closeSubPath()
  161. to join the final point back to the start.
  162. This ensures that closes shapes are recognised as such, and this is
  163. important for tasks like drawing strokes, which needs to know whether to
  164. draw end-caps or not.
  165. @see startNewSubPath, lineTo, quadraticTo, cubicTo, closeSubPath
  166. */
  167. void closeSubPath();
  168. /** Adds a line from the shape's last position to a new end-point.
  169. This will connect the end-point of the last line or curve that was added
  170. to a new point, using a straight line.
  171. See the class description for an example of how to add lines and curves to a path.
  172. @see startNewSubPath, quadraticTo, cubicTo, closeSubPath
  173. */
  174. void lineTo (float endX, float endY);
  175. /** Adds a line from the shape's last position to a new end-point.
  176. This will connect the end-point of the last line or curve that was added
  177. to a new point, using a straight line.
  178. See the class description for an example of how to add lines and curves to a path.
  179. @see startNewSubPath, quadraticTo, cubicTo, closeSubPath
  180. */
  181. void lineTo (const Point<float>& end);
  182. /** Adds a quadratic bezier curve from the shape's last position to a new position.
  183. This will connect the end-point of the last line or curve that was added
  184. to a new point, using a quadratic spline with one control-point.
  185. See the class description for an example of how to add lines and curves to a path.
  186. @see startNewSubPath, lineTo, cubicTo, closeSubPath
  187. */
  188. void quadraticTo (float controlPointX,
  189. float controlPointY,
  190. float endPointX,
  191. float endPointY);
  192. /** Adds a quadratic bezier curve from the shape's last position to a new position.
  193. This will connect the end-point of the last line or curve that was added
  194. to a new point, using a quadratic spline with one control-point.
  195. See the class description for an example of how to add lines and curves to a path.
  196. @see startNewSubPath, lineTo, cubicTo, closeSubPath
  197. */
  198. void quadraticTo (const Point<float>& controlPoint,
  199. const Point<float>& endPoint);
  200. /** Adds a cubic bezier curve from the shape's last position to a new position.
  201. This will connect the end-point of the last line or curve that was added
  202. to a new point, using a cubic spline with two control-points.
  203. See the class description for an example of how to add lines and curves to a path.
  204. @see startNewSubPath, lineTo, quadraticTo, closeSubPath
  205. */
  206. void cubicTo (float controlPoint1X,
  207. float controlPoint1Y,
  208. float controlPoint2X,
  209. float controlPoint2Y,
  210. float endPointX,
  211. float endPointY);
  212. /** Adds a cubic bezier curve from the shape's last position to a new position.
  213. This will connect the end-point of the last line or curve that was added
  214. to a new point, using a cubic spline with two control-points.
  215. See the class description for an example of how to add lines and curves to a path.
  216. @see startNewSubPath, lineTo, quadraticTo, closeSubPath
  217. */
  218. void cubicTo (const Point<float>& controlPoint1,
  219. const Point<float>& controlPoint2,
  220. const Point<float>& endPoint);
  221. /** Returns the last point that was added to the path by one of the drawing methods.
  222. */
  223. const Point<float> getCurrentPosition() const;
  224. //==============================================================================
  225. /** Adds a rectangle to the path.
  226. The rectangle is added as a new sub-path. (Any currently open paths will be
  227. left open).
  228. @see addRoundedRectangle, addTriangle
  229. */
  230. void addRectangle (float x, float y, float width, float height);
  231. /** Adds a rectangle to the path.
  232. The rectangle is added as a new sub-path. (Any currently open paths will be
  233. left open).
  234. @see addRoundedRectangle, addTriangle
  235. */
  236. void addRectangle (const Rectangle<int>& rectangle);
  237. /** Adds a rectangle with rounded corners to the path.
  238. The rectangle is added as a new sub-path. (Any currently open paths will be
  239. left open).
  240. @see addRectangle, addTriangle
  241. */
  242. void addRoundedRectangle (float x, float y, float width, float height,
  243. float cornerSize);
  244. /** Adds a rectangle with rounded corners to the path.
  245. The rectangle is added as a new sub-path. (Any currently open paths will be
  246. left open).
  247. @see addRectangle, addTriangle
  248. */
  249. void addRoundedRectangle (float x, float y, float width, float height,
  250. float cornerSizeX,
  251. float cornerSizeY);
  252. /** Adds a triangle to the path.
  253. The triangle is added as a new closed sub-path. (Any currently open paths will be
  254. left open).
  255. Note that whether the vertices are specified in clockwise or anticlockwise
  256. order will affect how the triangle is filled when it overlaps other
  257. shapes (the winding order setting will affect this of course).
  258. */
  259. void addTriangle (float x1, float y1,
  260. float x2, float y2,
  261. float x3, float y3);
  262. /** Adds a quadrilateral to the path.
  263. The quad is added as a new closed sub-path. (Any currently open paths will be
  264. left open).
  265. Note that whether the vertices are specified in clockwise or anticlockwise
  266. order will affect how the quad is filled when it overlaps other
  267. shapes (the winding order setting will affect this of course).
  268. */
  269. void addQuadrilateral (float x1, float y1,
  270. float x2, float y2,
  271. float x3, float y3,
  272. float x4, float y4);
  273. /** Adds an ellipse to the path.
  274. The shape is added as a new sub-path. (Any currently open paths will be
  275. left open).
  276. @see addArc
  277. */
  278. void addEllipse (float x, float y, float width, float height);
  279. /** Adds an elliptical arc to the current path.
  280. Note that when specifying the start and end angles, the curve will be drawn either clockwise
  281. or anti-clockwise according to whether the end angle is greater than the start. This means
  282. that sometimes you may need to use values greater than 2*Pi for the end angle.
  283. @param x the left-hand edge of the rectangle in which the elliptical outline fits
  284. @param y the top edge of the rectangle in which the elliptical outline fits
  285. @param width the width of the rectangle in which the elliptical outline fits
  286. @param height the height of the rectangle in which the elliptical outline fits
  287. @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the
  288. top-centre of the ellipse)
  289. @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the
  290. top-centre of the ellipse). This angle can be greater than 2*Pi, so for example to
  291. draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via
  292. 12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points.
  293. @param startAsNewSubPath if true, the arc will begin a new subpath from its starting point; if false,
  294. it will be added to the current sub-path, continuing from the current postition
  295. @see addCentredArc, arcTo, addPieSegment, addEllipse
  296. */
  297. void addArc (float x, float y, float width, float height,
  298. float fromRadians,
  299. float toRadians,
  300. bool startAsNewSubPath = false);
  301. /** Adds an arc which is centred at a given point, and can have a rotation specified.
  302. Note that when specifying the start and end angles, the curve will be drawn either clockwise
  303. or anti-clockwise according to whether the end angle is greater than the start. This means
  304. that sometimes you may need to use values greater than 2*Pi for the end angle.
  305. @param centreX the centre x of the ellipse
  306. @param centreY the centre y of the ellipse
  307. @param radiusX the horizontal radius of the ellipse
  308. @param radiusY the vertical radius of the ellipse
  309. @param rotationOfEllipse an angle by which the whole ellipse should be rotated about its centre, in radians (clockwise)
  310. @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the
  311. top-centre of the ellipse)
  312. @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the
  313. top-centre of the ellipse). This angle can be greater than 2*Pi, so for example to
  314. draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via
  315. 12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points.
  316. @param startAsNewSubPath if true, the arc will begin a new subpath from its starting point; if false,
  317. it will be added to the current sub-path, continuing from the current postition
  318. @see addArc, arcTo
  319. */
  320. void addCentredArc (float centreX, float centreY,
  321. float radiusX, float radiusY,
  322. float rotationOfEllipse,
  323. float fromRadians,
  324. float toRadians,
  325. bool startAsNewSubPath = false);
  326. /** Adds a "pie-chart" shape to the path.
  327. The shape is added as a new sub-path. (Any currently open paths will be
  328. left open).
  329. Note that when specifying the start and end angles, the curve will be drawn either clockwise
  330. or anti-clockwise according to whether the end angle is greater than the start. This means
  331. that sometimes you may need to use values greater than 2*Pi for the end angle.
  332. @param x the left-hand edge of the rectangle in which the elliptical outline fits
  333. @param y the top edge of the rectangle in which the elliptical outline fits
  334. @param width the width of the rectangle in which the elliptical outline fits
  335. @param height the height of the rectangle in which the elliptical outline fits
  336. @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the
  337. top-centre of the ellipse)
  338. @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the
  339. top-centre of the ellipse)
  340. @param innerCircleProportionalSize if this is > 0, then the pie will be drawn as a curved band around a hollow
  341. ellipse at its centre, where this value indicates the inner ellipse's size with
  342. respect to the outer one.
  343. @see addArc
  344. */
  345. void addPieSegment (float x, float y,
  346. float width, float height,
  347. float fromRadians,
  348. float toRadians,
  349. float innerCircleProportionalSize);
  350. /** Adds a line with a specified thickness.
  351. The line is added as a new closed sub-path. (Any currently open paths will be
  352. left open).
  353. @see addArrow
  354. */
  355. void addLineSegment (const Line<float>& line, float lineThickness);
  356. /** Adds a line with an arrowhead on the end.
  357. The arrow is added as a new closed sub-path. (Any currently open paths will be left open).
  358. @see PathStrokeType::createStrokeWithArrowheads
  359. */
  360. void addArrow (const Line<float>& line,
  361. float lineThickness,
  362. float arrowheadWidth,
  363. float arrowheadLength);
  364. /** Adds a polygon shape to the path.
  365. @see addStar
  366. */
  367. void addPolygon (const Point<float>& centre,
  368. int numberOfSides,
  369. float radius,
  370. float startAngle = 0.0f);
  371. /** Adds a star shape to the path.
  372. @see addPolygon
  373. */
  374. void addStar (const Point<float>& centre,
  375. int numberOfPoints,
  376. float innerRadius,
  377. float outerRadius,
  378. float startAngle = 0.0f);
  379. /** Adds a speech-bubble shape to the path.
  380. @param bodyX the left of the main body area of the bubble
  381. @param bodyY the top of the main body area of the bubble
  382. @param bodyW the width of the main body area of the bubble
  383. @param bodyH the height of the main body area of the bubble
  384. @param cornerSize the amount by which to round off the corners of the main body rectangle
  385. @param arrowTipX the x position that the tip of the arrow should connect to
  386. @param arrowTipY the y position that the tip of the arrow should connect to
  387. @param whichSide the side to connect the arrow to: 0 = top, 1 = left, 2 = bottom, 3 = right
  388. @param arrowPositionAlongEdgeProportional how far along the edge of the main rectangle the
  389. arrow's base should be - this is a proportional distance between 0 and 1.0
  390. @param arrowWidth how wide the base of the arrow should be where it joins the main rectangle
  391. */
  392. void addBubble (float bodyX, float bodyY,
  393. float bodyW, float bodyH,
  394. float cornerSize,
  395. float arrowTipX,
  396. float arrowTipY,
  397. int whichSide,
  398. float arrowPositionAlongEdgeProportional,
  399. float arrowWidth);
  400. /** Adds another path to this one.
  401. The new path is added as a new sub-path. (Any currently open paths in this
  402. path will be left open).
  403. @param pathToAppend the path to add
  404. */
  405. void addPath (const Path& pathToAppend);
  406. /** Adds another path to this one, transforming it on the way in.
  407. The new path is added as a new sub-path, its points being transformed by the given
  408. matrix before being added.
  409. @param pathToAppend the path to add
  410. @param transformToApply an optional transform to apply to the incoming vertices
  411. */
  412. void addPath (const Path& pathToAppend,
  413. const AffineTransform& transformToApply);
  414. /** Swaps the contents of this path with another one.
  415. The internal data of the two paths is swapped over, so this is much faster than
  416. copying it to a temp variable and back.
  417. */
  418. void swapWithPath (Path& other) throw();
  419. //==============================================================================
  420. /** Applies a 2D transform to all the vertices in the path.
  421. @see AffineTransform, scaleToFit, getTransformToScaleToFit
  422. */
  423. void applyTransform (const AffineTransform& transform) throw();
  424. /** Rescales this path to make it fit neatly into a given space.
  425. This is effectively a quick way of calling
  426. applyTransform (getTransformToScaleToFit (x, y, w, h, preserveProportions))
  427. @param x the x position of the rectangle to fit the path inside
  428. @param y the y position of the rectangle to fit the path inside
  429. @param width the width of the rectangle to fit the path inside
  430. @param height the height of the rectangle to fit the path inside
  431. @param preserveProportions if true, it will fit the path into the space without altering its
  432. horizontal/vertical scale ratio; if false, it will distort the
  433. path to fill the specified ratio both horizontally and vertically
  434. @see applyTransform, getTransformToScaleToFit
  435. */
  436. void scaleToFit (float x, float y, float width, float height,
  437. bool preserveProportions) throw();
  438. /** Returns a transform that can be used to rescale the path to fit into a given space.
  439. @param x the x position of the rectangle to fit the path inside
  440. @param y the y position of the rectangle to fit the path inside
  441. @param width the width of the rectangle to fit the path inside
  442. @param height the height of the rectangle to fit the path inside
  443. @param preserveProportions if true, it will fit the path into the space without altering its
  444. horizontal/vertical scale ratio; if false, it will distort the
  445. path to fill the specified ratio both horizontally and vertically
  446. @param justificationType if the proportions are preseved, the resultant path may be smaller
  447. than the available rectangle, so this describes how it should be
  448. positioned within the space.
  449. @returns an appropriate transformation
  450. @see applyTransform, scaleToFit
  451. */
  452. const AffineTransform getTransformToScaleToFit (float x, float y, float width, float height,
  453. bool preserveProportions,
  454. const Justification& justificationType = Justification::centred) const;
  455. /** Creates a version of this path where all sharp corners have been replaced by curves.
  456. Wherever two lines meet at an angle, this will replace the corner with a curve
  457. of the given radius.
  458. */
  459. const Path createPathWithRoundedCorners (float cornerRadius) const;
  460. //==============================================================================
  461. /** Changes the winding-rule to be used when filling the path.
  462. If set to true (which is the default), then the path uses a non-zero-winding rule
  463. to determine which points are inside the path. If set to false, it uses an
  464. alternate-winding rule.
  465. The winding-rule comes into play when areas of the shape overlap other
  466. areas, and determines whether the overlapping regions are considered to be
  467. inside or outside.
  468. Changing this value just sets a flag - it doesn't affect the contents of the
  469. path.
  470. @see isUsingNonZeroWinding
  471. */
  472. void setUsingNonZeroWinding (bool isNonZeroWinding) throw();
  473. /** Returns the flag that indicates whether the path should use a non-zero winding rule.
  474. The default for a new path is true.
  475. @see setUsingNonZeroWinding
  476. */
  477. bool isUsingNonZeroWinding() const { return useNonZeroWinding; }
  478. //==============================================================================
  479. /** Iterates the lines and curves that a path contains.
  480. @see Path, PathFlatteningIterator
  481. */
  482. class JUCE_API Iterator
  483. {
  484. public:
  485. //==============================================================================
  486. Iterator (const Path& path);
  487. ~Iterator();
  488. //==============================================================================
  489. /** Moves onto the next element in the path.
  490. If this returns false, there are no more elements. If it returns true,
  491. the elementType variable will be set to the type of the current element,
  492. and some of the x and y variables will be filled in with values.
  493. */
  494. bool next();
  495. //==============================================================================
  496. enum PathElementType
  497. {
  498. startNewSubPath, /**< For this type, x1 and y1 will be set to indicate the first point in the subpath. */
  499. lineTo, /**< For this type, x1 and y1 indicate the end point of the line. */
  500. quadraticTo, /**< For this type, x1, y1, x2, y2 indicate the control point and endpoint of a quadratic curve. */
  501. cubicTo, /**< For this type, x1, y1, x2, y2, x3, y3 indicate the two control points and the endpoint of a cubic curve. */
  502. closePath /**< Indicates that the sub-path is being closed. None of the x or y values are valid in this case. */
  503. };
  504. PathElementType elementType;
  505. float x1, y1, x2, y2, x3, y3;
  506. //==============================================================================
  507. private:
  508. const Path& path;
  509. size_t index;
  510. Iterator (const Iterator&);
  511. Iterator& operator= (const Iterator&);
  512. };
  513. //==============================================================================
  514. /** Loads a stored path from a data stream.
  515. The data in the stream must have been written using writePathToStream().
  516. Note that this will append the stored path to whatever is currently in
  517. this path, so you might need to call clear() beforehand.
  518. @see loadPathFromData, writePathToStream
  519. */
  520. void loadPathFromStream (InputStream& source);
  521. /** Loads a stored path from a block of data.
  522. This is similar to loadPathFromStream(), but just reads from a block
  523. of data. Useful if you're including stored shapes in your code as a
  524. block of static data.
  525. @see loadPathFromStream, writePathToStream
  526. */
  527. void loadPathFromData (const void* data, int numberOfBytes);
  528. /** Stores the path by writing it out to a stream.
  529. After writing out a path, you can reload it using loadPathFromStream().
  530. @see loadPathFromStream, loadPathFromData
  531. */
  532. void writePathToStream (OutputStream& destination) const;
  533. //==============================================================================
  534. /** Creates a string containing a textual representation of this path.
  535. @see restoreFromString
  536. */
  537. const String toString() const;
  538. /** Restores this path from a string that was created with the toString() method.
  539. @see toString()
  540. */
  541. void restoreFromString (const String& stringVersion);
  542. //==============================================================================
  543. juce_UseDebuggingNewOperator
  544. private:
  545. friend class PathFlatteningIterator;
  546. friend class Path::Iterator;
  547. ArrayAllocationBase <float, DummyCriticalSection> data;
  548. size_t numElements;
  549. float pathXMin, pathXMax, pathYMin, pathYMax;
  550. bool useNonZeroWinding;
  551. static const float lineMarker;
  552. static const float moveMarker;
  553. static const float quadMarker;
  554. static const float cubicMarker;
  555. static const float closeSubPathMarker;
  556. };
  557. #endif // __JUCE_PATH_JUCEHEADER__