18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkPath_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPath_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
12ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkPathRef.h"
131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#include "SkRefCnt.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15739456585a0cc52b335cd1c0a9fc6b01782a7f89reed@google.comclass SkReader32;
16739456585a0cc52b335cd1c0a9fc6b01782a7f89reed@google.comclass SkWriter32;
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoPathBoundsUpdate;
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkString;
194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comclass SkRRect;
2066a5d8bf13fe98baae268db0211e9c25e5ece7facaryclarkclass SkWStream;
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkPath
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The SkPath class encapsulates compound (multiple contour) geometric paths
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    consisting of straight line segments, quadratic curves, and cubic curves.
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
277ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgclass SK_API SkPath {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath();
301ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    SkPath(const SkPath&);
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkPath();
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
331ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    SkPath& operator=(const SkPath&);
345e728450247c677343e072f37150967b36892573bsalomon@google.com    friend  SK_API bool operator==(const SkPath&, const SkPath&);
353abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com    friend bool operator!=(const SkPath& a, const SkPath& b) {
363abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com        return !(a == b);
373abec1d7c38e9bd786fc6057f9608f3eeec98c86reed@android.com    }
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398e7b19d0f04f286ec283747ec128e9696c842858caryclark    /** Return true if the paths contain an equal array of verbs and weights. Paths
408e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  with equal verb counts can be readily interpolated. If the paths contain one
418e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  or more conics, the conics' weights must also match.
428e7b19d0f04f286ec283747ec128e9696c842858caryclark     *
438e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  @param compare  The path to compare.
448e7b19d0f04f286ec283747ec128e9696c842858caryclark     *
458e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  @return true if the paths have the same verbs and weights.
468e7b19d0f04f286ec283747ec128e9696c842858caryclark     */
478e7b19d0f04f286ec283747ec128e9696c842858caryclark    bool isInterpolatable(const SkPath& compare) const;
488e7b19d0f04f286ec283747ec128e9696c842858caryclark
498e7b19d0f04f286ec283747ec128e9696c842858caryclark    /** Interpolate between two paths with same-sized point arrays.
508e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  The out path contains the verbs and weights of this path.
518e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  The out points are a weighted average of this path and the ending path.
528e7b19d0f04f286ec283747ec128e9696c842858caryclark     *
538e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  @param ending  The path to interpolate between.
548e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  @param weight  The weight, from 0 to 1. The output points are set to
558e7b19d0f04f286ec283747ec128e9696c842858caryclark     *                 (this->points * weight) + ending->points * (1 - weight).
568e7b19d0f04f286ec283747ec128e9696c842858caryclark     *  @return true if the paths could be interpolated.
578e7b19d0f04f286ec283747ec128e9696c842858caryclark     */
588e7b19d0f04f286ec283747ec128e9696c842858caryclark    bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
598e7b19d0f04f286ec283747ec128e9696c842858caryclark
6090b5c0ced0e7ecc8812509d4c6c8017b1d08308fdjsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
6190b5c0ced0e7ecc8812509d4c6c8017b1d08308fdjsollen    /** Returns true if the caller is the only owner of the underlying path data */
6290b5c0ced0e7ecc8812509d4c6c8017b1d08308fdjsollen    bool unique() const { return fPathRef->unique(); }
6390b5c0ced0e7ecc8812509d4c6c8017b1d08308fdjsollen#endif
6490b5c0ced0e7ecc8812509d4c6c8017b1d08308fdjsollen
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum FillType {
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Specifies that "inside" is computed by a non-zero sum of signed
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            edge crossings
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kWinding_FillType,
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Specifies that "inside" is computed by an odd number of edge
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            crossings
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kEvenOdd_FillType,
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Same as Winding, but draws outside of the path, rather than inside
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kInverseWinding_FillType,
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Same as EvenOdd, but draws outside of the path, rather than inside
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com         */
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kInverseEvenOdd_FillType
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the path's fill type. This is used to define how "inside" is
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        computed. The default value is kWinding_FillType.
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return the path's fill type
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    FillType getFillType() const { return (FillType)fFillType; }
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the path's fill type. This is used to define how "inside" is
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        computed. The default value is kWinding_FillType.
91b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param ft The new fill type for this path
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
94f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void setFillType(FillType ft) {
95f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        fFillType = SkToU8(ft);
96f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    }
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the filltype is one of the Inverse variants */
995f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
101b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    /**
102b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Toggle between inverse and normal filltypes. This reverse the return
103b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  value of isInverseFillType()
104b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     */
105f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void toggleInverseFillType() {
106f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        fFillType ^= 2;
1076b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    }
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10904863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    enum Convexity {
11004863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kUnknown_Convexity,
11104863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kConvex_Convexity,
11204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        kConcave_Convexity
11304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    };
11404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
11504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
11630c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  Return the path's convexity, as stored in the path. If it is currently unknown,
11730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  then this function will attempt to compute the convexity (and cache the result).
118b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     */
119b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    Convexity getConvexity() const {
12030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        if (kUnknown_Convexity != fConvexity) {
12130c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com            return static_cast<Convexity>(fConvexity);
12230c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        } else {
12330c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com            return this->internalGetConvexity();
124b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com        }
125b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    }
126b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com
127b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    /**
128b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Return the currently cached value for convexity, even if that is set to
129b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  kUnknown_Convexity. Note: getConvexity() will automatically call
130b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  ComputeConvexity and cache its return value if the current setting is
131b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  kUnknown.
13204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
133b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
13404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
13504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
13604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Store a convexity setting in the path. There is no automatic check to
13730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  see if this value actually agrees with the return value that would be
13830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com     *  computed by getConvexity().
139b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *
140b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  Note: even if this is set to a "known" value, if the path is later
141b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
142b54455e440e66e0b1c30954d226226f49aac26d6reed@google.com     *  reset to kUnknown_Convexity.
14304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
14404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    void setConvexity(Convexity);
14504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
14604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
14704863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Returns true if the path is flagged as being convex. This is not a
14804863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  confirmed by any analysis, it is just the value set earlier.
14904863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     */
15004863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    bool isConvex() const {
15104863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        return kConvex_Convexity == this->getConvexity();
15204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    }
15304863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com
15404863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com    /**
15504863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  Set the isConvex flag to true or false. Convex paths may draw faster if
15604863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  this flag is set, though setting this to true on a path that is in fact
15704863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  not convex can give undefined results when drawn. Paths default to
15804863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com     *  isConvex == false
1596b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com     */
1604469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use setConvexity")
161f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    void setIsConvex(bool isConvex) {
16204863fa14a44ddf85acbc6268690ebc3f0d1d6dbreed@google.com        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
163f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    }
1646b82d1adc6a4726e36674e468ff1157e0b75373freed@android.com
1656aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    /** Returns true if the path is an oval.
1666aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *
1676aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     * @param rect      returns the bounding rect of this oval. It's a circle
1686aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *                  if the height and width are the same.
1696aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *
1706aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     * @return true if this path is an oval.
1716aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              Tracking whether a path is an oval is considered an
1726aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              optimization for performance and so some paths that are in
1736aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     *              fact ovals can report false.
1746aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com     */
175466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
1766aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com
177da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark    /** Returns true if the path is a round rect.
178da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     *
179da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     * @param rrect  Returns the bounding rect and radii of this round rect.
180da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     *
181da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     * @return true if this path is a round rect.
182da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     *              Tracking whether a path is a round rect is considered an
183da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     *              optimization for performance and so some paths that are in
184da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     *              fact round rects can report false.
185da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark     */
186da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark    bool isRRect(SkRRect* rrect) const { return fPathRef->isRRect(rrect); }
187da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Clear any lines and curves from the path, making it empty. This frees up
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        internal storage associated with those segments.
190cb8b0eeacfc2ff79a2b9721e3ef21d1efb507dc8mtklein@google.com        On Android, does not change fSourcePath.
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void reset();
193fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Similar to reset(), in that all lines and curves are removed from the
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path. However, any internal storage for those lines/curves is retained,
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        making reuse of the path potentially faster.
197cb8b0eeacfc2ff79a2b9721e3ef21d1efb507dc8mtklein@google.com        On Android, does not change fSourcePath.
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rewind();
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the path is empty (contains no lines or curves)
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return true if the path is empty (contains no lines or curves)
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
205ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool isEmpty() const {
206ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
207ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return 0 == fPathRef->countVerbs();
208ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
210b1475b0d41efc580207183a4e25d14e920b57360fs    /** Return true if the last contour of this path ends with a close verb.
211b1475b0d41efc580207183a4e25d14e920b57360fs     */
212b1475b0d41efc580207183a4e25d14e920b57360fs    bool isLastContourClosed() const;
213b1475b0d41efc580207183a4e25d14e920b57360fs
2140bb18bb264b26afca45452910437c09445e23a3creed@google.com    /**
2150bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  Returns true if all of the points in this path are finite, meaning there
2160bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  are no infinities and no NaNs.
2170bb18bb264b26afca45452910437c09445e23a3creed@google.com     */
2180bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite() const {
219ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
220ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->isFinite();
2210bb18bb264b26afca45452910437c09445e23a3creed@google.com    }
2220bb18bb264b26afca45452910437c09445e23a3creed@google.com
223b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    /** Returns true if the path is volatile (i.e. should not be cached by devices.)
224b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     */
225b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    bool isVolatile() const {
226b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth        return SkToBool(fIsVolatile);
227b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    }
228b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth
229b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    /** Specify whether this path is volatile. Paths are not volatile by
230b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     default. Temporary paths that are discarded or modified after use should be
231b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     marked as volatile. This provides a hint to the device that the path
232b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     should not be cached. Providing this hint when appropriate can
233b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     improve performance by avoiding unnecessary overhead and resource
234b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     consumption on the device.
235b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth     */
236b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    void setIsVolatile(bool isVolatile) {
237b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth        fIsVolatile = isVolatile;
238b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth    }
239b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth
2404da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a line for zero length
2414da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2424da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the line is of zero length; otherwise false.
2434da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
244e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact) {
245e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark        return exact ? p1 == p2 : p1.equalsWithinTolerance(p2);
2464da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
2474da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2484da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a quad for zero length
2494da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2504da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the quad is of zero length; otherwise false.
2514da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
2524da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
253e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                                 const SkPoint& p3, bool exact) {
254e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark        return exact ? p1 == p2 && p2 == p3 : p1.equalsWithinTolerance(p2) &&
25594fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p2.equalsWithinTolerance(p3);
2564da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
2574da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2584da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    /** Test a cubic curve for zero length
2594da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2604da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org        @return true if the cubic is of zero length; otherwise false.
2614da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
2624da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
263e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                                  const SkPoint& p3, const SkPoint& p4, bool exact) {
264e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark        return exact ? p1 == p2 && p2 == p3 && p3 == p4 : p1.equalsWithinTolerance(p2) &&
26594fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p2.equalsWithinTolerance(p3) &&
26694fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               p3.equalsWithinTolerance(p4);
2674da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
2684da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
2697e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com    /**
2707e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  Returns true if the path specifies a single line (i.e. it contains just
2717e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
2727e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  points in line[] to the end-points of the line. If the path is not a
2737e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     *  line, returns false and ignores line[].
2747e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com     */
2757e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com    bool isLine(SkPoint line[2]) const;
2767e6c4d16010550ee148f1c79cf088c0320fed5c1reed@google.com
277d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    /** Return the number of points in the path
278d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com     */
2791dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int countPoints() const;
280d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com
281d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    /** Return the point at the specified index. If the index is out of range
282d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
283d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com         will be (0,0)
284d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com     */
285d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com    SkPoint getPoint(int index) const;
286d3aa4ff7a564953dff9a15ff03fd42eebf64569freed@android.com
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the number of points in the path. Up to max points are copied.
288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param points If not null, receives up to max points
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param max The maximum number of points to copy into points
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @return the actual number of points in the path
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int getPoints(SkPoint points[], int max) const;
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
295df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    /** Return the number of verbs in the path
296df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com     */
2971dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int countVerbs() const;
298df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
299df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    /** Returns the number of verbs in the path. Up to max verbs are copied. The
300df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        verbs are copied as one byte per verb.
301fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
302df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @param verbs If not null, receives up to max verbs
303df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @param max The maximum number of verbs to copy into verbs
304df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com        @return the actual number of verbs in the path
305df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    */
306df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com    int getVerbs(uint8_t verbs[], int max) const;
307df9d656c352928f995abce0a62c4ec3255232a45bsalomon@google.com
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //! Swap contents of this and other. Guaranteed not to throw
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void swap(SkPath& other);
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31191f283bb4e6ea71bbd4e6efc27befc29118ee543reed    /**
31291f283bb4e6ea71bbd4e6efc27befc29118ee543reed     *  Returns the bounds of the path's points. If the path contains zero points/verbs, this
31391f283bb4e6ea71bbd4e6efc27befc29118ee543reed     *  will return the "empty" rect [0, 0, 0, 0].
31491f283bb4e6ea71bbd4e6efc27befc29118ee543reed     *  Note: this bounds may be larger than the actual shape, since curves
31591f283bb4e6ea71bbd4e6efc27befc29118ee543reed     *  do not extend as far as their control points. Additionally this bound encompases all points,
31691f283bb4e6ea71bbd4e6efc27befc29118ee543reed     *  even isolated moveTos either preceeding or following the last non-degenerate contour.
317d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    */
318d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    const SkRect& getBounds() const {
319ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->getBounds();
320d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Calling this will, if the internal cache of the bounds is out of date,
3239bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com        update it so that subsequent calls to getBounds will be instantaneous.
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        This also means that any copies or simple transformations of the path
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        will inherit the cached bounds.
326d252db03d9650013b545ef9781fe993c07f8f314reed@android.com     */
327d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    void updateBoundsCache() const {
328d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        // for now, just calling getBounds() is sufficient
329d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        this->getBounds();
330d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3329bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com    /**
3339bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * Does a conservative test to see whether a rectangle is inside a path. Currently it only
3349bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * will ever return true for single convex contour paths. The empty-status of the rect is not
3359bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
3369bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     * the rect edge touches the path border are not considered containment violations.
3379bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com     */
3389bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com    bool conservativelyContainsRect(const SkRect& rect) const;
3399bee33afbeca29f531c8455513b925f6e93da633bsalomon@google.com
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //  Construction methods
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Hint to the path to prepare for adding more points. This can allow the
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path to more efficiently grow its storage.
344fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param extraPtCount The number of extra points the path should
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            preallocate for.
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void incReserve(unsigned extraPtCount);
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour to the point (x,y).
351fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The x-coordinate of the start of a new contour
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The y-coordinate of the start of a new contour
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void moveTo(SkScalar x, SkScalar y);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour to the point
358fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The start of a new contour
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void moveTo(const SkPoint& p) {
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->moveTo(p.fX, p.fY);
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the beginning of the next contour relative to the last point on the
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        previous contour. If there is no previous contour, this is treated the
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        same as moveTo().
368fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to add to the x-coordinate of the end of the
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    previous contour, to specify the start of a new contour
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy   The amount to add to the y-coordinate of the end of the
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    previous contour, to specify the start of a new contour
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rMoveTo(SkScalar dx, SkScalar dy);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a line from the last point to the specified point (x,y). If no
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo() call has been made for this contour, the first point is
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        automatically set to (0,0).
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The x-coordinate of the end of a line
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The y-coordinate of the end of a line
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void lineTo(SkScalar x, SkScalar y);
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a line from the last point to the specified point. If no moveTo()
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        call has been made for this contour, the first point is automatically
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        set to (0,0).
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The end of a line
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void lineTo(const SkPoint& p) {
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->lineTo(p.fX, p.fY);
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as lineTo, but the coordinates are considered relative to the last
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        point on this contour. If there is no previous point, then a moveTo(0,0)
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is inserted automatically.
398fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to add to the x-coordinate of the previous point
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    on this contour, to specify a line
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy   The amount to add to the y-coordinate of the previous point
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    on this contour, to specify a line
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rLineTo(SkScalar dx, SkScalar dy);
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a quadratic bezier from the last point, approaching control point
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this contour, the first point is automatically set to (0,0).
409fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x1   The x-coordinate of the control point on a quadratic curve
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y1   The y-coordinate of the control point on a quadratic curve
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x2   The x-coordinate of the end point on a quadratic curve
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y2   The y-coordinate of the end point on a quadratic curve
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a quadratic bezier from the last point, approaching control point
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        p1, and ending at p2. If no moveTo() call has been made for this
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        contour, the first point is automatically set to (0,0).
420fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p1   The control point on a quadratic curve
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p2   The end point on a quadratic curve
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void quadTo(const SkPoint& p1, const SkPoint& p2) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as quadTo, but the coordinates are considered relative to the last
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        point on this contour. If there is no previous point, then a moveTo(0,0)
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is inserted automatically.
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx1   The amount to add to the x-coordinate of the last point on
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the control point of a quadratic curve
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy1   The amount to add to the y-coordinate of the last point on
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the control point of a quadratic curve
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx2   The amount to add to the x-coordinate of the last point on
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a quadratic curve
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy2   The amount to add to the y-coordinate of the last point on
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a quadratic curve
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
443277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
444277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com                 SkScalar w);
445277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
446277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
447277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    }
448277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
449277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com                  SkScalar w);
45026da7f00aedba107d4b3e382283034e265db09b6skia.committer@gmail.com
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a cubic bezier from the last point, approaching control points
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        made for this contour, the first point is automatically set to (0,0).
454fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x1   The x-coordinate of the 1st control point on a cubic curve
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y1   The y-coordinate of the 1st control point on a cubic curve
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x2   The x-coordinate of the 2nd control point on a cubic curve
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y2   The y-coordinate of the 2nd control point on a cubic curve
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x3   The x-coordinate of the end point on a cubic curve
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y3   The y-coordinate of the end point on a cubic curve
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkScalar x3, SkScalar y3);
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a cubic bezier from the last point, approaching control points p1
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and p2, and ending at p3. If no moveTo() call has been made for this
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        contour, the first point is automatically set to (0,0).
468fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p1   The 1st control point on a cubic curve
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p2   The 2nd control point on a cubic curve
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p3   The end point on a cubic curve
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Same as cubicTo, but the coordinates are considered relative to the
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        current point on this contour. If there is no previous point, then a
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo(0,0) is inserted automatically.
480fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx1   The amount to add to the x-coordinate of the last point on
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 1st control point of a cubic curve
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy1   The amount to add to the y-coordinate of the last point on
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 1st control point of a cubic curve
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx2   The amount to add to the x-coordinate of the last point on
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 2nd control point of a cubic curve
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy2   The amount to add to the y-coordinate of the last point on
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                this contour, to specify the 2nd control point of a cubic curve
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx3   The amount to add to the x-coordinate of the last point on
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a cubic curve
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dy3   The amount to add to the y-coordinate of the last point on
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     this contour, to specify the end point of a cubic curve
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4946b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4956b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com                  SkScalar x3, SkScalar y3);
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
497c778904a5b686617ad7fdec850ddc21e103dca0freed    /**
498c778904a5b686617ad7fdec850ddc21e103dca0freed     *  Append the specified arc to the path. If the start of the arc is different from the path's
499c778904a5b686617ad7fdec850ddc21e103dca0freed     *  current last point, then an automatic lineTo() is added to connect the current contour
500c778904a5b686617ad7fdec850ddc21e103dca0freed     *  to the start of the arc. However, if the path is empty, then we call moveTo() with
501c778904a5b686617ad7fdec850ddc21e103dca0freed     *  the first point of the arc. The sweep angle is treated mod 360.
502c778904a5b686617ad7fdec850ddc21e103dca0freed     *
503c778904a5b686617ad7fdec850ddc21e103dca0freed     *  @param oval The bounding oval defining the shape and size of the arc
504c778904a5b686617ad7fdec850ddc21e103dca0freed     *  @param startAngle Starting angle (in degrees) where the arc begins
505c778904a5b686617ad7fdec850ddc21e103dca0freed     *  @param sweepAngle Sweep angle (in degrees) measured clockwise. This is treated mod 360.
506c778904a5b686617ad7fdec850ddc21e103dca0freed     *  @param forceMoveTo If true, always begin a new contour with the arc
507c778904a5b686617ad7fdec850ddc21e103dca0freed     */
508c778904a5b686617ad7fdec850ddc21e103dca0freed    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
510c778904a5b686617ad7fdec850ddc21e103dca0freed    /**
511c778904a5b686617ad7fdec850ddc21e103dca0freed     *  Append a line and arc to the current path. This is the same as the PostScript call "arct".
512c778904a5b686617ad7fdec850ddc21e103dca0freed     */
513c778904a5b686617ad7fdec850ddc21e103dca0freed    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Append a line and arc to the current path. This is the same as the
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        PostScript call "arct".
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
52255d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    enum ArcSize {
52355d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        /** the smaller of the two possible SVG arcs. */
52455d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        kSmall_ArcSize,
52555d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        /** the larger of the two possible SVG arcs. */
52655d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        kLarge_ArcSize,
52755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    };
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5298fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    enum Direction {
5308fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        /** clockwise direction for adding closed contours */
5318fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        kCW_Direction,
5328fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        /** counter-clockwise direction for adding closed contours */
5338fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        kCCW_Direction,
5348fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    };
5358fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
536a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
53755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  Append an elliptical arc from the current point in the format used by SVG.
53855d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  The center of the ellipse is computed to satisfy the constraints below.
53955d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *
54055d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param rx,ry The radii in the x and y directions respectively.
54155d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param xAxisRotate The angle in degrees relative to the x-axis.
54255d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param largeArc Determines whether the smallest or largest arc possible
54355d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         is drawn.
54455d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param sweep Determines if the arc should be swept in an anti-clockwise or
54555d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         clockwise direction. Note that this enum value is opposite the SVG
54655d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         arc sweep value.
54755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param x,y The destination coordinates.
54855d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     */
54955d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
55055d49053d1b6db42e013eb3409ffcfc7e235c685caryclark               Direction sweep, SkScalar x, SkScalar y);
55155d49053d1b6db42e013eb3409ffcfc7e235c685caryclark
55255d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
55355d49053d1b6db42e013eb3409ffcfc7e235c685caryclark               const SkPoint xy) {
55455d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
55555d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    }
55655d49053d1b6db42e013eb3409ffcfc7e235c685caryclark
55755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    /** Same as arcTo format used by SVG, but the destination coordinate is relative to the
55855d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  last point on this contour. If there is no previous point, then a
55955d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  moveTo(0,0) is inserted automatically.
56055d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *
56155d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param rx,ry The radii in the x and y directions respectively.
56255d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param xAxisRotate The angle in degrees relative to the x-axis.
56355d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param largeArc Determines whether the smallest or largest arc possible
56455d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         is drawn.
56555d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param sweep Determines if the arc should be swept in an anti-clockwise or
56655d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         clockwise direction. Note that this enum value is opposite the SVG
56755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *         arc sweep value.
56855d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     *  @param dx,dy The destination coordinates relative to the last point.
56955d49053d1b6db42e013eb3409ffcfc7e235c685caryclark     */
57055d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
57155d49053d1b6db42e013eb3409ffcfc7e235c685caryclark                Direction sweep, SkScalar dx, SkScalar dy);
57255d49053d1b6db42e013eb3409ffcfc7e235c685caryclark
57355d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    /** Close the current contour. If the current point is not equal to the
57455d49053d1b6db42e013eb3409ffcfc7e235c685caryclark        first point of the contour, a line segment is automatically added.
57555d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    */
57655d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    void close();
57755d49053d1b6db42e013eb3409ffcfc7e235c685caryclark
57855d49053d1b6db42e013eb3409ffcfc7e235c685caryclark    /**
57912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     *  Returns whether or not a fill type is inverted
5805f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *
5815f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kWinding_FillType        -> false
5825f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kEvenOdd_FillType        -> false
5835f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseWinding_FillType -> true
5845f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseEvenOdd_FillType -> true
58512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     */
5865f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    static bool IsInverseFillType(FillType fill) {
58799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
58899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
58999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
59099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
59112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        return (fill & 2) != 0;
59212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    }
59312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com
59412b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    /**
59512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     *  Returns the equivalent non-inverted fill type to the given fill type
5965f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *
5975f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kWinding_FillType        -> kWinding_FillType
5985f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kEvenOdd_FillType        -> kEvenOdd_FillType
5995f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseWinding_FillType -> kWinding_FillType
6005f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
60112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com     */
6025f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com    static FillType ConvertToNonInverseFillType(FillType fill) {
60399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
60499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
60599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
60699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
60712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com        return (FillType)(fill & 1);
60812b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    }
60912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com
61012b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    /**
611aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita     *  Chop a conic into N quads, stored continguously in pts[], where
612aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita     *  N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
613aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita     */
614aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita    static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
615aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita                                   SkScalar w, SkPoint pts[], int pow2);
616aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita
617aa0df4e98d39cf0691fbaf0766c9f5f7ec72177ffmalita    /**
6184f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  Returns true if the path specifies a rectangle.
6194f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *
6204f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  If this returns false, then all output parameters are ignored, and left
6214f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  unchanged. If this returns true, then each of the output parameters
6224f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  are checked for NULL. If they are not, they return their value.
6234f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *
62491b0a3587342c48a1a6e1c4687686688737359darobertphillips     *  @param rect If not null, set to the bounds of the rectangle.
62591b0a3587342c48a1a6e1c4687686688737359darobertphillips     *              Note : this bounds may be smaller than the path's bounds, since it is just
62691b0a3587342c48a1a6e1c4687686688737359darobertphillips     *              the bounds of the "drawable" parts of the path. e.g. a trailing MoveTo would
62791b0a3587342c48a1a6e1c4687686688737359darobertphillips     *              be ignored in this rect, but not by the path's bounds
6284f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  @param isClosed If not null, set to true if the path is closed
6294f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  @param direction If not null, set to the rectangle's direction
6304f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     *  @return true if the path specifies a rectangle
6314f662e62cd44e302ef689fabdb2c0ae8d9471b02robertphillips     */
63291b0a3587342c48a1a6e1c4687686688737359darobertphillips    bool isRect(SkRect* rect, bool* isClosed = NULL, Direction* direction = NULL) const;
6338fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
63495bc5f349561fef2d6fbae71adb08cf5c2eec0c9caryclark    /** Returns true if the path specifies a pair of nested rectangles, or would draw a
63595bc5f349561fef2d6fbae71adb08cf5c2eec0c9caryclark        pair of nested rectangles when filled. If so, and if
6368fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
6378fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        rectangle. If so, and dirs is not null, set dirs[0] to the direction of
6388fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        the outer rectangle and dirs[1] to the direction of the inner rectangle. If
6398fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        the path does not specify a pair of nested rectangles, return
6408fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        false and ignore rect and dirs.
6418fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
6428fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param rect If not null, returns the path as a pair of nested rectangles
6438fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @param dirs If not null, returns the direction of the rects
6448fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com        @return true if the path describes a pair of nested rectangles
6458fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com    */
64695bc5f349561fef2d6fbae71adb08cf5c2eec0c9caryclark    bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = NULL) const;
6478fd160350ca5f57fbb1b2e03383c5778414a9b48robertphillips@google.com
648a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
649a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed rectangle contour to the path
650a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The rectangle to add as a closed contour to the path
651026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the rectangle's contour.
652c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
653c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Note: the contour initial point index is 0 (as defined below).
654a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
655ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void addRect(const SkRect& rect, Direction dir = kCW_Direction);
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
657a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
658a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed rectangle contour to the path
659c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param rect  The rectangle to add as a closed contour to the path
660c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param dir   The direction to wind the rectangle's contour.
661c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param start Initial point of the contour (initial moveTo), expressed as
662c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *               a corner index, starting in the upper-left position, clock-wise:
663c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
664c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  0         1
665c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   *-------*
666c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   |       |
667c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   *-------*
668c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  3         2
669c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     */
670c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    void addRect(const SkRect& rect, Direction dir, unsigned start);
671c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita
672c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    /**
673c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Add a closed rectangle contour to the path
674a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
675a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param left     The left side of a rectangle to add as a closed contour
676a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  to the path
677a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param top      The top of a rectangle to add as a closed contour to the
678a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  path
679a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param right    The right side of a rectangle to add as a closed contour
680a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  to the path
681a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param bottom   The bottom of a rectangle to add as a closed contour to
682a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  the path
683026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the rectangle's contour.
684c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
685c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Note: the contour initial point index is 0 (as defined above).
686a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 Direction dir = kCW_Direction);
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
690a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
691a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed oval contour to the path
692a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
693a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param oval The bounding oval to add as a closed contour to the path
694026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the oval's contour.
695c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
696c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Note: the contour initial point index is 1 (as defined below).
697a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
700a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
701c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Add a closed oval contour to the path
702c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
703c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param oval  The bounding oval to add as a closed contour to the path
704c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param dir   The direction to wind the oval's contour.
705c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param start Initial point of the contour (initial moveTo), expressed
706c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *               as an ellipse vertex index, starting at the top, clock-wise
707c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *               (90/0/270/180deg order):
708c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
709c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *        0
710c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *       -*-
711c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *     |     |
712c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   3 *     * 1
713c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *     |     |
714c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *       -*-
715c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *        2
716c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     */
717c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    void addOval(const SkRect& oval, Direction dir, unsigned start);
718c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita
719c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    /**
720a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed circle contour to the path
721a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *
722a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param x        The x-coordinate of the center of a circle to add as a
723a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  closed contour to the path
724a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param y        The y-coordinate of the center of a circle to add as a
725a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  closed contour to the path
726a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param radius   The radius of a circle to add as a closed contour to the
727a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *                  path
728026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the circle's contour.
729a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                   Direction dir = kCW_Direction);
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add the specified arc to the path as a new contour.
734fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param oval The bounds of oval used to define the size of the arc
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param startAngle Starting angle (in degrees) where the arc begins
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param sweepAngle Sweep angle (in degrees) measured clockwise
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
741a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
742a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed round-rectangle contour to the path
743a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The bounds of a round-rectangle to add as a closed contour
744a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rx   The x-radius of the rounded corners on the round-rectangle
745a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param ry   The y-radius of the rounded corners on the round-rectangle
746026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the rectangle's contour.
747a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
748ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
749ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com                      Direction dir = kCW_Direction);
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
751a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com    /**
752a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  Add a closed round-rectangle contour to the path. Each corner receives
753a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  two radius values [X, Y]. The corners are ordered top-left, top-right,
754a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  bottom-right, bottom-left.
755a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param rect The bounds of a round-rectangle to add as a closed contour
756a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
757026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir  The direction to wind the rectangle's contour.
7584e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     * Note: The radii here now go through the same constraint handling as the
7594e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *       SkRRect radii (i.e., either radii at a corner being 0 implies a
7604e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *       sqaure corner and oversized radii are proportionally scaled down).
761a8a3b3d9a027ad54ce20f8b4ed7c577a176b31careed@google.com     */
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void addRoundRect(const SkRect& rect, const SkScalar radii[],
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                      Direction dir = kCW_Direction);
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
765744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com    /**
7664e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *  Add an SkRRect contour to the path
7674e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com     *  @param rrect The rounded rect to add as a closed contour
768026beb52a29a620290fcfb24f1e7e9e75547b80freed     *  @param dir   The winding direction for the new contour.
769c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
770c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Note: the contour initial point index is either 6 (for dir == kCW_Direction)
771c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *        or 7 (for dir == kCCW_Direction), as defined below.
772c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
7734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     */
7744e18c7a9bbef6ac949d535aa61dfe1462ebb4452robertphillips@google.com    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
7754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
7764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    /**
777c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  Add an SkRRect contour to the path
778c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param rrect The rounded rect to add as a closed contour
779c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param dir   The winding direction for the new contour.
780c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *  @param start Initial point of the contour (initial moveTo), expressed as
781c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *               an index of the radii minor/major points, ordered clock-wise:
782c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *
783c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *      0    1
784c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *      *----*
785c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   7 *      * 2
786c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *     |      |
787c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *   6 *      * 3
788c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *      *----*
789c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     *      5    4
790c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita     */
791c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    void addRRect(const SkRRect& rrect, Direction dir, unsigned start);
792c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita
793c08d53ee175e190254d8fd6659d9ad051ac0ba46fmalita    /**
794744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *  Add a new contour made of just lines. This is just a fast version of
795744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *  the following:
796744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      this->moveTo(pts[0]);
797744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      for (int i = 1; i < count; ++i) {
798744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *          this->lineTo(pts[i]);
799744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      }
800744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      if (close) {
801744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *          this->close();
802744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     *      }
803744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com     */
804744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com    void addPoly(const SkPoint pts[], int count, bool close);
805744fabad474e3e111e7cbd8609cf7e209df17f32reed@google.com
80614747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    enum AddPathMode {
80714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        /** Source path contours are added as new contours.
80814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        */
80914747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        kAppend_AddPathMode,
81014747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        /** Path is added by extending the last contour of the destination path
81114747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            with the first contour of the source path. If the last contour of
812877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com            the destination path is closed, then it will not be extended.
81314747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            Instead, the start of source path will be extended by a straight
81414747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org            line to the end point of the destination path.
81514747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        */
816877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com        kExtend_AddPathMode
81714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    };
81814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path, offset by (dx,dy)
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param src  The path to add as a new contour
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to translate the path in X as it is added
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dx   The amount to translate the path in Y as it is added
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
82414747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
82514747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org                 AddPathMode mode = kAppend_AddPathMode);
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
82914747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkMatrix m;
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        m.reset();
83214747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        this->addPath(src, m, mode);
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add a copy of src to the path, transformed by matrix
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param src  The path to add as a new contour
83714747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        @param matrix  Transform applied to src
83814747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org        @param mode  Determines how path is added
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
84014747e58f8127a6d6b3c748bf0642b0d6a3a79e8commit-bot@chromium.org    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84263d73749fbe36491403ea521005fd298dc70a94creed@google.com    /**
84363d73749fbe36491403ea521005fd298dc70a94creed@google.com     *  Same as addPath(), but reverses the src input
84463d73749fbe36491403ea521005fd298dc70a94creed@google.com     */
84563d73749fbe36491403ea521005fd298dc70a94creed@google.com    void reverseAddPath(const SkPath& src);
84663d73749fbe36491403ea521005fd298dc70a94creed@google.com
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset the path by (dx,dy), returning true on success
848fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
849fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dx   The amount in the X direction to offset the entire path
850fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dy   The amount in the Y direction to offset the entire path
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dst  The translated path is written here
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Offset the path by (dx,dy), returning true on success
856fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
857fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dx   The amount in the X direction to offset the entire path
858fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        @param dy   The amount in the Y direction to offset the entire path
8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void offset(SkScalar dx, SkScalar dy) {
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->offset(dx, dy, this);
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Transform the points in this path by matrix, and write the answer into
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst.
866fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param matrix   The matrix to apply to the path
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param dst      The transformed path is written here
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void transform(const SkMatrix& matrix, SkPath* dst) const;
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Transform the points in this path by matrix
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param matrix The matrix to apply to the path
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void transform(const SkMatrix& matrix) {
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->transform(matrix, this);
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the last point on the path. If no points have been added, (0,0)
881294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com        is returned. If there are no points, this returns false, otherwise it
882294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com        returns true.
883fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param lastPt   The last point on the path is returned here
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
886294dd7b3d7b55ba38881cd4cabb6636abda23eb9reed@google.com    bool getLastPt(SkPoint* lastPt) const;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the last point on the path. If no points have been added,
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        moveTo(x,y) is automatically called.
890fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param x    The new x-coordinate for the last point
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param y    The new y-coordinate for the last point
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setLastPt(SkScalar x, SkScalar y);
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the last point on the path. If no points have been added, moveTo(p)
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        is automatically called.
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        @param p    The new location for the last point
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setLastPt(const SkPoint& p) {
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->setLastPt(p.fX, p.fY);
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90510296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    enum SegmentMask {
90610296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com        kLine_SegmentMask   = 1 << 0,
90710296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com        kQuad_SegmentMask   = 1 << 1,
908277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kConic_SegmentMask  = 1 << 2,
909277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kCubic_SegmentMask  = 1 << 3,
91010296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    };
91110296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com
91210296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com    /**
91310296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  Returns a mask, where each bit corresponding to a SegmentMask is
91410296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  set if the path contains 1 or more segments of that type.
91510296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     *  Returns 0 for an empty path (no segments).
91610296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com     */
9176b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
91810296ccb6a63c65b2e60733a929bf15d8bf94309reed@google.com
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    enum Verb {
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kMove_Verb,     //!< iter.next returns 1 point
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kLine_Verb,     //!< iter.next returns 2 points
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kQuad_Verb,     //!< iter.next returns 3 points
923277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        kCubic_Verb,    //!< iter.next returns 4 points
925449f7fcf7088bb67b86729bd4675a72c7580c443caryclark        kClose_Verb,    //!< iter.next returns 0 points
926277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        kDone_Verb,     //!< iter.next returns 0 points
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Iterate through all of the segments (lines, quadratics, cubics) of
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        each contours in a path.
93172785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org
93272785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        The iterator cleans up the segments along the way, removing degenerate
93372785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        segments and adding close verbs where necessary. When the forceClose
93472785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        argument is provided, each contour (as defined by a new starting
93572785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        move command) will be completed with a close verb regardless of the
93672785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        contour's contents.
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
9387ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.org    class SK_API Iter {
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    public:
94072785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        Iter();
94172785c4c8928a8b0fc5bbdb48929f9356554daceschenney@chromium.org        Iter(const SkPath&, bool forceClose);
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void setPath(const SkPath&, bool forceClose);
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Return the next verb in this iteration of the path. When all
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            segments have been visited, return kDone_Verb.
947b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @param  pts The points representing the current verb and/or segment
9494a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            @param doConsumeDegerates If true, first scan for segments that are
9504a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com                   deemed degenerate (too short) and skip those.
951e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark            @param exact if doConsumeDegenerates is true and exact is true, skip only
952e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                   degenerate elements with lengths exactly equal to zero. If exact
953e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                   is false, skip degenerate elements with lengths close to zero. If
954e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                   doConsumeDegenerates is false, exact has no effect.
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return The verb for the current segment
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
957e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark        Verb next(SkPoint pts[4], bool doConsumeDegerates = true, bool exact = false) {
9584a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            if (doConsumeDegerates) {
959e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark                this->consumeDegenerateSegments(exact);
9604a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            }
9614a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com            return this->doNext(pts);
9624a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        }
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
964277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        /**
965277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         *  Return the weight for the current conic. Only valid if the current
966277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         *  segment return by next() was a conic.
967277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com         */
968277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        SkScalar conicWeight() const { return *fConicWeights; }
969277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** If next() returns kLine_Verb, then this query returns true if the
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            line was the result of a close() command (i.e. the end point is the
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            initial moveto for this contour). If next() returned a different
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            verb, this returns an undefined value.
974b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return If the last call to next() returned kLine_Verb, return true
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if it was the result of an explicit close command.
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool isCloseLine() const { return SkToBool(fCloseLine); }
979b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /** Returns true if the current contour is closed (has a kClose_Verb)
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            @return true if the current contour is closed (has a kClose_Verb)
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool isClosedContour() const;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    private:
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPoint*  fPts;
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  fVerbs;
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  fVerbStop;
989277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        const SkScalar* fConicWeights;
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint         fMoveTo;
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint         fLastPt;
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fForceClose;
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fNeedClose;
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkBool8         fCloseLine;
995b0af6dad94f3c51ea0d5d6426a9509354338c6b2schenney@chromium.org        SkBool8         fSegmentState;
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9979e25dbf589539dd44244bc2581590bd7591e17a2reed@google.com        inline const SkPoint& cons_moveTo();
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Verb autoClose(SkPoint pts[2]);
999e8c5666e0387e70bd921e01558e627af3f1411dbcaryclark        void consumeDegenerateSegments(bool exact);
10004a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        Verb doNext(SkPoint pts[4]);
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10036630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    /** Iterate through the verbs in the path, providing the associated points.
10046630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    */
10056630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    class SK_API RawIter {
10066630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    public:
1007da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        RawIter() {}
1008da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        RawIter(const SkPath& path) {
1009da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark            setPath(path);
1010da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        }
10116630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
1012da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        void setPath(const SkPath& path) {
1013da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark            fRawIter.setPathRef(*path.fPathRef.get());
1014da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        }
10156630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
10166630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        /** Return the next verb in this iteration of the path. When all
10176630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            segments have been visited, return kDone_Verb.
1018fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
10196630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            @param  pts The points representing the current verb and/or segment
1020f6d3c5aa5f93e4c3cc7a7aebf014e960cf837783bsalomon@google.com                        This must not be NULL.
10216630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org            @return The verb for the current segment
10226630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org        */
1023da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        Verb next(SkPoint pts[4]) {
1024da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark            return (Verb) fRawIter.next(pts);
1025da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        }
10266630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
10272028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark        /** Return what the next verb will be, but do not visit the next segment.
10282028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark
10292028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark            @return The verb for the next segment
10302028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark        */
10312028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark        Verb peek() const {
10322028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark            return (Verb) fRawIter.peek();
10332028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark        }
10342028d7ff744c36855ed36d602e3e050e9f18ec9fcaryclark
1035da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        SkScalar conicWeight() const {
1036da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark            return fRawIter.conicWeight();
1037da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        }
1038277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
10396630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    private:
1040da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        SkPathRef::Iter fRawIter;
1041da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark        friend class SkPath;
10426630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org    };
10436630d8d8ea7a897a18e3d950bab9fa40f065804aschenney@chromium.org
1044bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org    /**
1045bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     *  Returns true if the point { x, y } is contained by the path, taking into
1046bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     *  account the FillType.
1047bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org     */
1048bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org    bool contains(SkScalar x, SkScalar y) const;
1049bad1b2ff1d34ff86693b776f89d7b46995746127mike@reedtribe.org
1050e956259c5a4f71768afb34ec032eaed49dcbe9f2caryclark    void dump(SkWStream* , bool forceClose, bool dumpAsHex) const;
1051e522ca5d5f249bd51a00cb68bb051f811d0a9e85reed@android.com    void dump() const;
1052e956259c5a4f71768afb34ec032eaed49dcbe9f2caryclark    void dumpHex() const;
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
105494e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    /**
10554faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *  Write the path to the buffer, and return the number of bytes written.
105694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     *  If buffer is NULL, it still returns the number of bytes.
105794e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     */
10584faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t writeToMemory(void* buffer) const;
105994e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    /**
10604faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * Initializes the path from the buffer
10614faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *
10624faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param buffer Memory to read from
10634faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param length Amount of memory available in the buffer
10644faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @return number of bytes read (must be a multiple of 4) or
10654faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *         0 if there was not enough memory available
106694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com     */
10674faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t readFromMemory(const void* buffer, size_t length);
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10691ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    /** Returns a non-zero, globally unique value corresponding to the set of verbs
10701ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org        and points in the path (but not the fill type [except on Android skbug.com/1762]).
10717ed98df9ba14bdb58e381508eb0505c963a4b6dbskia.committer@gmail.com        Each time the path is modified, a different generation ID will be returned.
10721ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    */
10737101abe5b37d82ea222e971a42615a97a2419edbrobertphillips@google.com    uint32_t getGenerationID() const;
10741ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org
1075523cda39435256bcb3e5665f47612d661d3c6bf9djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
10761ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
10771ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org#else
10781ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    static const int kPathRefGenIDBitCnt = 32;
1079f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
1080f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(void validate() const;)
108263c684a8a609d39da11b4a656223cebf52ca85dccaryclark    SkDEBUGCODE(void experimentalValidateRef() const { fPathRef->validate(); } )
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
108501ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com    enum SerializationOffsets {
1086fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org        // 1 free bit at 29
108711e055518a0cbe5329232a55fe2cd177e83836d8robertphillips@google.com        kUnused1_SerializationShift = 28,    // 1 free bit
108830c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com        kDirection_SerializationShift = 26, // requires 2 bits
1089b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth        kIsVolatile_SerializationShift = 25, // requires 1 bit
1090fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org        // 1 free bit at 24
1091ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        kConvexity_SerializationShift = 16, // requires 8 bits
1092ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        kFillType_SerializationShift = 8,   // requires 8 bits
10938f086023bf615b2661b82bcf59cdedde78ad7374reed        // low-8-bits are version
10948f086023bf615b2661b82bcf59cdedde78ad7374reed    };
10958f086023bf615b2661b82bcf59cdedde78ad7374reed
10968f086023bf615b2661b82bcf59cdedde78ad7374reed    enum SerializationVersions {
10978f086023bf615b2661b82bcf59cdedde78ad7374reed        kPathPrivFirstDirection_Version = 1,
10986900641e02c3b6c7ee15d0aa5bd4af0d42db480fcaryclark        kPathPrivLastMoveToIndex_Version = 2,
10996900641e02c3b6c7ee15d0aa5bd4af0d42db480fcaryclark        kCurrent_Version = 2
110001ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com    };
110101ec2eb42e9c64f8d06afd51f80c055710147141robertphillips@google.com
1102bf90520f63415f539cd5792a18efbd79cb86be0amtklein    SkAutoTUnref<SkPathRef>                            fPathRef;
1103bf90520f63415f539cd5792a18efbd79cb86be0amtklein    int                                                fLastMoveToIndex;
1104bf90520f63415f539cd5792a18efbd79cb86be0amtklein    uint8_t                                            fFillType;
1105bf90520f63415f539cd5792a18efbd79cb86be0amtklein    mutable uint8_t                                    fConvexity;
1106bf90520f63415f539cd5792a18efbd79cb86be0amtklein    mutable SkAtomic<uint8_t, sk_memory_order_relaxed> fFirstDirection;// SkPathPriv::FirstDirection
1107bf90520f63415f539cd5792a18efbd79cb86be0amtklein    mutable SkBool8                                    fIsVolatile;
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1109a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    /** Resets all fields other than fPathRef to their initial 'empty' values.
1110a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  Assumes the caller has already emptied fPathRef.
1111a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  On Android increments fGenerationID without reseting it.
1112a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     */
1113a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    void resetFields();
1114a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com
1115a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    /** Sets all fields other than fPathRef to the values in 'that'.
1116a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     *  Assumes the caller has already set fPathRef.
11179c9d4a70028ef8dc33a46cfc0b22e254443effe3mtklein@google.com     *  Doesn't change fGenerationID or fSourcePath on Android.
1118a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com     */
1119a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com    void copyFields(const SkPath& that);
1120a5809a3e4cb356387c5201ab9c0a10edf11a01bebungeman@google.com
11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class Iter;
1122026beb52a29a620290fcfb24f1e7e9e75547b80freed    friend class SkPathPriv;
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class SkPathStroker;
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Append, in reverse order, the first contour of path, ignoring path's
11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        last point. If no moveTo() call has been made for this contour, the
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        first point is automatically set to (0,0).
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void reversePathTo(const SkPath&);
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1131d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // called before we add points for lineTo, quadTo, cubicTo, checking to see
1132d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // if we need to inject a leading moveTo first
1133d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //
1134d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
1135d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
1136d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com    //
11375e1a7f2cc621d357da5c62a7bc4ef750d94b96f3commit-bot@chromium.org    inline void injectMoveToIfNeeded();
1138d335d1d784167f8b9a4bf8a35e04d8e82d0a9507reed@google.com
11396aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    inline bool hasOnlyMoveTos() const;
11406aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com
114130c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    Convexity internalGetConvexity() const;
11423458716b52aa25dcd1b270141c7628c380696e35skia.committer@gmail.com
1143f68154a3cf43eb22d45be11f3b09e25440c366a6caryclark@google.com    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
1144f68154a3cf43eb22d45be11f3b09e25440c366a6caryclark@google.com                       bool* isClosed, Direction* direction) const;
114530c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com
1146d49a86ade0bab1fc3048d6ba5d8536abf25ed77ccaryclark    // called by stroker to see if all points are equal and worthy of a cap
1147d49a86ade0bab1fc3048d6ba5d8536abf25ed77ccaryclark    // equivalent to a short-circuit version of getBounds().isEmpty()
1148d49a86ade0bab1fc3048d6ba5d8536abf25ed77ccaryclark    bool isZeroLength() const;
1149d49a86ade0bab1fc3048d6ba5d8536abf25ed77ccaryclark
1150ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    /** Returns if the path can return a bound at no cost (true) or will have to
1151ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        perform some computation (false).
1152ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com     */
1153ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool hasComputedBounds() const {
1154ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
1155ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fPathRef->hasComputedBounds();
1156ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
1157ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1158ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1159ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    // 'rect' needs to be sorted
1160ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void setBounds(const SkRect& rect) {
11610efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        SkPathRef::Editor ed(&fPathRef);
11620efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
11630efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        ed.setBounds(rect);
1164ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
1165ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1166aec251012542e971100e218bf463adbfb5d21d20caryclark    void setPt(int index, SkScalar x, SkScalar y);
1167aec251012542e971100e218bf463adbfb5d21d20caryclark
11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend class SkAutoPathBoundsUpdate;
11696aa2965ca814dd3329b65398b5c5af980e54b101bsalomon@google.com    friend class SkAutoDisableOvalCheck;
117030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com    friend class SkAutoDisableDirectionCheck;
1171a1a097ee814d05a92487d85db8ad02e1d852fd6fcommit-bot@chromium.org    friend class SkBench_AddPathTest; // perf test reversePathTo
1172a1a097ee814d05a92487d85db8ad02e1d852fd6fcommit-bot@chromium.org    friend class PathTest_Private; // unit test reversePathTo
1173da707bf5635c70d4c3c284a0b05d92489b76788ecaryclark    friend class ForceIsRRect_Private; // unit test isRRect
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1177