SkPath.h revision 020b25becb4a99061e8643780c887ad472eb0648
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2006 The Android Open Source Project 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SkPath_DEFINED 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SkPath_DEFINED 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkInstCnt.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMatrix.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTDArray.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkRefCnt.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SK_BUILD_FOR_ANDROID 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_INC fGenerationID++ 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_PTR_INC(ptr) (ptr)->fGenerationID++ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_INC 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_PTR_INC(ptr) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkReader32; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkWriter32; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkAutoPathBoundsUpdate; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SkString; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPathRef; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkRRect; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SK_DEBUG_PATH_REF 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SK_DEBUG_PATH_REF 0 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** \class SkPath 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) The SkPath class encapsulates compound (multiple contour) geometric paths 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consisting of straight line segments, quadratic curves, and cubic curves. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SK_API SkPath { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_DECLARE_INST_COUNT_ROOT(SkPath); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPath(); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPath(const SkPath&); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SkPath(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPath& operator=(const SkPath&); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend SK_API bool operator==(const SkPath&, const SkPath&); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend bool operator!=(const SkPath& a, const SkPath& b) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !(a == b); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum FillType { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** Specifies that "inside" is computed by a non-zero sum of signed 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) edge crossings 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kWinding_FillType, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Specifies that "inside" is computed by an odd number of edge 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crossings 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kEvenOdd_FillType, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** Same as Winding, but draws outside of the path, rather than inside 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInverseWinding_FillType, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Same as EvenOdd, but draws outside of the path, rather than inside 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInverseEvenOdd_FillType 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Return the path's fill type. This is used to define how "inside" is 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computed. The default value is kWinding_FillType. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return the path's fill type 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillType getFillType() const { return (FillType)fFillType; } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Set the path's fill type. This is used to define how "inside" is 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computed. The default value is kWinding_FillType. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param ft The new fill type for this path 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setFillType(FillType ft) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fFillType = SkToU8(ft); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GEN_ID_INC; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns true if the filltype is one of the Inverse variants */ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Toggle between inverse and normal filltypes. This reverse the return 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * value of isInverseFillType() 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void toggleInverseFillType() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fFillType ^= 2; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GEN_ID_INC; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Convexity { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUnknown_Convexity, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kConvex_Convexity, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kConcave_Convexity 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the path's convexity, as stored in the path. If it is currently unknown, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then this function will attempt to compute the convexity (and cache the result). 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Convexity getConvexity() const { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (kUnknown_Convexity != fConvexity) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<Convexity>(fConvexity); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this->internalGetConvexity(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the currently cached value for convexity, even if that is set to 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kUnknown_Convexity. Note: getConvexity() will automatically call 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ComputeConvexity and cache its return value if the current setting is 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kUnknown. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Store a convexity setting in the path. There is no automatic check to 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * see if this value actually agrees with the return value that would be 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * computed by getConvexity(). 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note: even if this is set to a "known" value, if the path is later 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * reset to kUnknown_Convexity. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setConvexity(Convexity); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DEPRECATED: use getConvexity() 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the path is flagged as being convex. This is not a 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * confirmed by any analysis, it is just the value set earlier. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isConvex() const { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kConvex_Convexity == this->getConvexity(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DEPRECATED: use setConvexity() 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set the isConvex flag to true or false. Convex paths may draw faster if 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this flag is set, though setting this to true on a path that is in fact 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * not convex can give undefined results when drawn. Paths default to 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * isConvex == false 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setIsConvex(bool isConvex) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns true if the path is an oval. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param rect returns the bounding rect of this oval. It's a circle 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the height and width are the same. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return true if this path is an oval. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Tracking whether a path is an oval is considered an 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * optimization for performance and so some paths that are in 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fact ovals can report false. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isOval(SkRect* rect) const; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Clear any lines and curves from the path, making it empty. This frees up 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal storage associated with those segments. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) This does NOT change the fill-type setting nor isConvex 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void reset(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Similar to reset(), in that all lines and curves are removed from the 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path. However, any internal storage for those lines/curves is retained, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) making reuse of the path potentially faster. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) This does NOT change the fill-type setting nor isConvex 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rewind(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns true if the path is empty (contains no lines or curves) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the path is empty (contains no lines or curves) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isEmpty() const; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if all of the points in this path are finite, meaning there 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are no infinities and no NaNs. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isFinite() const { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fBoundsIsDirty) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->computeBounds(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkToBool(fIsFinite); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Test a line for zero length 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the line is of zero length; otherwise false. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p1.equalsWithinTolerance(p2); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Test a quad for zero length 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the quad is of zero length; otherwise false. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkPoint& p3) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p1.equalsWithinTolerance(p2) && 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p2.equalsWithinTolerance(p3); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Test a cubic curve for zero length 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the cubic is of zero length; otherwise false. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkPoint& p3, const SkPoint& p4) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p1.equalsWithinTolerance(p2) && 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p2.equalsWithinTolerance(p3) && 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p3.equalsWithinTolerance(p4); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the path specifies a single line (i.e. it contains just 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * points in line[] to the end-points of the line. If the path is not a 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * line, returns false and ignores line[]. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isLine(SkPoint line[2]) const; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Direction { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Direction either has not been or could not be computed */ 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUnknown_Direction, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** clockwise direction for adding closed contours */ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCW_Direction, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** counter-clockwise direction for adding closed contours */ 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kCCW_Direction, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns true if the path specifies a rectangle. If so, and if rect is 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) not null, set rect to the bounds of the path. If the path does not 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) specify a rectangle, return false and ignore rect. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param rect If not null, returns the bounds of the path if it specifies 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a rectangle 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the path specifies a rectangle 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isRect(SkRect* rect) const { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this->isRect(rect, NULL, NULL); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the path specifies a rectangle. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If this returns false, then all output parameters are ignored, and left 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * unchanged. If this returns true, then each of the output parameters 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are checked for NULL. If they are not, they return their value. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param rect If not null, set to the bounds of the rectangle 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param isClosed If not null, set to true if the path is closed 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param direction If not null, set to the rectangle's direction 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return true if the path specifies a rectangle 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isRect(SkRect* rect, bool* isClosed, Direction* direction) const; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns true if the path specifies a pair of nested rectangles. If so, and if 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rectangle. If so, and dirs is not null, set dirs[0] to the direction of 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the outer rectangle and dirs[1] to the direction of the inner rectangle. If 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the path does not specify a pair of nested rectangles, return 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false and ignore rect and dirs. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param rect If not null, returns the path as a pair of nested rectangles 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dirs If not null, returns the direction of the rects 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return true if the path describes a pair of nested rectangles 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Return the number of points in the path 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int countPoints() const; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Return the point at the specified index. If the index is out of range 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (i.e. is not 0 <= index < countPoints()) then the returned coordinates 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) will be (0,0) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPoint getPoint(int index) const; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns the number of points in the path. Up to max points are copied. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param points If not null, receives up to max points 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param max The maximum number of points to copy into points 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return the actual number of points in the path 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int getPoints(SkPoint points[], int max) const; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Return the number of verbs in the path 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int countVerbs() const; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns the number of verbs in the path. Up to max verbs are copied. The 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verbs are copied as one byte per verb. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param verbs If not null, receives up to max verbs 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param max The maximum number of verbs to copy into verbs 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @return the actual number of verbs in the path 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int getVerbs(uint8_t verbs[], int max) const; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) //! Swap contents of this and other. Guaranteed not to throw 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void swap(SkPath& other); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Returns the bounds of the path's points. If the path contains 0 or 1 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) points, the bounds is set to (0,0,0,0), and isEmpty() will return true. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Note: this bounds may be larger than the actual shape, since curves 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do not extend as far as their control points. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkRect& getBounds() const { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fBoundsIsDirty) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->computeBounds(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fBounds; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Calling this will, if the internal cache of the bounds is out of date, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update it so that subsequent calls to getBounds will be instantaneous. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) This also means that any copies or simple transformations of the path 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) will inherit the cached bounds. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void updateBoundsCache() const { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for now, just calling getBounds() is sufficient 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->getBounds(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Does a conservative test to see whether a rectangle is inside a path. Currently it only 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will ever return true for single convex contour paths. The empty-status of the rect is not 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * considered (e.g. a rect that is a point can be inside a path). Points or line segments where 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rect edge touches the path border are not considered containment violations. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool conservativelyContainsRect(const SkRect& rect) const; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construction methods 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Hint to the path to prepare for adding more points. This can allow the 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path to more efficiently grow its storage. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param extraPtCount The number of extra points the path should 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preallocate for. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void incReserve(unsigned extraPtCount); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Set the beginning of the next contour to the point (x,y). 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param x The x-coordinate of the start of a new contour 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param y The y-coordinate of the start of a new contour 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void moveTo(SkScalar x, SkScalar y); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Set the beginning of the next contour to the point 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p The start of a new contour 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void moveTo(const SkPoint& p) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->moveTo(p.fX, p.fY); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Set the beginning of the next contour relative to the last point on the 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous contour. If there is no previous contour, this is treated the 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) same as moveTo(). 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dx The amount to add to the x-coordinate of the end of the 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous contour, to specify the start of a new contour 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy The amount to add to the y-coordinate of the end of the 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous contour, to specify the start of a new contour 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rMoveTo(SkScalar dx, SkScalar dy); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Add a line from the last point to the specified point (x,y). If no 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) moveTo() call has been made for this contour, the first point is 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) automatically set to (0,0). 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param x The x-coordinate of the end of a line 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param y The y-coordinate of the end of a line 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void lineTo(SkScalar x, SkScalar y); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** Add a line from the last point to the specified point. If no moveTo() 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) call has been made for this contour, the first point is automatically 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set to (0,0). 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param p The end of a line 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void lineTo(const SkPoint& p) { 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this->lineTo(p.fX, p.fY); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** Same as lineTo, but the coordinates are considered relative to the last 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) point on this contour. If there is no previous point, then a moveTo(0,0) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is inserted automatically. 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dx The amount to add to the x-coordinate of the previous point 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on this contour, to specify a line 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy The amount to add to the y-coordinate of the previous point 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) on this contour, to specify a line 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rLineTo(SkScalar dx, SkScalar dy); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Add a quadratic bezier from the last point, approaching control point 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, the first point is automatically set to (0,0). 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param x1 The x-coordinate of the control point on a quadratic curve 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param y1 The y-coordinate of the control point on a quadratic curve 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param x2 The x-coordinate of the end point on a quadratic curve 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param y2 The y-coordinate of the end point on a quadratic curve 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Add a quadratic bezier from the last point, approaching control point 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p1, and ending at p2. If no moveTo() call has been made for this 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contour, the first point is automatically set to (0,0). 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p1 The control point on a quadratic curve 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p2 The end point on a quadratic curve 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void quadTo(const SkPoint& p1, const SkPoint& p2) { 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Same as quadTo, but the coordinates are considered relative to the last 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) point on this contour. If there is no previous point, then a moveTo(0,0) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is inserted automatically. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dx1 The amount to add to the x-coordinate of the last point on 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the control point of a quadratic curve 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy1 The amount to add to the y-coordinate of the last point on 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the control point of a quadratic curve 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param dx2 The amount to add to the x-coordinate of the last point on 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the end point of a quadratic curve 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy2 The amount to add to the y-coordinate of the last point on 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the end point of a quadratic curve 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkScalar w); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkScalar w); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Add a cubic bezier from the last point, approaching control points 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) made for this contour, the first point is automatically set to (0,0). 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param x1 The x-coordinate of the 1st control point on a cubic curve 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param y1 The y-coordinate of the 1st control point on a cubic curve 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param x2 The x-coordinate of the 2nd control point on a cubic curve 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param y2 The y-coordinate of the 2nd control point on a cubic curve 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param x3 The x-coordinate of the end point on a cubic curve 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param y3 The y-coordinate of the end point on a cubic curve 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkScalar x3, SkScalar y3); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Add a cubic bezier from the last point, approaching control points p1 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) and p2, and ending at p3. If no moveTo() call has been made for this 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contour, the first point is automatically set to (0,0). 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p1 The 1st control point on a cubic curve 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p2 The 2nd control point on a cubic curve 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param p3 The end point on a cubic curve 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Same as cubicTo, but the coordinates are considered relative to the 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current point on this contour. If there is no previous point, then a 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) moveTo(0,0) is inserted automatically. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dx1 The amount to add to the x-coordinate of the last point on 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the 1st control point of a cubic curve 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy1 The amount to add to the y-coordinate of the last point on 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the 1st control point of a cubic curve 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dx2 The amount to add to the x-coordinate of the last point on 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this contour, to specify the 2nd control point of a cubic curve 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param dy2 The amount to add to the y-coordinate of the last point on 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this contour, to specify the 2nd control point of a cubic curve 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param dx3 The amount to add to the x-coordinate of the last point on 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this contour, to specify the end point of a cubic curve 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @param dy3 The amount to add to the y-coordinate of the last point on 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this contour, to specify the end point of a cubic curve 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkScalar x3, SkScalar y3); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Append the specified arc to the path as a new contour. If the start of 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) the path is different from the path's current last point, then an 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) automatic lineTo() is added to connect the current contour to the start 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) of the arc. However, if the path is empty, then we call moveTo() with 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) the first point of the arc. The sweep angle is treated mod 360. 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param oval The bounding oval defining the shape and size of the arc 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param startAngle Starting angle (in degrees) where the arc begins 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param sweepAngle Sweep angle (in degrees) measured clockwise. This is 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) treated mod 360. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @param forceMoveTo If true, always begin a new contour with the arc 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool forceMoveTo); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Append a line and arc to the current path. This is the same as the 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostScript call "arct". 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkScalar radius); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** Append a line and arc to the current path. This is the same as the 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostScript call "arct". 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) { 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** Close the current contour. If the current point is not equal to the 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first point of the contour, a line segment is automatically added. 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void close(); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the opposite of the specified direction. kUnknown is its own 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * opposite. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Direction OppositeDirection(Direction dir) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const Direction gOppositeDir[] = { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUnknown_Direction, kCCW_Direction, kCW_Direction 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gOppositeDir[dir]; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns whether or not a fill type is inverted 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kWinding_FillType -> false 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kEvenOdd_FillType -> false 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kInverseWinding_FillType -> true 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kInverseEvenOdd_FillType -> true 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsInverseFillType(FillType fill) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fill & 2) != 0; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the equivalent non-inverted fill type to the given fill type 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kWinding_FillType -> kWinding_FillType 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kEvenOdd_FillType -> kEvenOdd_FillType 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kInverseWinding_FillType -> kWinding_FillType 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kInverseEvenOdd_FillType -> kEvenOdd_FillType 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static FillType ConvertToNonInverseFillType(FillType fill) { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (FillType)(fill & 1); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Tries to quickly compute the direction of the first non-degenerate 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contour. If it can be computed, return true and set dir to that 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * direction. If it cannot be (quickly) determined, return false and ignore 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the dir parameter. If the direction was determined, it is cached to make 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * subsequent calls return quickly. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cheapComputeDirection(Direction* dir) const; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the path's direction can be computed via 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cheapComputDirection() and if that computed direction matches the 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * specified direction. If dir is kUnknown, returns true if the direction 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cannot be computed. 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cheapIsDirection(Direction dir) const { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction computedDir = kUnknown_Direction; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)this->cheapComputeDirection(&computedDir); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return computedDir == dir; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a closed rectangle contour to the path 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param rect The rectangle to add as a closed contour to the path 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param dir The direction to wind the rectangle's contour. Cannot be 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kUnknown_Direction. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void addRect(const SkRect& rect, Direction dir = kCW_Direction); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a closed rectangle contour to the path 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param left The left side of a rectangle to add as a closed contour 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to the path 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param top The top of a rectangle to add as a closed contour to the 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * path 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param right The right side of a rectangle to add as a closed contour 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to the path 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param bottom The bottom of a rectangle to add as a closed contour to 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the path 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param dir The direction to wind the rectangle's contour. Cannot be 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * kUnknown_Direction. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 627 void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, 628 Direction dir = kCW_Direction); 629 630 /** 631 * Add a closed oval contour to the path 632 * 633 * @param oval The bounding oval to add as a closed contour to the path 634 * @param dir The direction to wind the oval's contour. Cannot be 635 * kUnknown_Direction. 636 */ 637 void addOval(const SkRect& oval, Direction dir = kCW_Direction); 638 639 /** 640 * Add a closed circle contour to the path 641 * 642 * @param x The x-coordinate of the center of a circle to add as a 643 * closed contour to the path 644 * @param y The y-coordinate of the center of a circle to add as a 645 * closed contour to the path 646 * @param radius The radius of a circle to add as a closed contour to the 647 * path 648 * @param dir The direction to wind the circle's contour. Cannot be 649 * kUnknown_Direction. 650 */ 651 void addCircle(SkScalar x, SkScalar y, SkScalar radius, 652 Direction dir = kCW_Direction); 653 654 /** Add the specified arc to the path as a new contour. 655 656 @param oval The bounds of oval used to define the size of the arc 657 @param startAngle Starting angle (in degrees) where the arc begins 658 @param sweepAngle Sweep angle (in degrees) measured clockwise 659 */ 660 void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); 661 662 /** 663 * Add a closed round-rectangle contour to the path 664 * @param rect The bounds of a round-rectangle to add as a closed contour 665 * @param rx The x-radius of the rounded corners on the round-rectangle 666 * @param ry The y-radius of the rounded corners on the round-rectangle 667 * @param dir The direction to wind the rectangle's contour. Cannot be 668 * kUnknown_Direction. 669 */ 670 void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 671 Direction dir = kCW_Direction); 672 673 /** 674 * Add a closed round-rectangle contour to the path. Each corner receives 675 * two radius values [X, Y]. The corners are ordered top-left, top-right, 676 * bottom-right, bottom-left. 677 * @param rect The bounds of a round-rectangle to add as a closed contour 678 * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner 679 * @param dir The direction to wind the rectangle's contour. Cannot be 680 * kUnknown_Direction. 681 * Note: The radii here now go through the same constraint handling as the 682 * SkRRect radii (i.e., either radii at a corner being 0 implies a 683 * sqaure corner and oversized radii are proportionally scaled down). 684 */ 685 void addRoundRect(const SkRect& rect, const SkScalar radii[], 686 Direction dir = kCW_Direction); 687 688 /** 689 * Add an SkRRect contour to the path 690 * @param rrect The rounded rect to add as a closed contour 691 * @param dir The winding direction for the new contour. Cannot be 692 * kUnknown_Direction. 693 */ 694 void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction); 695 696 /** 697 * Add a new contour made of just lines. This is just a fast version of 698 * the following: 699 * this->moveTo(pts[0]); 700 * for (int i = 1; i < count; ++i) { 701 * this->lineTo(pts[i]); 702 * } 703 * if (close) { 704 * this->close(); 705 * } 706 */ 707 void addPoly(const SkPoint pts[], int count, bool close); 708 709 /** Add a copy of src to the path, offset by (dx,dy) 710 @param src The path to add as a new contour 711 @param dx The amount to translate the path in X as it is added 712 @param dx The amount to translate the path in Y as it is added 713 */ 714 void addPath(const SkPath& src, SkScalar dx, SkScalar dy); 715 716 /** Add a copy of src to the path 717 */ 718 void addPath(const SkPath& src) { 719 SkMatrix m; 720 m.reset(); 721 this->addPath(src, m); 722 } 723 724 /** Add a copy of src to the path, transformed by matrix 725 @param src The path to add as a new contour 726 */ 727 void addPath(const SkPath& src, const SkMatrix& matrix); 728 729 /** 730 * Same as addPath(), but reverses the src input 731 */ 732 void reverseAddPath(const SkPath& src); 733 734 /** Offset the path by (dx,dy), returning true on success 735 736 @param dx The amount in the X direction to offset the entire path 737 @param dy The amount in the Y direction to offset the entire path 738 @param dst The translated path is written here 739 */ 740 void offset(SkScalar dx, SkScalar dy, SkPath* dst) const; 741 742 /** Offset the path by (dx,dy), returning true on success 743 744 @param dx The amount in the X direction to offset the entire path 745 @param dy The amount in the Y direction to offset the entire path 746 */ 747 void offset(SkScalar dx, SkScalar dy) { 748 this->offset(dx, dy, this); 749 } 750 751 /** Transform the points in this path by matrix, and write the answer into 752 dst. 753 754 @param matrix The matrix to apply to the path 755 @param dst The transformed path is written here 756 */ 757 void transform(const SkMatrix& matrix, SkPath* dst) const; 758 759 /** Transform the points in this path by matrix 760 761 @param matrix The matrix to apply to the path 762 */ 763 void transform(const SkMatrix& matrix) { 764 this->transform(matrix, this); 765 } 766 767 /** Return the last point on the path. If no points have been added, (0,0) 768 is returned. If there are no points, this returns false, otherwise it 769 returns true. 770 771 @param lastPt The last point on the path is returned here 772 */ 773 bool getLastPt(SkPoint* lastPt) const; 774 775 /** Set the last point on the path. If no points have been added, 776 moveTo(x,y) is automatically called. 777 778 @param x The new x-coordinate for the last point 779 @param y The new y-coordinate for the last point 780 */ 781 void setLastPt(SkScalar x, SkScalar y); 782 783 /** Set the last point on the path. If no points have been added, moveTo(p) 784 is automatically called. 785 786 @param p The new location for the last point 787 */ 788 void setLastPt(const SkPoint& p) { 789 this->setLastPt(p.fX, p.fY); 790 } 791 792 enum SegmentMask { 793 kLine_SegmentMask = 1 << 0, 794 kQuad_SegmentMask = 1 << 1, 795 kConic_SegmentMask = 1 << 2, 796 kCubic_SegmentMask = 1 << 3, 797 }; 798 799 /** 800 * Returns a mask, where each bit corresponding to a SegmentMask is 801 * set if the path contains 1 or more segments of that type. 802 * Returns 0 for an empty path (no segments). 803 */ 804 uint32_t getSegmentMasks() const { return fSegmentMask; } 805 806 enum Verb { 807 kMove_Verb, //!< iter.next returns 1 point 808 kLine_Verb, //!< iter.next returns 2 points 809 kQuad_Verb, //!< iter.next returns 3 points 810 kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight() 811 kCubic_Verb, //!< iter.next returns 4 points 812 kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt) 813 kDone_Verb, //!< iter.next returns 0 points 814 }; 815 816 /** Iterate through all of the segments (lines, quadratics, cubics) of 817 each contours in a path. 818 819 The iterator cleans up the segments along the way, removing degenerate 820 segments and adding close verbs where necessary. When the forceClose 821 argument is provided, each contour (as defined by a new starting 822 move command) will be completed with a close verb regardless of the 823 contour's contents. 824 */ 825 class SK_API Iter { 826 public: 827 Iter(); 828 Iter(const SkPath&, bool forceClose); 829 830 void setPath(const SkPath&, bool forceClose); 831 832 /** Return the next verb in this iteration of the path. When all 833 segments have been visited, return kDone_Verb. 834 835 @param pts The points representing the current verb and/or segment 836 @param doConsumeDegerates If true, first scan for segments that are 837 deemed degenerate (too short) and skip those. 838 @return The verb for the current segment 839 */ 840 Verb next(SkPoint pts[4], bool doConsumeDegerates = true) { 841 if (doConsumeDegerates) { 842 this->consumeDegenerateSegments(); 843 } 844 return this->doNext(pts); 845 } 846 847 /** 848 * Return the weight for the current conic. Only valid if the current 849 * segment return by next() was a conic. 850 */ 851 SkScalar conicWeight() const { return *fConicWeights; } 852 853 /** If next() returns kLine_Verb, then this query returns true if the 854 line was the result of a close() command (i.e. the end point is the 855 initial moveto for this contour). If next() returned a different 856 verb, this returns an undefined value. 857 858 @return If the last call to next() returned kLine_Verb, return true 859 if it was the result of an explicit close command. 860 */ 861 bool isCloseLine() const { return SkToBool(fCloseLine); } 862 863 /** Returns true if the current contour is closed (has a kClose_Verb) 864 @return true if the current contour is closed (has a kClose_Verb) 865 */ 866 bool isClosedContour() const; 867 868 private: 869 const SkPoint* fPts; 870 const uint8_t* fVerbs; 871 const uint8_t* fVerbStop; 872 const SkScalar* fConicWeights; 873 SkPoint fMoveTo; 874 SkPoint fLastPt; 875 SkBool8 fForceClose; 876 SkBool8 fNeedClose; 877 SkBool8 fCloseLine; 878 SkBool8 fSegmentState; 879 880 inline const SkPoint& cons_moveTo(); 881 Verb autoClose(SkPoint pts[2]); 882 void consumeDegenerateSegments(); 883 Verb doNext(SkPoint pts[4]); 884 }; 885 886 /** Iterate through the verbs in the path, providing the associated points. 887 */ 888 class SK_API RawIter { 889 public: 890 RawIter(); 891 RawIter(const SkPath&); 892 893 void setPath(const SkPath&); 894 895 /** Return the next verb in this iteration of the path. When all 896 segments have been visited, return kDone_Verb. 897 898 @param pts The points representing the current verb and/or segment 899 This must not be NULL. 900 @return The verb for the current segment 901 */ 902 Verb next(SkPoint pts[4]); 903 904 SkScalar conicWeight() const { return *fConicWeights; } 905 906 private: 907 const SkPoint* fPts; 908 const uint8_t* fVerbs; 909 const uint8_t* fVerbStop; 910 const SkScalar* fConicWeights; 911 SkPoint fMoveTo; 912 SkPoint fLastPt; 913 }; 914 915 /** 916 * Returns true if the point { x, y } is contained by the path, taking into 917 * account the FillType. 918 */ 919 bool contains(SkScalar x, SkScalar y) const; 920 921 void dump(bool forceClose, const char title[] = NULL) const; 922 void dump() const; 923 924 /** 925 * Write the region to the buffer, and return the number of bytes written. 926 * If buffer is NULL, it still returns the number of bytes. 927 */ 928 uint32_t writeToMemory(void* buffer) const; 929 /** 930 * Initialized the region from the buffer, returning the number 931 * of bytes actually read. 932 */ 933 uint32_t readFromMemory(const void* buffer); 934 935#ifdef SK_BUILD_FOR_ANDROID 936 uint32_t getGenerationID() const; 937 const SkPath* getSourcePath() const; 938 void setSourcePath(const SkPath* path); 939#endif 940 941 SkDEBUGCODE(void validate() const;) 942 943private: 944 enum SerializationOffsets { 945 kDirection_SerializationShift = 26, // requires 2 bits 946 kIsFinite_SerializationShift = 25, // requires 1 bit 947 kIsOval_SerializationShift = 24, // requires 1 bit 948 kConvexity_SerializationShift = 16, // requires 2 bits 949 kFillType_SerializationShift = 8, // requires 2 bits 950 kSegmentMask_SerializationShift = 0 // requires 4 bits 951 }; 952 953#if SK_DEBUG_PATH_REF 954public: 955 /** Debugging wrapper for SkAutoTUnref<SkPathRef> used to track owners (SkPaths) 956 of SkPathRefs */ 957 class PathRefDebugRef { 958 public: 959 PathRefDebugRef(SkPath* owner); 960 PathRefDebugRef(SkPathRef* pr, SkPath* owner); 961 ~PathRefDebugRef(); 962 void reset(SkPathRef* ref); 963 void swap(PathRefDebugRef* other); 964 SkPathRef* get() const; 965 SkAutoTUnref<SkPathRef>::BlockRefType *operator->() const; 966 operator SkPathRef*(); 967 private: 968 SkAutoTUnref<SkPathRef> fPathRef; 969 SkPath* fOwner; 970 }; 971 972private: 973 PathRefDebugRef fPathRef; 974#else 975 SkAutoTUnref<SkPathRef> fPathRef; 976#endif 977 978 mutable SkRect fBounds; 979 int fLastMoveToIndex; 980 uint8_t fFillType; 981 uint8_t fSegmentMask; 982 mutable uint8_t fBoundsIsDirty; 983 mutable uint8_t fConvexity; 984 mutable uint8_t fDirection; 985 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid 986 mutable SkBool8 fIsOval; 987#ifdef SK_BUILD_FOR_ANDROID 988 uint32_t fGenerationID; 989 const SkPath* fSourcePath; 990#endif 991 992 /** Resets all fields other than fPathRef to their initial 'empty' values. 993 * Assumes the caller has already emptied fPathRef. 994 * On Android increments fGenerationID without reseting it. 995 */ 996 void resetFields(); 997 998 /** Sets all fields other than fPathRef to the values in 'that'. 999 * Assumes the caller has already set fPathRef. 1000 * On Android increments fGenerationID without copying it. 1001 * On Android sets fSourcePath to NULL. 1002 */ 1003 void copyFields(const SkPath& that); 1004 1005 // called, if dirty, by getBounds() 1006 void computeBounds() const; 1007 1008 friend class Iter; 1009 1010 friend class SkPathStroker; 1011 /* Append the first contour of path, ignoring path's initial point. If no 1012 moveTo() call has been made for this contour, the first point is 1013 automatically set to (0,0). 1014 */ 1015 void pathTo(const SkPath& path); 1016 1017 /* Append, in reverse order, the first contour of path, ignoring path's 1018 last point. If no moveTo() call has been made for this contour, the 1019 first point is automatically set to (0,0). 1020 */ 1021 void reversePathTo(const SkPath&); 1022 1023 // called before we add points for lineTo, quadTo, cubicTo, checking to see 1024 // if we need to inject a leading moveTo first 1025 // 1026 // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0) 1027 // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo) 1028 // 1029 inline void injectMoveToIfNeeded(); 1030 1031 inline bool hasOnlyMoveTos() const; 1032 1033 Convexity internalGetConvexity() const; 1034 1035 bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, 1036 bool* isClosed, Direction* direction) const; 1037 1038 friend class SkAutoPathBoundsUpdate; 1039 friend class SkAutoDisableOvalCheck; 1040 friend class SkAutoDisableDirectionCheck; 1041 friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo 1042}; 1043 1044#endif 1045