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