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