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