SkPath.h revision 58190644c30e1c4aa8e527f3503c58f841e0fcf3
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkPath_DEFINED 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPath_DEFINED 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkInstCnt.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMatrix.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h" 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRefCnt.h" 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_BUILD_FOR_ANDROID 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GEN_ID_INC fGenerationID++ 2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#define GEN_ID_PTR_INC(ptr) (ptr)->fGenerationID++ 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GEN_ID_INC 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GEN_ID_PTR_INC(ptr) 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkReader32; 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkWriter32; 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkAutoPathBoundsUpdate; 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkString; 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkPathRef; 31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SkRRect; 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** \class SkPath 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru The SkPath class encapsulates compound (multiple contour) geometric paths 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru consisting of straight line segments, quadratic curves, and cubic curves. 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SK_API SkPath { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_DECLARE_INST_COUNT_ROOT(SkPath); 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPath(); 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPath(const SkPath&); 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ~SkPath(); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPath& operator=(const SkPath&); 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend SK_API bool operator==(const SkPath&, const SkPath&); 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend bool operator!=(const SkPath& a, const SkPath& b) { 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return !(a == b); 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum FillType { 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Specifies that "inside" is computed by a non-zero sum of signed 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru edge crossings 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kWinding_FillType, 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Specifies that "inside" is computed by an odd number of edge 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru crossings 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kEvenOdd_FillType, 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Same as Winding, but draws outside of the path, rather than inside 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kInverseWinding_FillType, 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Same as EvenOdd, but draws outside of the path, rather than inside 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kInverseEvenOdd_FillType 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the path's fill type. This is used to define how "inside" is 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru computed. The default value is kWinding_FillType. 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return the path's fill type 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru FillType getFillType() const { return (FillType)fFillType; } 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the path's fill type. This is used to define how "inside" is 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru computed. The default value is kWinding_FillType. 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param ft The new fill type for this path 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setFillType(FillType ft) { 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fFillType = SkToU8(ft); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GEN_ID_INC; 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns true if the filltype is one of the Inverse variants */ 88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); } 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Toggle between inverse and normal filltypes. This reverse the return 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * value of isInverseFillType() 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void toggleInverseFillType() { 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fFillType ^= 2; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru GEN_ID_INC; 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum Convexity { 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kUnknown_Convexity, 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kConvex_Convexity, 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kConcave_Convexity 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Return the path's convexity, as stored in the path. If it is currently unknown, 107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * then this function will attempt to compute the convexity (and cache the result). 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Convexity getConvexity() const { 110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if (kUnknown_Convexity != fConvexity) { 111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return static_cast<Convexity>(fConvexity); 112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } else { 113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return this->internalGetConvexity(); 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Return the currently cached value for convexity, even if that is set to 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * kUnknown_Convexity. Note: getConvexity() will automatically call 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * ComputeConvexity and cache its return value if the current setting is 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * kUnknown. 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; } 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Store a convexity setting in the path. There is no automatic check to 127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * see if this value actually agrees with the return value that would be 128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * computed by getConvexity(). 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Note: even if this is set to a "known" value, if the path is later 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * reset to kUnknown_Convexity. 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setConvexity(Convexity); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * DEPRECATED: use getConvexity() 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if the path is flagged as being convex. This is not a 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * confirmed by any analysis, it is just the value set earlier. 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isConvex() const { 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kConvex_Convexity == this->getConvexity(); 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * DEPRECATED: use setConvexity() 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Set the isConvex flag to true or false. Convex paths may draw faster if 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * this flag is set, though setting this to true on a path that is in fact 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * not convex can give undefined results when drawn. Paths default to 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * isConvex == false 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setIsConvex(bool isConvex) { 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity); 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns true if the path is an oval. 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param rect returns the bounding rect of this oval. It's a circle 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * if the height and width are the same. 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @return true if this path is an oval. 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Tracking whether a path is an oval is considered an 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * optimization for performance and so some paths that are in 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * fact ovals can report false. 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isOval(SkRect* rect) const; 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Clear any lines and curves from the path, making it empty. This frees up 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru internal storage associated with those segments. 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru This does NOT change the fill-type setting nor isConvex 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void reset(); 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Similar to reset(), in that all lines and curves are removed from the 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru path. However, any internal storage for those lines/curves is retained, 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru making reuse of the path potentially faster. 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru This does NOT change the fill-type setting nor isConvex 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rewind(); 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns true if the path is empty (contains no lines or curves) 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the path is empty (contains no lines or curves) 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isEmpty() const; 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if all of the points in this path are finite, meaning there 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * are no infinities and no NaNs. 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isFinite() const { 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fBoundsIsDirty) { 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->computeBounds(); 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkToBool(fIsFinite); 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Test a line for zero length 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the line is of zero length; otherwise false. 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) { 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return p1.equalsWithinTolerance(p2); 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Test a quad for zero length 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the quad is of zero length; otherwise false. 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPoint& p3) { 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return p1.equalsWithinTolerance(p2) && 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru p2.equalsWithinTolerance(p3); 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Test a cubic curve for zero length 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the cubic is of zero length; otherwise false. 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPoint& p3, const SkPoint& p4) { 22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return p1.equalsWithinTolerance(p2) && 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru p2.equalsWithinTolerance(p3) && 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru p3.equalsWithinTolerance(p4); 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if the path specifies a single line (i.e. it contains just 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * points in line[] to the end-points of the line. If the path is not a 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * line, returns false and ignores line[]. 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isLine(SkPoint line[2]) const; 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns true if the path specifies a rectangle. If so, and if rect is 23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru not null, set rect to the bounds of the path. If the path does not 23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru specify a rectangle, return false and ignore rect. 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param rect If not null, returns the bounds of the path if it specifies 24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru a rectangle 24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the path specifies a rectangle 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isRect(SkRect* rect) const; 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the number of points in the path 24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int countPoints() const; 24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the point at the specified index. If the index is out of range 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (i.e. is not 0 <= index < countPoints()) then the returned coordinates 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru will be (0,0) 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint getPoint(int index) const; 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns the number of points in the path. Up to max points are copied. 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param points If not null, receives up to max points 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param max The maximum number of points to copy into points 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return the actual number of points in the path 26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int getPoints(SkPoint points[], int max) const; 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the number of verbs in the path 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int countVerbs() const; 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns the number of verbs in the path. Up to max verbs are copied. The 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru verbs are copied as one byte per verb. 26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param verbs If not null, receives up to max verbs 27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param max The maximum number of verbs to copy into verbs 27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return the actual number of verbs in the path 27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int getVerbs(uint8_t verbs[], int max) const; 27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //! Swap contents of this and other. Guaranteed not to throw 27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void swap(SkPath& other); 27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns the bounds of the path's points. If the path contains 0 or 1 28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points, the bounds is set to (0,0,0,0), and isEmpty() will return true. 28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Note: this bounds may be larger than the actual shape, since curves 28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do not extend as far as their control points. 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkRect& getBounds() const { 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fBoundsIsDirty) { 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->computeBounds(); 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return fBounds; 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Calling this will, if the internal cache of the bounds is out of date, 292363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger update it so that subsequent calls to getBounds will be instantaneous. 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru This also means that any copies or simple transformations of the path 29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru will inherit the cached bounds. 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void updateBoundsCache() const { 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // for now, just calling getBounds() is sufficient 29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->getBounds(); 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 301363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 302363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Does a conservative test to see whether a rectangle is inside a path. Currently it only 303363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * will ever return true for single convex contour paths. The empty-status of the rect is not 304363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * considered (e.g. a rect that is a point can be inside a path). Points or line segments where 305363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * the rect edge touches the path border are not considered containment violations. 306363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 307363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bool conservativelyContainsRect(const SkRect& rect) const; 308363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Construction methods 31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Hint to the path to prepare for adding more points. This can allow the 31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru path to more efficiently grow its storage. 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param extraPtCount The number of extra points the path should 31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru preallocate for. 31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void incReserve(unsigned extraPtCount); 31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the beginning of the next contour to the point (x,y). 32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x The x-coordinate of the start of a new contour 32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y The y-coordinate of the start of a new contour 32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void moveTo(SkScalar x, SkScalar y); 32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the beginning of the next contour to the point 32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p The start of a new contour 32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void moveTo(const SkPoint& p) { 33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->moveTo(p.fX, p.fY); 33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the beginning of the next contour relative to the last point on the 33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru previous contour. If there is no previous contour, this is treated the 33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru same as moveTo(). 33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount to add to the x-coordinate of the end of the 33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru previous contour, to specify the start of a new contour 34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy The amount to add to the y-coordinate of the end of the 34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru previous contour, to specify the start of a new contour 34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rMoveTo(SkScalar dx, SkScalar dy); 34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a line from the last point to the specified point (x,y). If no 34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru moveTo() call has been made for this contour, the first point is 34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru automatically set to (0,0). 34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x The x-coordinate of the end of a line 35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y The y-coordinate of the end of a line 35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void lineTo(SkScalar x, SkScalar y); 35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a line from the last point to the specified point. If no moveTo() 35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru call has been made for this contour, the first point is automatically 35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru set to (0,0). 35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p The end of a line 35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void lineTo(const SkPoint& p) { 36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->lineTo(p.fX, p.fY); 36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Same as lineTo, but the coordinates are considered relative to the last 36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru point on this contour. If there is no previous point, then a moveTo(0,0) 36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru is inserted automatically. 36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount to add to the x-coordinate of the previous point 36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru on this contour, to specify a line 37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy The amount to add to the y-coordinate of the previous point 37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru on this contour, to specify a line 37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rLineTo(SkScalar dx, SkScalar dy); 37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a quadratic bezier from the last point, approaching control point 37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for 37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, the first point is automatically set to (0,0). 37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x1 The x-coordinate of the control point on a quadratic curve 38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y1 The y-coordinate of the control point on a quadratic curve 38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x2 The x-coordinate of the end point on a quadratic curve 38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y2 The y-coordinate of the end point on a quadratic curve 38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2); 38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a quadratic bezier from the last point, approaching control point 38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru p1, and ending at p2. If no moveTo() call has been made for this 38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru contour, the first point is automatically set to (0,0). 38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p1 The control point on a quadratic curve 39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p2 The end point on a quadratic curve 39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void quadTo(const SkPoint& p1, const SkPoint& p2) { 39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY); 39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Same as quadTo, but the coordinates are considered relative to the last 39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru point on this contour. If there is no previous point, then a moveTo(0,0) 39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru is inserted automatically. 40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx1 The amount to add to the x-coordinate of the last point on 40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the control point of a quadratic curve 40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy1 The amount to add to the y-coordinate of the last point on 40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the control point of a quadratic curve 40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx2 The amount to add to the x-coordinate of the last point on 40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the end point of a quadratic curve 40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy2 The amount to add to the y-coordinate of the last point on 40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the end point of a quadratic curve 40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); 41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 41258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 41358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkScalar w); 41458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) { 41558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w); 41658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 41758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, 41858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkScalar w); 41958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a cubic bezier from the last point, approaching control points 42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been 42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru made for this contour, the first point is automatically set to (0,0). 42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x1 The x-coordinate of the 1st control point on a cubic curve 42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y1 The y-coordinate of the 1st control point on a cubic curve 42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x2 The x-coordinate of the 2nd control point on a cubic curve 42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y2 The y-coordinate of the 2nd control point on a cubic curve 42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x3 The x-coordinate of the end point on a cubic curve 42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y3 The y-coordinate of the end point on a cubic curve 43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar x3, SkScalar y3); 43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a cubic bezier from the last point, approaching control points p1 43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru and p2, and ending at p3. If no moveTo() call has been made for this 43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru contour, the first point is automatically set to (0,0). 43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p1 The 1st control point on a cubic curve 43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p2 The 2nd control point on a cubic curve 44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p3 The end point on a cubic curve 44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) { 44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY); 44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Same as cubicTo, but the coordinates are considered relative to the 44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru current point on this contour. If there is no previous point, then a 44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru moveTo(0,0) is inserted automatically. 44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx1 The amount to add to the x-coordinate of the last point on 45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the 1st control point of a cubic curve 45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy1 The amount to add to the y-coordinate of the last point on 45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the 1st control point of a cubic curve 45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx2 The amount to add to the x-coordinate of the last point on 45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the 2nd control point of a cubic curve 45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy2 The amount to add to the y-coordinate of the last point on 45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the 2nd control point of a cubic curve 45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx3 The amount to add to the x-coordinate of the last point on 45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the end point of a cubic curve 46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy3 The amount to add to the y-coordinate of the last point on 46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this contour, to specify the end point of a cubic curve 46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar x3, SkScalar y3); 46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Append the specified arc to the path as a new contour. If the start of 46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru the path is different from the path's current last point, then an 46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru automatic lineTo() is added to connect the current contour to the start 46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru of the arc. However, if the path is empty, then we call moveTo() with 47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru the first point of the arc. The sweep angle is treated mod 360. 47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param oval The bounding oval defining the shape and size of the arc 47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param startAngle Starting angle (in degrees) where the arc begins 47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param sweepAngle Sweep angle (in degrees) measured clockwise. This is 47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru treated mod 360. 47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param forceMoveTo If true, always begin a new contour with the arc 47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool forceMoveTo); 48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Append a line and arc to the current path. This is the same as the 48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PostScript call "arct". 48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar radius); 48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Append a line and arc to the current path. This is the same as the 48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru PostScript call "arct". 48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) { 49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius); 49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Close the current contour. If the current point is not equal to the 49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru first point of the contour, a line segment is automatically added. 49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void close(); 49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum Direction { 500363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** Direction either has not been or could not be computed */ 501363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kUnknown_Direction, 50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** clockwise direction for adding closed contours */ 50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kCW_Direction, 50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** counter-clockwise direction for adding closed contours */ 505363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kCCW_Direction, 50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 509363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Return the opposite of the specified direction. kUnknown is its own 510363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * opposite. 511363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger static Direction OppositeDirection(Direction dir) { 513363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger static const Direction gOppositeDir[] = { 514363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kUnknown_Direction, kCCW_Direction, kCW_Direction 515363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger }; 516363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return gOppositeDir[dir]; 517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 519363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 520363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Returns whether or not a fill type is inverted 521363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * 522363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kWinding_FillType -> false 523363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kEvenOdd_FillType -> false 524363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kInverseWinding_FillType -> true 525363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kInverseEvenOdd_FillType -> true 526363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 527363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger static bool IsInverseFillType(FillType fill) { 528363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch); 529363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch); 530363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch); 531363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch); 532363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return (fill & 2) != 0; 533363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 534363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 535363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 536363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Returns the equivalent non-inverted fill type to the given fill type 537363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * 538363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kWinding_FillType -> kWinding_FillType 539363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kEvenOdd_FillType -> kEvenOdd_FillType 540363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kInverseWinding_FillType -> kWinding_FillType 541363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kInverseEvenOdd_FillType -> kEvenOdd_FillType 542363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 543363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger static FillType ConvertToNonInverseFillType(FillType fill) { 544363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch); 545363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch); 546363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch); 547363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch); 548363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return (FillType)(fill & 1); 549363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 550363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 551363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Tries to quickly compute the direction of the first non-degenerate 55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * contour. If it can be computed, return true and set dir to that 55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * direction. If it cannot be (quickly) determined, return false and ignore 555363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * the dir parameter. If the direction was determined, it is cached to make 556363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * subsequent calls return quickly. 55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool cheapComputeDirection(Direction* dir) const; 55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if the path's direction can be computed via 56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * cheapComputDirection() and if that computed direction matches the 563363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * specified direction. If dir is kUnknown, returns true if the direction 564363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * cannot be computed. 56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool cheapIsDirection(Direction dir) const { 567363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger Direction computedDir = kUnknown_Direction; 568363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger (void)this->cheapComputeDirection(&computedDir); 569363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger return computedDir == dir; 57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 572363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** Returns true if the path specifies a rectangle. If so, and if isClosed is 573363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger not null, set isClosed to true if the path is closed. Also, if returning true 574363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger and direction is not null, return the rect direction. If the path does not 575363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger specify a rectangle, return false and ignore isClosed and direction. 576363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 577363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger @param isClosed If not null, set to true if the path is closed 578363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger @param direction If not null, set to the rectangle's direction 579363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger @return true if the path specifies a rectangle 58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 581363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bool isRect(bool* isClosed, Direction* direction) const; 58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger /** Returns true if the path specifies a pair of nested rectangles. If so, and if 5847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner 5857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger rectangle. If so, and dirs is not null, set dirs[0] to the direction of 5867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger the outer rectangle and dirs[1] to the direction of the inner rectangle. If 5877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger the path does not specify a pair of nested rectangles, return 5887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger false and ignore rect and dirs. 5897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger @param rect If not null, returns the path as a pair of nested rectangles 5917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger @param dirs If not null, returns the direction of the rects 5927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger @return true if the path describes a pair of nested rectangles 5937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */ 5947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const; 5957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 596363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 597363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed rectangle contour to the path 598363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param rect The rectangle to add as a closed contour to the path 599363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the rectangle's contour. Cannot be 600363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 601363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 602363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger void addRect(const SkRect& rect, Direction dir = kCW_Direction); 60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 604363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 605363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed rectangle contour to the path 606363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * 607363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param left The left side of a rectangle to add as a closed contour 608363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * to the path 609363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param top The top of a rectangle to add as a closed contour to the 610363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * path 611363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param right The right side of a rectangle to add as a closed contour 612363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * to the path 613363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param bottom The bottom of a rectangle to add as a closed contour to 614363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * the path 615363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the rectangle's contour. Cannot be 616363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 617363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, 61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Direction dir = kCW_Direction); 62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 621363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 622363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed oval contour to the path 623363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * 624363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param oval The bounding oval to add as a closed contour to the path 625363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the oval's contour. Cannot be 626363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 627363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addOval(const SkRect& oval, Direction dir = kCW_Direction); 62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 630363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 631363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed circle contour to the path 632363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * 633363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param x The x-coordinate of the center of a circle to add as a 634363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * closed contour to the path 635363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param y The y-coordinate of the center of a circle to add as a 636363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * closed contour to the path 637363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param radius The radius of a circle to add as a closed contour to the 638363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * path 639363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the circle's contour. Cannot be 640363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 641363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addCircle(SkScalar x, SkScalar y, SkScalar radius, 64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Direction dir = kCW_Direction); 64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add the specified arc to the path as a new contour. 64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param oval The bounds of oval used to define the size of the arc 64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param startAngle Starting angle (in degrees) where the arc begins 64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param sweepAngle Sweep angle (in degrees) measured clockwise 65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); 65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 653363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 654363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed round-rectangle contour to the path 655363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param rect The bounds of a round-rectangle to add as a closed contour 656363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param rx The x-radius of the rounded corners on the round-rectangle 657363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param ry The y-radius of the rounded corners on the round-rectangle 658363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the rectangle's contour. Cannot be 659363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 660363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Direction dir = kCW_Direction); 66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 664363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 665363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add a closed round-rectangle contour to the path. Each corner receives 666363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * two radius values [X, Y]. The corners are ordered top-left, top-right, 667363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * bottom-right, bottom-left. 668363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param rect The bounds of a round-rectangle to add as a closed contour 669363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner 670363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The direction to wind the rectangle's contour. Cannot be 671363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 672363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Note: The radii here now go through the same constraint handling as the 673363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * SkRRect radii (i.e., either radii at a corner being 0 implies a 674363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * sqaure corner and oversized radii are proportionally scaled down). 675363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addRoundRect(const SkRect& rect, const SkScalar radii[], 67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Direction dir = kCW_Direction); 67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 680363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Add an SkRRect contour to the path 681363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param rrect The rounded rect to add as a closed contour 682363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * @param dir The winding direction for the new contour. Cannot be 683363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * kUnknown_Direction. 684363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */ 685363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction); 686363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 687363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /** 68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Add a new contour made of just lines. This is just a fast version of 68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the following: 69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * this->moveTo(pts[0]); 69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * for (int i = 1; i < count; ++i) { 69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * this->lineTo(pts[i]); 69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * } 69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * if (close) { 69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * this->close(); 69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * } 69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addPoly(const SkPoint pts[], int count, bool close); 69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a copy of src to the path, offset by (dx,dy) 70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param src The path to add as a new contour 70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount to translate the path in X as it is added 70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount to translate the path in Y as it is added 70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addPath(const SkPath& src, SkScalar dx, SkScalar dy); 70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a copy of src to the path 70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addPath(const SkPath& src) { 71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkMatrix m; 71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru m.reset(); 71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->addPath(src, m); 71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Add a copy of src to the path, transformed by matrix 71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param src The path to add as a new contour 71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void addPath(const SkPath& src, const SkMatrix& matrix); 71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Same as addPath(), but reverses the src input 72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void reverseAddPath(const SkPath& src); 72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Offset the path by (dx,dy), returning true on success 72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount in the X direction to offset the entire path 72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy The amount in the Y direction to offset the entire path 72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dst The translated path is written here 73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void offset(SkScalar dx, SkScalar dy, SkPath* dst) const; 73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Offset the path by (dx,dy), returning true on success 73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dx The amount in the X direction to offset the entire path 73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dy The amount in the Y direction to offset the entire path 73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void offset(SkScalar dx, SkScalar dy) { 73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->offset(dx, dy, this); 74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Transform the points in this path by matrix, and write the answer into 74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst. 74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param matrix The matrix to apply to the path 74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param dst The transformed path is written here 74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void transform(const SkMatrix& matrix, SkPath* dst) const; 74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Transform the points in this path by matrix 75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param matrix The matrix to apply to the path 75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void transform(const SkMatrix& matrix) { 75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->transform(matrix, this); 75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the last point on the path. If no points have been added, (0,0) 75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru is returned. If there are no points, this returns false, otherwise it 76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru returns true. 76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param lastPt The last point on the path is returned here 76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool getLastPt(SkPoint* lastPt) const; 76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the last point on the path. If no points have been added, 76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru moveTo(x,y) is automatically called. 76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param x The new x-coordinate for the last point 77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param y The new y-coordinate for the last point 77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setLastPt(SkScalar x, SkScalar y); 77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Set the last point on the path. If no points have been added, moveTo(p) 77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru is automatically called. 77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param p The new location for the last point 77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setLastPt(const SkPoint& p) { 78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->setLastPt(p.fX, p.fY); 78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum SegmentMask { 78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kLine_SegmentMask = 1 << 0, 78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kQuad_SegmentMask = 1 << 1, 78658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kConic_SegmentMask = 1 << 2, 78758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kCubic_SegmentMask = 1 << 3, 78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns a mask, where each bit corresponding to a SegmentMask is 79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * set if the path contains 1 or more segments of that type. 79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns 0 for an empty path (no segments). 79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t getSegmentMasks() const { return fSegmentMask; } 79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum Verb { 79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kMove_Verb, //!< iter.next returns 1 point 79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kLine_Verb, //!< iter.next returns 2 points 80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kQuad_Verb, //!< iter.next returns 3 points 80158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight() 80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kCubic_Verb, //!< iter.next returns 4 points 80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt) 80458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kDone_Verb, //!< iter.next returns 0 points 80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Iterate through all of the segments (lines, quadratics, cubics) of 80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru each contours in a path. 80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru The iterator cleans up the segments along the way, removing degenerate 81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru segments and adding close verbs where necessary. When the forceClose 81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru argument is provided, each contour (as defined by a new starting 81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru move command) will be completed with a close verb regardless of the 81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru contour's contents. 81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru class SK_API Iter { 81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru public: 81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Iter(); 81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Iter(const SkPath&, bool forceClose); 82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setPath(const SkPath&, bool forceClose); 82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the next verb in this iteration of the path. When all 82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru segments have been visited, return kDone_Verb. 82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param pts The points representing the current verb and/or segment 82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param doConsumeDegerates If true, first scan for segments that are 82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru deemed degenerate (too short) and skip those. 82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return The verb for the current segment 83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Verb next(SkPoint pts[4], bool doConsumeDegerates = true) { 83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (doConsumeDegerates) { 83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->consumeDegenerateSegments(); 83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return this->doNext(pts); 83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 83858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger /** 83958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Return the weight for the current conic. Only valid if the current 84058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * segment return by next() was a conic. 84158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */ 84258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkScalar conicWeight() const { return *fConicWeights; } 84358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** If next() returns kLine_Verb, then this query returns true if the 84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru line was the result of a close() command (i.e. the end point is the 84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru initial moveto for this contour). If next() returned a different 84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru verb, this returns an undefined value. 84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return If the last call to next() returned kLine_Verb, return true 85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if it was the result of an explicit close command. 85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isCloseLine() const { return SkToBool(fCloseLine); } 85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Returns true if the current contour is closed (has a kClose_Verb) 85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return true if the current contour is closed (has a kClose_Verb) 85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isClosedContour() const; 85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru private: 86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPoint* fPts; 86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* fVerbs; 86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* fVerbStop; 86358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkScalar* fConicWeights; 86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint fMoveTo; 86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint fLastPt; 86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBool8 fForceClose; 86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBool8 fNeedClose; 86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBool8 fCloseLine; 86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBool8 fSegmentState; 87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru inline const SkPoint& cons_moveTo(); 87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Verb autoClose(SkPoint pts[2]); 87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void consumeDegenerateSegments(); 87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Verb doNext(SkPoint pts[4]); 87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Iterate through the verbs in the path, providing the associated points. 87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru class SK_API RawIter { 88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru public: 88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru RawIter(); 88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru RawIter(const SkPath&); 88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setPath(const SkPath&); 88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** Return the next verb in this iteration of the path. When all 88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru segments have been visited, return kDone_Verb. 88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @param pts The points representing the current verb and/or segment 89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru This must not be NULL. 89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru @return The verb for the current segment 89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Verb next(SkPoint pts[4]); 89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 89558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkScalar conicWeight() const { return *fConicWeights; } 89658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru private: 89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPoint* fPts; 89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* fVerbs; 90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* fVerbStop; 90158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkScalar* fConicWeights; 90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint fMoveTo; 90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint fLastPt; 90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns true if the point { x, y } is contained by the path, taking into 90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * account the FillType. 90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool contains(SkScalar x, SkScalar y) const; 91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void dump(bool forceClose, const char title[] = NULL) const; 91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void dump() const; 91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Write the region to the buffer, and return the number of bytes written. 91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * If buffer is NULL, it still returns the number of bytes. 91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t writeToMemory(void* buffer) const; 92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Initialized the region from the buffer, returning the number 92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * of bytes actually read. 92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t readFromMemory(const void* buffer); 92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_BUILD_FOR_ANDROID 92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t getGenerationID() const; 92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPath* getSourcePath() const; 92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void setSourcePath(const SkPath* path); 93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDEBUGCODE(void validate() const;) 93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum SerializationOffsets { 936363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kDirection_SerializationShift = 26, // requires 2 bits 937363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kIsFinite_SerializationShift = 25, // requires 1 bit 938363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kIsOval_SerializationShift = 24, // requires 1 bit 939363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kConvexity_SerializationShift = 16, // requires 2 bits 940363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger kFillType_SerializationShift = 8, // requires 2 bits 94158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kSegmentMask_SerializationShift = 0 // requires 4 bits 94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTUnref<SkPathRef> fPathRef; 94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mutable SkRect fBounds; 94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int fLastMoveToIndex; 94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t fFillType; 94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t fSegmentMask; 95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mutable uint8_t fBoundsIsDirty; 95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mutable uint8_t fConvexity; 952363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger mutable uint8_t fDirection; 95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mutable SkBool8 fIsFinite; // only meaningful if bounds are valid 95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru mutable SkBool8 fIsOval; 95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_BUILD_FOR_ANDROID 95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t fGenerationID; 95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPath* fSourcePath; 95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 96058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger /** Resets all fields other than fPathRef to their initial 'empty' values. 96158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Assumes the caller has already emptied fPathRef. 96258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * On Android increments fGenerationID without reseting it. 96358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */ 96458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void resetFields(); 96558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 96658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger /** Sets all fields other than fPathRef to the values in 'that'. 96758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Assumes the caller has already set fPathRef. 96858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * On Android increments fGenerationID without copying it. 96958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * On Android sets fSourcePath to NULL. 97058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */ 97158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void copyFields(const SkPath& that); 97258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // called, if dirty, by getBounds() 97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void computeBounds() const; 97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend class Iter; 97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend class SkPathStroker; 97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* Append the first contour of path, ignoring path's initial point. If no 98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru moveTo() call has been made for this contour, the first point is 98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru automatically set to (0,0). 98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void pathTo(const SkPath& path); 98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* Append, in reverse order, the first contour of path, ignoring path's 98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru last point. If no moveTo() call has been made for this contour, the 98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru first point is automatically set to (0,0). 98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void reversePathTo(const SkPath&); 99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // called before we add points for lineTo, quadTo, cubicTo, checking to see 99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if we need to inject a leading moveTo first 99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // 99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0) 99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo) 99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // 99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru inline void injectMoveToIfNeeded(); 99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru inline bool hasOnlyMoveTos() const; 100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1001363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger Convexity internalGetConvexity() const; 1002363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1003363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, 1004363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bool* isClosed, Direction* direction) const; 1005363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend class SkAutoPathBoundsUpdate; 100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend class SkAutoDisableOvalCheck; 1008363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger friend class SkAutoDisableDirectionCheck; 100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo 101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 1013