1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkPath_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPath_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1365a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com#include "SkInstCnt.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
15ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkPathRef.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTDArray.h"
171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#include "SkRefCnt.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19739456585a0cc52b335cd1c0a9fc6b01782a7f89reed@google.comclass SkReader32;
20739456585a0cc52b335cd1c0a9fc6b01782a7f89reed@google.comclass SkWriter32;
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoPathBoundsUpdate;
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkString;
234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comclass SkRRect;
2466a5d8bf13fe98baae268db0211e9c25e5ece7facaryclarkclass SkWStream;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkPath
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The SkPath class encapsulates compound (multiple contour) geometric paths
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    consisting of straight line segments, quadratic curves, and cubic curves.
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
317ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgclass SK_API SkPath {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3365a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com    SK_DECLARE_INST_COUNT_ROOT(SkPath);
3465a87cc13d6babcf12844cca244ca7cc5258cadcbsalomon@google.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath();
361ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    SkPath(const SkPath&);
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkPath();
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
391ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    SkPath& operator=(const SkPath&);
405e728450247c677343e072f37150967b36892573bsalomon@google.com    friend  SK_API bool operator==(const SkPath&, const SkPath&);
413abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com    friend bool operator!=(const SkPath& a, const SkPath& b) {
423abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com        return !(a == b);
433abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com    }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum FillType {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Specifies that "inside" is computed by a non-zero sum of signed
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            edge crossings
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kWinding_FillType,
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Specifies that "inside" is computed by an odd number of edge
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            crossings
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kEvenOdd_FillType,
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Same as Winding, but draws outside of the path, rather than inside
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kInverseWinding_FillType,
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Same as EvenOdd, but draws outside of the path, rather than inside
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com         */
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kInverseEvenOdd_FillType
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the path's fill type. This is used to define how "inside" is
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        computed. The default value is kWinding_FillType.
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return the path's fill type
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    FillType getFillType() const { return (FillType)fFillType; }
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the path's fill type. This is used to define how "inside" is
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        computed. The default value is kWinding_FillType.
71b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param ft The new fill type for this path
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
74f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void setFillType(FillType ft) {
75f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        fFillType = SkToU8(ft);
76f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    }
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the filltype is one of the Inverse variants */
795f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
81b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    /**
82b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Toggle between inverse and normal filltypes. This reverse the return
83b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  value of isInverseFillType()
84b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     */
85f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void toggleInverseFillType() {
86f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        fFillType ^= 2;
876b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    }
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8904863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    enum Convexity {
9004863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kUnknown_Convexity,
9104863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kConvex_Convexity,
9204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kConcave_Convexity
9304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    };
9404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
9504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
9630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  Return the path's convexity, as stored in the path. If it is currently unknown,
9730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  then this function will attempt to compute the convexity (and cache the result).
98b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     */
99b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    Convexity getConvexity() const {
10030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        if (kUnknown_Convexity != fConvexity) {
10130c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com            return static_cast<Convexity>(fConvexity);
10230c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        } else {
10330c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com            return this->internalGetConvexity();
104b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com        }
105b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    }
106b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com
107b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    /**
108b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Return the currently cached value for convexity, even if that is set to
109b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  kUnknown_Convexity. Note: getConvexity() will automatically call
110b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  ComputeConvexity and cache its return value if the current setting is
111b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  kUnknown.
11204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
113b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
11404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
11504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
11604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Store a convexity setting in the path. There is no automatic check to
11730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  see if this value actually agrees with the return value that would be
11830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  computed by getConvexity().
119b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *
120b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Note: even if this is set to a "known" value, if the path is later
121b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
122b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  reset to kUnknown_Convexity.
12304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
12404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    void setConvexity(Convexity);
12504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
12604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
12704863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Returns true if the path is flagged as being convex. This is not a
12804863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  confirmed by any analysis, it is just the value set earlier.
12904863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
13004863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    bool isConvex() const {
13104863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        return kConvex_Convexity == this->getConvexity();
13204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    }
13304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
13404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
13504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Set the isConvex flag to true or false. Convex paths may draw faster if
13604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  this flag is set, though setting this to true on a path that is in fact
13704863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  not convex can give undefined results when drawn. Paths default to
13804863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  isConvex == false
1396b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com     */
1404469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use setConvexity")
141f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void setIsConvex(bool isConvex) {
14204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
143f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    }
1446b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com
1456aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    /** Returns true if the path is an oval.
1466aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *
1476aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     * @param rect      returns the bounding rect of this oval. It's a circle
1486aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *                  if the height and width are the same.
1496aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *
1506aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     * @return true if this path is an oval.
1516aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              Tracking whether a path is an oval is considered an
1526aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              optimization for performance and so some paths that are in
1536aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              fact ovals can report false.
1546aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     */
155466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
1566aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Clear any lines and curves from the path, making it empty. This frees up
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        internal storage associated with those segments.
159cb8b0eeacfc2ff79a2b9721e3ef21d1efb507dc8mtklein@google.com        On Android, does not change fSourcePath.
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void reset();
162fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Similar to reset(), in that all lines and curves are removed from the
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path. However, any internal storage for those lines/curves is retained,
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        making reuse of the path potentially faster.
166cb8b0eeacfc2ff79a2b9721e3ef21d1efb507dc8mtklein@google.com        On Android, does not change fSourcePath.
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rewind();
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the path is empty (contains no lines or curves)
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return true if the path is empty (contains no lines or curves)
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
174ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool isEmpty() const {
175ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
176ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return 0 == fPathRef->countVerbs();
177ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1790bb18bb264b26afca45452910437c09445e23a3creed@google.com    /**
1800bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  Returns true if all of the points in this path are finite, meaning there
1810bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  are no infinities and no NaNs.
1820bb18bb264b26afca45452910437c09445e23a3creed@google.com     */
1830bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite() const {
184ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
185ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->isFinite();
1860bb18bb264b26afca45452910437c09445e23a3creed@google.com    }
1870bb18bb264b26afca45452910437c09445e23a3creed@google.com
1884da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a line for zero length
1894da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
1904da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the line is of zero length; otherwise false.
1914da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
1924da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) {
19394fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        return p1.equalsWithinTolerance(p2);
1944da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
1954da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
1964da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a quad for zero length
1974da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
1984da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the quad is of zero length; otherwise false.
1994da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
2004da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
2014da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org                                 const SkPoint& p3) {
20294fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        return p1.equalsWithinTolerance(p2) &&
20394fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p2.equalsWithinTolerance(p3);
2044da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
2054da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2064da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a cubic curve for zero length
2074da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2084da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the cubic is of zero length; otherwise false.
2094da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
2104da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
2114da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org                                  const SkPoint& p3, const SkPoint& p4) {
21294fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        return p1.equalsWithinTolerance(p2) &&
21394fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p2.equalsWithinTolerance(p3) &&
21494fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p3.equalsWithinTolerance(p4);
2154da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
2164da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2177e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com    /**
2187e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  Returns true if the path specifies a single line (i.e. it contains just
2197e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
2207e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  points in line[] to the end-points of the line. If the path is not a
2217e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  line, returns false and ignores line[].
2227e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     */
2237e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com    bool isLine(SkPoint line[2]) const;
2247e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the path specifies a rectangle. If so, and if rect is
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        not null, set rect to the bounds of the path. If the path does not
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        specify a rectangle, return false and ignore rect.
228fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param rect If not null, returns the bounds of the path if it specifies
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    a rectangle
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return true if the path specifies a rectangle
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2338fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    bool isRect(SkRect* rect) const;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
235d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    /** Return the number of points in the path
236d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com     */
2371dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int countPoints() const;
238d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com
239d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    /** Return the point at the specified index. If the index is out of range
240d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
241d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com         will be (0,0)
242d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com     */
243d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    SkPoint getPoint(int index) const;
244d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the number of points in the path. Up to max points are copied.
246fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param points If not null, receives up to max points
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param max The maximum number of points to copy into points
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return the actual number of points in the path
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int getPoints(SkPoint points[], int max) const;
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
253df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    /** Return the number of verbs in the path
254df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     */
2551dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int countVerbs() const;
256df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
257df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    /** Returns the number of verbs in the path. Up to max verbs are copied. The
258df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        verbs are copied as one byte per verb.
259fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
260df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @param verbs If not null, receives up to max verbs
261df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @param max The maximum number of verbs to copy into verbs
262df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @return the actual number of verbs in the path
263df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    */
264df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    int getVerbs(uint8_t verbs[], int max) const;
265df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //! Swap contents of this and other. Guaranteed not to throw
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void swap(SkPath& other);
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
269d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    /** Returns the bounds of the path's points. If the path contains 0 or 1
270d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
271d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        Note: this bounds may be larger than the actual shape, since curves
272d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        do not extend as far as their control points.
273d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    */
274d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    const SkRect& getBounds() const {
275ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->getBounds();
276d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Calling this will, if the internal cache of the bounds is out of date,
2799bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com        update it so that subsequent calls to getBounds will be instantaneous.
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This also means that any copies or simple transformations of the path
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        will inherit the cached bounds.
282d252db03d9650013b545ef9781fe993c07f8f314reed@android.com     */
283d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    void updateBoundsCache() const {
284d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        // for now, just calling getBounds() is sufficient
285d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        this->getBounds();
286d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2889bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com    /**
2899bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * Does a conservative test to see whether a rectangle is inside a path. Currently it only
2909bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * will ever return true for single convex contour paths. The empty-status of the rect is not
2919bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
2929bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * the rect edge touches the path border are not considered containment violations.
2939bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     */
2949bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com    bool conservativelyContainsRect(const SkRect& rect) const;
2959bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //  Construction methods
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Hint to the path to prepare for adding more points. This can allow the
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path to more efficiently grow its storage.
300fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param extraPtCount The number of extra points the path should
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            preallocate for.
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void incReserve(unsigned extraPtCount);
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour to the point (x,y).
307fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The x-coordinate of the start of a new contour
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The y-coordinate of the start of a new contour
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void moveTo(SkScalar x, SkScalar y);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour to the point
314fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The start of a new contour
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void moveTo(const SkPoint& p) {
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->moveTo(p.fX, p.fY);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour relative to the last point on the
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        previous contour. If there is no previous contour, this is treated the
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        same as moveTo().
324fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to add to the x-coordinate of the end of the
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    previous contour, to specify the start of a new contour
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy   The amount to add to the y-coordinate of the end of the
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    previous contour, to specify the start of a new contour
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rMoveTo(SkScalar dx, SkScalar dy);
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a line from the last point to the specified point (x,y). If no
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo() call has been made for this contour, the first point is
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        automatically set to (0,0).
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The x-coordinate of the end of a line
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The y-coordinate of the end of a line
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void lineTo(SkScalar x, SkScalar y);
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a line from the last point to the specified point. If no moveTo()
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        call has been made for this contour, the first point is automatically
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        set to (0,0).
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The end of a line
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void lineTo(const SkPoint& p) {
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->lineTo(p.fX, p.fY);
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as lineTo, but the coordinates are considered relative to the last
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        point on this contour. If there is no previous point, then a moveTo(0,0)
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is inserted automatically.
354fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to add to the x-coordinate of the previous point
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    on this contour, to specify a line
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy   The amount to add to the y-coordinate of the previous point
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    on this contour, to specify a line
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rLineTo(SkScalar dx, SkScalar dy);
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a quadratic bezier from the last point, approaching control point
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this contour, the first point is automatically set to (0,0).
365fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x1   The x-coordinate of the control point on a quadratic curve
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y1   The y-coordinate of the control point on a quadratic curve
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x2   The x-coordinate of the end point on a quadratic curve
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y2   The y-coordinate of the end point on a quadratic curve
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a quadratic bezier from the last point, approaching control point
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        p1, and ending at p2. If no moveTo() call has been made for this
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        contour, the first point is automatically set to (0,0).
376fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p1   The control point on a quadratic curve
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p2   The end point on a quadratic curve
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void quadTo(const SkPoint& p1, const SkPoint& p2) {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as quadTo, but the coordinates are considered relative to the last
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        point on this contour. If there is no previous point, then a moveTo(0,0)
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is inserted automatically.
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx1   The amount to add to the x-coordinate of the last point on
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the control point of a quadratic curve
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy1   The amount to add to the y-coordinate of the last point on
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the control point of a quadratic curve
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx2   The amount to add to the x-coordinate of the last point on
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a quadratic curve
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy2   The amount to add to the y-coordinate of the last point on
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a quadratic curve
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
399277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
400277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com                 SkScalar w);
401277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
402277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
403277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    }
404277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
405277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com                  SkScalar w);
40626da7f00aedba107d4b3e382283034e265db09b6skia.committer@gmail.com
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a cubic bezier from the last point, approaching control points
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        made for this contour, the first point is automatically set to (0,0).
410fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x1   The x-coordinate of the 1st control point on a cubic curve
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y1   The y-coordinate of the 1st control point on a cubic curve
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x2   The x-coordinate of the 2nd control point on a cubic curve
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y2   The y-coordinate of the 2nd control point on a cubic curve
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x3   The x-coordinate of the end point on a cubic curve
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y3   The y-coordinate of the end point on a cubic curve
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkScalar x3, SkScalar y3);
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a cubic bezier from the last point, approaching control points p1
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and p2, and ending at p3. If no moveTo() call has been made for this
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        contour, the first point is automatically set to (0,0).
424fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p1   The 1st control point on a cubic curve
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p2   The 2nd control point on a cubic curve
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p3   The end point on a cubic curve
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as cubicTo, but the coordinates are considered relative to the
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        current point on this contour. If there is no previous point, then a
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo(0,0) is inserted automatically.
436fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx1   The amount to add to the x-coordinate of the last point on
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 1st control point of a cubic curve
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy1   The amount to add to the y-coordinate of the last point on
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 1st control point of a cubic curve
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx2   The amount to add to the x-coordinate of the last point on
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 2nd control point of a cubic curve
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy2   The amount to add to the y-coordinate of the last point on
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 2nd control point of a cubic curve
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx3   The amount to add to the x-coordinate of the last point on
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a cubic curve
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy3   The amount to add to the y-coordinate of the last point on
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a cubic curve
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4506b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4516b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com                  SkScalar x3, SkScalar y3);
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Append the specified arc to the path as a new contour. If the start of
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the path is different from the path's current last point, then an
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        automatic lineTo() is added to connect the current contour to the start
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        of the arc. However, if the path is empty, then we call moveTo() with
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the first point of the arc. The sweep angle is treated mod 360.
458fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param oval The bounding oval defining the shape and size of the arc
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param startAngle Starting angle (in degrees) where the arc begins
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          treated mod 360.
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param forceMoveTo If true, always begin a new contour with the arc
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4656b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
4666b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com               bool forceMoveTo);
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Append a line and arc to the current path. This is the same as the
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        PostScript call "arct".
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com               SkScalar radius);
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Append a line and arc to the current path. This is the same as the
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        PostScript call "arct".
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Close the current contour. If the current point is not equal to the
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        first point of the contour, a line segment is automatically added.
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void close();
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4868fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    enum Direction {
4878fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        /** Direction either has not been or could not be computed */
4888fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        kUnknown_Direction,
4898fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        /** clockwise direction for adding closed contours */
4908fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        kCW_Direction,
4918fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        /** counter-clockwise direction for adding closed contours */
4928fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        kCCW_Direction,
4938fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    };
4948fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
495a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
496a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Return the opposite of the specified direction. kUnknown is its own
497a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  opposite.
498a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
49930c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    static Direction OppositeDirection(Direction dir) {
500a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        static const Direction gOppositeDir[] = {
501a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com            kUnknown_Direction, kCCW_Direction, kCW_Direction
502a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        };
503a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        return gOppositeDir[dir];
50430c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    }
50530c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com
50669a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com    /**
50712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     *  Returns whether or not a fill type is inverted
5085f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *
5095f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kWinding_FillType        -> false
5105f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kEvenOdd_FillType        -> false
5115f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseWinding_FillType -> true
5125f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseEvenOdd_FillType -> true
51312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     */
5145f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    static bool IsInverseFillType(FillType fill) {
51512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
51612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
51712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
51812b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
51912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        return (fill & 2) != 0;
52012b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    }
52112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com
52212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    /**
52312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     *  Returns the equivalent non-inverted fill type to the given fill type
5245f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *
5255f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kWinding_FillType        -> kWinding_FillType
5265f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kEvenOdd_FillType        -> kEvenOdd_FillType
5275f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseWinding_FillType -> kWinding_FillType
5285f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
52912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     */
5305f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    static FillType ConvertToNonInverseFillType(FillType fill) {
53112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
53212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
53312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
53412b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
53512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        return (FillType)(fill & 1);
53612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    }
53712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com
53812b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    /**
53969a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     *  Tries to quickly compute the direction of the first non-degenerate
54069a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     *  contour. If it can be computed, return true and set dir to that
54169a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     *  direction. If it cannot be (quickly) determined, return false and ignore
54230c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  the dir parameter. If the direction was determined, it is cached to make
54330c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  subsequent calls return quickly.
54469a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     */
54569a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com    bool cheapComputeDirection(Direction* dir) const;
54669a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com
54769a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com    /**
54869a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     *  Returns true if the path's direction can be computed via
54969a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     *  cheapComputDirection() and if that computed direction matches the
550a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  specified direction. If dir is kUnknown, returns true if the direction
551a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  cannot be computed.
55269a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com     */
55369a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com    bool cheapIsDirection(Direction dir) const {
554a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        Direction computedDir = kUnknown_Direction;
555a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        (void)this->cheapComputeDirection(&computedDir);
556a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com        return computedDir == dir;
55769a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com    }
55869a9943b67cc52c24beac853c6f8865dcb197b85reed@google.com
559c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org    enum PathAsRect {
560c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        /** The path can not draw the same as its bounds. */
561c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        kNone_PathAsRect,
562c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        /** The path draws the same as its bounds when filled. */
563c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        kFill_PathAsRect,
5647e90e8dbb96f2084f7dd4a6a20cb4b880b362438commit-bot@chromium.org        /** The path draws the same as its bounds when stroked or filled. */
5657e90e8dbb96f2084f7dd4a6a20cb4b880b362438commit-bot@chromium.org        kStroke_PathAsRect,
566c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org    };
567c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org
568c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org    /** Returns kFill_PathAsRect or kStroke_PathAsRect if drawing the path (either filled or
569c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        stroked) will be equivalent to filling/stroking the path's bounding rect. If
570c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        either is true, and direction is not null, sets the direction of the contour. If the
571c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        path is not drawn equivalent to a rect, returns kNone_PathAsRect and ignores direction.
572c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org
573c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        @param direction If not null, set to the contour's direction when it is drawn as a rect
574c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org        @return the path's PathAsRect type
575c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org     */
576c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org    PathAsRect asRect(Direction* direction = NULL) const;
577c2abd54edadf94bb86e1635a3515089e4a6a8eeecommit-bot@chromium.org
5788fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    /** Returns true if the path specifies a rectangle. If so, and if isClosed is
5798fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        not null, set isClosed to true if the path is closed. Also, if returning true
5808fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        and direction is not null, return the rect direction. If the path does not
5818fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        specify a rectangle, return false and ignore isClosed and direction.
5828fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
5838fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param isClosed If not null, set to true if the path is closed
5848fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param direction If not null, set to the rectangle's direction
5858fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @return true if the path specifies a rectangle
5868fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    */
5878fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    bool isRect(bool* isClosed, Direction* direction) const;
5888fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
5898fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    /** Returns true if the path specifies a pair of nested rectangles. If so, and if
5908fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
5918fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        rectangle. If so, and dirs is not null, set dirs[0] to the direction of
5928fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        the outer rectangle and dirs[1] to the direction of the inner rectangle. If
5938fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        the path does not specify a pair of nested rectangles, return
5948fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        false and ignore rect and dirs.
5958fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
5968fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param rect If not null, returns the path as a pair of nested rectangles
5978fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param dirs If not null, returns the direction of the rects
5988fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @return true if the path describes a pair of nested rectangles
5998fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    */
6008fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
6018fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
602a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
603a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed rectangle contour to the path
604a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The rectangle to add as a closed contour to the path
605a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the rectangle's contour. Cannot be
606a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
607a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
608ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void addRect(const SkRect& rect, Direction dir = kCW_Direction);
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
610a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
611a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed rectangle contour to the path
612a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
613a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param left     The left side of a rectangle to add as a closed contour
614a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  to the path
615a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param top      The top of a rectangle to add as a closed contour to the
616a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  path
617a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param right    The right side of a rectangle to add as a closed contour
618a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  to the path
619a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param bottom   The bottom of a rectangle to add as a closed contour to
620a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  the path
621a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the rectangle's contour. Cannot be
622a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
623a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 Direction dir = kCW_Direction);
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
627a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
628a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed oval contour to the path
629a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
630a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param oval The bounding oval to add as a closed contour to the path
631a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the oval's contour. Cannot be
632a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
633a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
636a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
637a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed circle contour to the path
638a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
639a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param x        The x-coordinate of the center of a circle to add as a
640a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  closed contour to the path
641a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param y        The y-coordinate of the center of a circle to add as a
642a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  closed contour to the path
643a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param radius   The radius of a circle to add as a closed contour to the
644a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  path
645a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the circle's contour. Cannot be
646a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
647a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                   Direction dir = kCW_Direction);
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add the specified arc to the path as a new contour.
652fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param oval The bounds of oval used to define the size of the arc
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param startAngle Starting angle (in degrees) where the arc begins
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param sweepAngle Sweep angle (in degrees) measured clockwise
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
659a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
660a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed round-rectangle contour to the path
661a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The bounds of a round-rectangle to add as a closed contour
662a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rx   The x-radius of the rounded corners on the round-rectangle
663a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param ry   The y-radius of the rounded corners on the round-rectangle
664a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the rectangle's contour. Cannot be
665a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
666a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
667ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
668ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com                      Direction dir = kCW_Direction);
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
670a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
671a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed round-rectangle contour to the path. Each corner receives
672a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  two radius values [X, Y]. The corners are ordered top-left, top-right,
673a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  bottom-right, bottom-left.
674a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The bounds of a round-rectangle to add as a closed contour
675a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
676a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param dir  The direction to wind the rectangle's contour. Cannot be
677a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *              kUnknown_Direction.
6784e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     * Note: The radii here now go through the same constraint handling as the
6794e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *       SkRRect radii (i.e., either radii at a corner being 0 implies a
6804e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *       sqaure corner and oversized radii are proportionally scaled down).
681a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addRoundRect(const SkRect& rect, const SkScalar radii[],
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                      Direction dir = kCW_Direction);
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
685744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com    /**
6864e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *  Add an SkRRect contour to the path
6874e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *  @param rrect The rounded rect to add as a closed contour
6884e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *  @param dir   The winding direction for the new contour. Cannot be
6894e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *               kUnknown_Direction.
6904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     */
6914e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
6924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
6934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    /**
694744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *  Add a new contour made of just lines. This is just a fast version of
695744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *  the following:
696744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      this->moveTo(pts[0]);
697744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      for (int i = 1; i < count; ++i) {
698744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *          this->lineTo(pts[i]);
699744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      }
700744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      if (close) {
701744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *          this->close();
702744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      }
703744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     */
704744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com    void addPoly(const SkPoint pts[], int count, bool close);
705744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com
70614747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    enum AddPathMode {
70714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        /** Source path contours are added as new contours.
70814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        */
70914747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        kAppend_AddPathMode,
71014747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        /** Path is added by extending the last contour of the destination path
71114747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            with the first contour of the source path. If the last contour of
712877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com            the destination path is closed, then it will not be extended.
71314747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            Instead, the start of source path will be extended by a straight
71414747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            line to the end point of the destination path.
71514747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        */
716877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com        kExtend_AddPathMode
71714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    };
71814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path, offset by (dx,dy)
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param src  The path to add as a new contour
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to translate the path in X as it is added
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to translate the path in Y as it is added
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
72414747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
72514747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org                 AddPathMode mode = kAppend_AddPathMode);
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
72914747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkMatrix m;
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        m.reset();
73214747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        this->addPath(src, m, mode);
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path, transformed by matrix
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param src  The path to add as a new contour
73714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        @param matrix  Transform applied to src
73814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        @param mode  Determines how path is added
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
74014747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
74263d73749fbe36491403ea521005fd298dc70a94creed@google.com    /**
74363d73749fbe36491403ea521005fd298dc70a94creed@google.com     *  Same as addPath(), but reverses the src input
74463d73749fbe36491403ea521005fd298dc70a94creed@google.com     */
74563d73749fbe36491403ea521005fd298dc70a94creed@google.com    void reverseAddPath(const SkPath& src);
74663d73749fbe36491403ea521005fd298dc70a94creed@google.com
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset the path by (dx,dy), returning true on success
748fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dx   The amount in the X direction to offset the entire path
750fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dy   The amount in the Y direction to offset the entire path
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dst  The translated path is written here
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset the path by (dx,dy), returning true on success
756fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
757fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dx   The amount in the X direction to offset the entire path
758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dy   The amount in the Y direction to offset the entire path
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void offset(SkScalar dx, SkScalar dy) {
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->offset(dx, dy, this);
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Transform the points in this path by matrix, and write the answer into
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst.
766fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param matrix   The matrix to apply to the path
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dst      The transformed path is written here
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void transform(const SkMatrix& matrix, SkPath* dst) const;
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Transform the points in this path by matrix
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param matrix The matrix to apply to the path
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void transform(const SkMatrix& matrix) {
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->transform(matrix, this);
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the last point on the path. If no points have been added, (0,0)
781294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com        is returned. If there are no points, this returns false, otherwise it
782294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com        returns true.
783fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param lastPt   The last point on the path is returned here
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
786294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com    bool getLastPt(SkPoint* lastPt) const;
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the last point on the path. If no points have been added,
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo(x,y) is automatically called.
790fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The new x-coordinate for the last point
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The new y-coordinate for the last point
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setLastPt(SkScalar x, SkScalar y);
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the last point on the path. If no points have been added, moveTo(p)
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is automatically called.
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The new location for the last point
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setLastPt(const SkPoint& p) {
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->setLastPt(p.fX, p.fY);
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
80510296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    enum SegmentMask {
80610296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com        kLine_SegmentMask   = 1 << 0,
80710296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com        kQuad_SegmentMask   = 1 << 1,
808277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kConic_SegmentMask  = 1 << 2,
809277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kCubic_SegmentMask  = 1 << 3,
81010296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    };
81110296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com
81210296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    /**
81310296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  Returns a mask, where each bit corresponding to a SegmentMask is
81410296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  set if the path contains 1 or more segments of that type.
81510296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  Returns 0 for an empty path (no segments).
81610296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     */
8176b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
81810296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum Verb {
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kMove_Verb,     //!< iter.next returns 1 point
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kLine_Verb,     //!< iter.next returns 2 points
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kQuad_Verb,     //!< iter.next returns 3 points
823277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kCubic_Verb,    //!< iter.next returns 4 points
825b3b8dfa31326c51dab8b5ed569e19ee715582d1bbsalomon@google.com        kClose_Verb,    //!< iter.next returns 1 point (contour's moveTo pt)
826277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kDone_Verb,     //!< iter.next returns 0 points
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Iterate through all of the segments (lines, quadratics, cubics) of
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        each contours in a path.
83172785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org
83272785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        The iterator cleans up the segments along the way, removing degenerate
83372785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        segments and adding close verbs where necessary. When the forceClose
83472785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        argument is provided, each contour (as defined by a new starting
83572785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        move command) will be completed with a close verb regardless of the
83672785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        contour's contents.
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8387ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.org    class SK_API Iter {
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    public:
84072785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        Iter();
84172785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        Iter(const SkPath&, bool forceClose);
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void setPath(const SkPath&, bool forceClose);
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Return the next verb in this iteration of the path. When all
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            segments have been visited, return kDone_Verb.
847b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @param  pts The points representing the current verb and/or segment
8494a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            @param doConsumeDegerates If true, first scan for segments that are
8504a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com                   deemed degenerate (too short) and skip those.
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return The verb for the current segment
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
8534a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
8544a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            if (doConsumeDegerates) {
8554a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com                this->consumeDegenerateSegments();
8564a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            }
8574a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            return this->doNext(pts);
8584a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        }
8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
860277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        /**
861277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         *  Return the weight for the current conic. Only valid if the current
862277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         *  segment return by next() was a conic.
863277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         */
864277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        SkScalar conicWeight() const { return *fConicWeights; }
865277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** If next() returns kLine_Verb, then this query returns true if the
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            line was the result of a close() command (i.e. the end point is the
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            initial moveto for this contour). If next() returned a different
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            verb, this returns an undefined value.
870b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return If the last call to next() returned kLine_Verb, return true
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if it was the result of an explicit close command.
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool isCloseLine() const { return SkToBool(fCloseLine); }
875b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Returns true if the current contour is closed (has a kClose_Verb)
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return true if the current contour is closed (has a kClose_Verb)
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool isClosedContour() const;
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    private:
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPoint*  fPts;
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  fVerbs;
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  fVerbStop;
885277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        const SkScalar* fConicWeights;
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint         fMoveTo;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint         fLastPt;
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fForceClose;
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fNeedClose;
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fCloseLine;
891b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org        SkBool8         fSegmentState;
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8939e25dbf589539dd44244bc2581590bd7591e17a2reed@google.com        inline const SkPoint& cons_moveTo();
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Verb autoClose(SkPoint pts[2]);
8954da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        void consumeDegenerateSegments();
8964a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        Verb doNext(SkPoint pts[4]);
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8996630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    /** Iterate through the verbs in the path, providing the associated points.
9006630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    */
9016630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    class SK_API RawIter {
9026630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    public:
9036630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        RawIter();
9046630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        RawIter(const SkPath&);
9056630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
9066630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        void setPath(const SkPath&);
9076630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
9086630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        /** Return the next verb in this iteration of the path. When all
9096630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            segments have been visited, return kDone_Verb.
910fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9116630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            @param  pts The points representing the current verb and/or segment
912f6d3c5aa5f93e4c3cc7a7aebf014e960cf837783bsalomon@google.com                        This must not be NULL.
9136630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            @return The verb for the current segment
9146630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        */
9156630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        Verb next(SkPoint pts[4]);
9166630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
917277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        SkScalar conicWeight() const { return *fConicWeights; }
918277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
9196630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    private:
9206630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        const SkPoint*  fPts;
9216630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        const uint8_t*  fVerbs;
9226630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        const uint8_t*  fVerbStop;
923277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        const SkScalar* fConicWeights;
9246630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        SkPoint         fMoveTo;
9256630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        SkPoint         fLastPt;
9266630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    };
9276630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
928bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org    /**
929bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     *  Returns true if the point { x, y } is contained by the path, taking into
930bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     *  account the FillType.
931bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     */
932bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org    bool contains(SkScalar x, SkScalar y) const;
933bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org
934e956259c5a4f71768afb34ec032eaed49dcbe9f2caryclark    void dump(SkWStream* , bool forceClose, bool dumpAsHex) const;
935e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com    void dump() const;
936e956259c5a4f71768afb34ec032eaed49dcbe9f2caryclark    void dumpHex() const;
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
93894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    /**
9394faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *  Write the path to the buffer, and return the number of bytes written.
94094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     *  If buffer is NULL, it still returns the number of bytes.
94194e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     */
9424faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t writeToMemory(void* buffer) const;
94394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    /**
9444faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * Initializes the path from the buffer
9454faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *
9464faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param buffer Memory to read from
9474faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param length Amount of memory available in the buffer
9484faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @return number of bytes read (must be a multiple of 4) or
9494faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *         0 if there was not enough memory available
95094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     */
9514faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t readFromMemory(const void* buffer, size_t length);
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9531ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    /** Returns a non-zero, globally unique value corresponding to the set of verbs
9541ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org        and points in the path (but not the fill type [except on Android skbug.com/1762]).
9557ed98df9ba14bdb58e381508eb0505c963a4b6dbskia.committer@gmail.com        Each time the path is modified, a different generation ID will be returned.
9561ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    */
9577101abe5b37d82ea222e971a42615a97a2419edbrobertphillips@google.com    uint32_t getGenerationID() const;
9581ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org
9591ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
9601ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
961e63793a2c8d2871bf7d95195be7b93ff669688d7djsollen@google.com    const SkPath* getSourcePath() const;
962e63793a2c8d2871bf7d95195be7b93ff669688d7djsollen@google.com    void setSourcePath(const SkPath* path);
9631ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org#else
9641ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    static const int kPathRefGenIDBitCnt = 32;
965f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
966f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(void validate() const;)
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
97001ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com    enum SerializationOffsets {
971fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org        // 1 free bit at 29
97211e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com        kUnused1_SerializationShift = 28,    // 1 free bit
97330c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        kDirection_SerializationShift = 26, // requires 2 bits
97411e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com        kUnused2_SerializationShift = 25,    // 1 free bit
975fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org        // 1 free bit at 24
976ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        kConvexity_SerializationShift = 16, // requires 8 bits
977ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        kFillType_SerializationShift = 8,   // requires 8 bits
978fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org        // 8 free bits at 0
97901ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com    };
98001ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com
981ae09f2dc3fb1e8a8db99b214c8a71d0b9613a856bsalomon@google.com    SkAutoTUnref<SkPathRef> fPathRef;
982ae09f2dc3fb1e8a8db99b214c8a71d0b9613a856bsalomon@google.com
9835e1a7f2cc621d357da5c62a7bc4ef750d94b96f3commit-bot@chromium.org    int                 fLastMoveToIndex;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t             fFillType;
985b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    mutable uint8_t     fConvexity;
98630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    mutable uint8_t     fDirection;
98756c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
988e63793a2c8d2871bf7d95195be7b93ff669688d7djsollen@google.com    const SkPath*       fSourcePath;
989f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
991a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    /** Resets all fields other than fPathRef to their initial 'empty' values.
992a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  Assumes the caller has already emptied fPathRef.
993a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  On Android increments fGenerationID without reseting it.
994a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     */
995a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    void resetFields();
996a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com
997a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    /** Sets all fields other than fPathRef to the values in 'that'.
998a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  Assumes the caller has already set fPathRef.
9999c9d4a70028ef8dc33a46cfc0b22e254443effe3mtklein@google.com     *  Doesn't change fGenerationID or fSourcePath on Android.
1000a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     */
1001a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    void copyFields(const SkPath& that);
1002a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class Iter;
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class SkPathStroker;
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Append, in reverse order, the first contour of path, ignoring path's
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        last point. If no moveTo() call has been made for this contour, the
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        first point is automatically set to (0,0).
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void reversePathTo(const SkPath&);
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1013d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // called before we add points for lineTo, quadTo, cubicTo, checking to see
1014d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // if we need to inject a leading moveTo first
1015d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //
1016d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
1017d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
1018d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //
10195e1a7f2cc621d357da5c62a7bc4ef750d94b96f3commit-bot@chromium.org    inline void injectMoveToIfNeeded();
1020d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com
10216aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    inline bool hasOnlyMoveTos() const;
10226aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com
102330c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    Convexity internalGetConvexity() const;
10243458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com
1025f68154a3cf43eb22d45be11f3b09e25440c366a6caryclark@google.com    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
1026f68154a3cf43eb22d45be11f3b09e25440c366a6caryclark@google.com                       bool* isClosed, Direction* direction) const;
102730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com
1028ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    /** Returns if the path can return a bound at no cost (true) or will have to
1029ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        perform some computation (false).
1030ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com     */
1031ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool hasComputedBounds() const {
1032ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
1033ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->hasComputedBounds();
1034ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
1035ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1036ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1037ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    // 'rect' needs to be sorted
1038ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void setBounds(const SkRect& rect) {
10390efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        SkPathRef::Editor ed(&fPathRef);
10400efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
10410efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        ed.setBounds(rect);
1042ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
1043ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class SkAutoPathBoundsUpdate;
10456aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    friend class SkAutoDisableOvalCheck;
104630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    friend class SkAutoDisableDirectionCheck;
1047a1a097ee814d05a92487d85db8ad02e1d852fd6fcommit-bot@chromium.org    friend class SkBench_AddPathTest; // perf test reversePathTo
1048a1a097ee814d05a92487d85db8ad02e1d852fd6fcommit-bot@chromium.org    friend class PathTest_Private; // unit test reversePathTo
10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1052