SkPath.h revision 020b25becb4a99061e8643780c887ad472eb0648
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2006 The Android Open Source Project
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SkPath_DEFINED
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SkPath_DEFINED
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkInstCnt.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMatrix.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTDArray.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkRefCnt.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SK_BUILD_FOR_ANDROID
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_INC              fGenerationID++
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_PTR_INC(ptr)     (ptr)->fGenerationID++
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_INC
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GEN_ID_PTR_INC(ptr)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkReader32;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkWriter32;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkAutoPathBoundsUpdate;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SkString;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPathRef;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkRRect;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SK_DEBUG_PATH_REF
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #define SK_DEBUG_PATH_REF 0
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** \class SkPath
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    The SkPath class encapsulates compound (multiple contour) geometric paths
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consisting of straight line segments, quadratic curves, and cubic curves.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SK_API SkPath {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SK_DECLARE_INST_COUNT_ROOT(SkPath);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath(const SkPath&);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~SkPath();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath& operator=(const SkPath&);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend  SK_API bool operator==(const SkPath&, const SkPath&);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend bool operator!=(const SkPath& a, const SkPath& b) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return !(a == b);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enum FillType {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /** Specifies that "inside" is computed by a non-zero sum of signed
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            edge crossings
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        */
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kWinding_FillType,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /** Specifies that "inside" is computed by an odd number of edge
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            crossings
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        */
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kEvenOdd_FillType,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /** Same as Winding, but draws outside of the path, rather than inside
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kInverseWinding_FillType,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /** Same as EvenOdd, but draws outside of the path, rather than inside
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kInverseEvenOdd_FillType
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Return the path's fill type. This is used to define how "inside" is
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        computed. The default value is kWinding_FillType.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return the path's fill type
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillType getFillType() const { return (FillType)fFillType; }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Set the path's fill type. This is used to define how "inside" is
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        computed. The default value is kWinding_FillType.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param ft The new fill type for this path
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void setFillType(FillType ft) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fFillType = SkToU8(ft);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GEN_ID_INC;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns true if the filltype is one of the Inverse variants */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Toggle between inverse and normal filltypes. This reverse the return
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  value of isInverseFillType()
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void toggleInverseFillType() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fFillType ^= 2;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GEN_ID_INC;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum Convexity {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kUnknown_Convexity,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kConvex_Convexity,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kConcave_Convexity
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Return the path's convexity, as stored in the path. If it is currently unknown,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  then this function will attempt to compute the convexity (and cache the result).
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Convexity getConvexity() const {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (kUnknown_Convexity != fConvexity) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return static_cast<Convexity>(fConvexity);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return this->internalGetConvexity();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Return the currently cached value for convexity, even if that is set to
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kUnknown_Convexity. Note: getConvexity() will automatically call
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  ComputeConvexity and cache its return value if the current setting is
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kUnknown.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Store a convexity setting in the path. There is no automatic check to
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  see if this value actually agrees with the return value that would be
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  computed by getConvexity().
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Note: even if this is set to a "known" value, if the path is later
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  reset to kUnknown_Convexity.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void setConvexity(Convexity);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  DEPRECATED: use getConvexity()
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns true if the path is flagged as being convex. This is not a
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  confirmed by any analysis, it is just the value set earlier.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isConvex() const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return kConvex_Convexity == this->getConvexity();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  DEPRECATED: use setConvexity()
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Set the isConvex flag to true or false. Convex paths may draw faster if
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  this flag is set, though setting this to true on a path that is in fact
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  not convex can give undefined results when drawn. Paths default to
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  isConvex == false
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void setIsConvex(bool isConvex) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns true if the path is an oval.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param rect      returns the bounding rect of this oval. It's a circle
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *                  if the height and width are the same.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @return true if this path is an oval.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *              Tracking whether a path is an oval is considered an
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *              optimization for performance and so some paths that are in
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *              fact ovals can report false.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isOval(SkRect* rect) const;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Clear any lines and curves from the path, making it empty. This frees up
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        internal storage associated with those segments.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This does NOT change the fill-type setting nor isConvex
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void reset();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Similar to reset(), in that all lines and curves are removed from the
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path. However, any internal storage for those lines/curves is retained,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        making reuse of the path potentially faster.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This does NOT change the fill-type setting nor isConvex
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void rewind();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns true if the path is empty (contains no lines or curves)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return true if the path is empty (contains no lines or curves)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isEmpty() const;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns true if all of the points in this path are finite, meaning there
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  are no infinities and no NaNs.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isFinite() const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (fBoundsIsDirty) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            this->computeBounds();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SkToBool(fIsFinite);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Test a line for zero length
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return true if the line is of zero length; otherwise false.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return p1.equalsWithinTolerance(p2);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Test a quad for zero length
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return true if the quad is of zero length; otherwise false.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const SkPoint& p3) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return p1.equalsWithinTolerance(p2) &&
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               p2.equalsWithinTolerance(p3);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Test a cubic curve for zero length
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return true if the cubic is of zero length; otherwise false.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const SkPoint& p3, const SkPoint& p4) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return p1.equalsWithinTolerance(p2) &&
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               p2.equalsWithinTolerance(p3) &&
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               p3.equalsWithinTolerance(p4);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns true if the path specifies a single line (i.e. it contains just
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  points in line[] to the end-points of the line. If the path is not a
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  line, returns false and ignores line[].
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isLine(SkPoint line[2]) const;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum Direction {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /** Direction either has not been or could not be computed */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kUnknown_Direction,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /** clockwise direction for adding closed contours */
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kCW_Direction,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /** counter-clockwise direction for adding closed contours */
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kCCW_Direction,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns true if the path specifies a rectangle. If so, and if rect is
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        not null, set rect to the bounds of the path. If the path does not
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        specify a rectangle, return false and ignore rect.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param rect If not null, returns the bounds of the path if it specifies
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    a rectangle
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return true if the path specifies a rectangle
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isRect(SkRect* rect) const {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return this->isRect(rect, NULL, NULL);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns true if the path specifies a rectangle.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  If this returns false, then all output parameters are ignored, and left
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  unchanged. If this returns true, then each of the output parameters
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  are checked for NULL. If they are not, they return their value.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param rect If not null, set to the bounds of the rectangle
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param isClosed If not null, set to true if the path is closed
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param direction If not null, set to the rectangle's direction
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @return true if the path specifies a rectangle
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isRect(SkRect* rect, bool* isClosed, Direction* direction) const;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns true if the path specifies a pair of nested rectangles. If so, and if
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     rectangle. If so, and dirs is not null, set dirs[0] to the direction of
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     the outer rectangle and dirs[1] to the direction of the inner rectangle. If
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     the path does not specify a pair of nested rectangles, return
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     false and ignore rect and dirs.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     @param rect If not null, returns the path as a pair of nested rectangles
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     @param dirs If not null, returns the direction of the rects
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     @return true if the path describes a pair of nested rectangles
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Return the number of points in the path
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int countPoints() const;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Return the point at the specified index. If the index is out of range
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         will be (0,0)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPoint getPoint(int index) const;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns the number of points in the path. Up to max points are copied.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param points If not null, receives up to max points
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param max The maximum number of points to copy into points
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return the actual number of points in the path
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int getPoints(SkPoint points[], int max) const;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Return the number of verbs in the path
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int countVerbs() const;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns the number of verbs in the path. Up to max verbs are copied. The
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        verbs are copied as one byte per verb.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param verbs If not null, receives up to max verbs
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param max The maximum number of verbs to copy into verbs
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @return the actual number of verbs in the path
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int getVerbs(uint8_t verbs[], int max) const;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //! Swap contents of this and other. Guaranteed not to throw
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void swap(SkPath& other);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Returns the bounds of the path's points. If the path contains 0 or 1
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Note: this bounds may be larger than the actual shape, since curves
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        do not extend as far as their control points.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkRect& getBounds() const {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (fBoundsIsDirty) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            this->computeBounds();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return fBounds;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Calling this will, if the internal cache of the bounds is out of date,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update it so that subsequent calls to getBounds will be instantaneous.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This also means that any copies or simple transformations of the path
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        will inherit the cached bounds.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void updateBoundsCache() const {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // for now, just calling getBounds() is sufficient
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->getBounds();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Does a conservative test to see whether a rectangle is inside a path. Currently it only
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * will ever return true for single convex contour paths. The empty-status of the rect is not
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the rect edge touches the path border are not considered containment violations.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool conservativelyContainsRect(const SkRect& rect) const;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  Construction methods
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Hint to the path to prepare for adding more points. This can allow the
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path to more efficiently grow its storage.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param extraPtCount The number of extra points the path should
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            preallocate for.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void incReserve(unsigned extraPtCount);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Set the beginning of the next contour to the point (x,y).
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param x    The x-coordinate of the start of a new contour
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param y    The y-coordinate of the start of a new contour
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void moveTo(SkScalar x, SkScalar y);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Set the beginning of the next contour to the point
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p    The start of a new contour
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void moveTo(const SkPoint& p) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->moveTo(p.fX, p.fY);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Set the beginning of the next contour relative to the last point on the
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        previous contour. If there is no previous contour, this is treated the
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        same as moveTo().
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dx   The amount to add to the x-coordinate of the end of the
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    previous contour, to specify the start of a new contour
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy   The amount to add to the y-coordinate of the end of the
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    previous contour, to specify the start of a new contour
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void rMoveTo(SkScalar dx, SkScalar dy);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Add a line from the last point to the specified point (x,y). If no
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        moveTo() call has been made for this contour, the first point is
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        automatically set to (0,0).
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param x    The x-coordinate of the end of a line
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param y    The y-coordinate of the end of a line
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void lineTo(SkScalar x, SkScalar y);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** Add a line from the last point to the specified point. If no moveTo()
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        call has been made for this contour, the first point is automatically
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set to (0,0).
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param p    The end of a line
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void lineTo(const SkPoint& p) {
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this->lineTo(p.fX, p.fY);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** Same as lineTo, but the coordinates are considered relative to the last
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        point on this contour. If there is no previous point, then a moveTo(0,0)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is inserted automatically.
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dx   The amount to add to the x-coordinate of the previous point
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    on this contour, to specify a line
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy   The amount to add to the y-coordinate of the previous point
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    on this contour, to specify a line
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void rLineTo(SkScalar dx, SkScalar dy);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Add a quadratic bezier from the last point, approaching control point
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this contour, the first point is automatically set to (0,0).
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param x1   The x-coordinate of the control point on a quadratic curve
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param y1   The y-coordinate of the control point on a quadratic curve
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param x2   The x-coordinate of the end point on a quadratic curve
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param y2   The y-coordinate of the end point on a quadratic curve
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Add a quadratic bezier from the last point, approaching control point
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p1, and ending at p2. If no moveTo() call has been made for this
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contour, the first point is automatically set to (0,0).
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p1   The control point on a quadratic curve
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p2   The end point on a quadratic curve
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void quadTo(const SkPoint& p1, const SkPoint& p2) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Same as quadTo, but the coordinates are considered relative to the last
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        point on this contour. If there is no previous point, then a moveTo(0,0)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is inserted automatically.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dx1   The amount to add to the x-coordinate of the last point on
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this contour, to specify the control point of a quadratic curve
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy1   The amount to add to the y-coordinate of the last point on
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this contour, to specify the control point of a quadratic curve
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param dx2   The amount to add to the x-coordinate of the last point on
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     this contour, to specify the end point of a quadratic curve
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy2   The amount to add to the y-coordinate of the last point on
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     this contour, to specify the end point of a quadratic curve
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 SkScalar w);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  SkScalar w);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Add a cubic bezier from the last point, approaching control points
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        made for this contour, the first point is automatically set to (0,0).
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param x1   The x-coordinate of the 1st control point on a cubic curve
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param y1   The y-coordinate of the 1st control point on a cubic curve
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param x2   The x-coordinate of the 2nd control point on a cubic curve
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param y2   The y-coordinate of the 2nd control point on a cubic curve
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param x3   The x-coordinate of the end point on a cubic curve
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param y3   The y-coordinate of the end point on a cubic curve
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    */
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 SkScalar x3, SkScalar y3);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Add a cubic bezier from the last point, approaching control points p1
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        and p2, and ending at p3. If no moveTo() call has been made for this
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contour, the first point is automatically set to (0,0).
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p1   The 1st control point on a cubic curve
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p2   The 2nd control point on a cubic curve
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param p3   The end point on a cubic curve
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Same as cubicTo, but the coordinates are considered relative to the
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current point on this contour. If there is no previous point, then a
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        moveTo(0,0) is inserted automatically.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dx1   The amount to add to the x-coordinate of the last point on
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this contour, to specify the 1st control point of a cubic curve
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy1   The amount to add to the y-coordinate of the last point on
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this contour, to specify the 1st control point of a cubic curve
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dx2   The amount to add to the x-coordinate of the last point on
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                this contour, to specify the 2nd control point of a cubic curve
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param dy2   The amount to add to the y-coordinate of the last point on
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                this contour, to specify the 2nd control point of a cubic curve
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param dx3   The amount to add to the x-coordinate of the last point on
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     this contour, to specify the end point of a cubic curve
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @param dy3   The amount to add to the y-coordinate of the last point on
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     this contour, to specify the end point of a cubic curve
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    */
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void    rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SkScalar x3, SkScalar y3);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Append the specified arc to the path as a new contour. If the start of
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        the path is different from the path's current last point, then an
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        automatic lineTo() is added to connect the current contour to the start
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        of the arc. However, if the path is empty, then we call moveTo() with
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        the first point of the arc. The sweep angle is treated mod 360.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param oval The bounding oval defining the shape and size of the arc
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param startAngle Starting angle (in degrees) where the arc begins
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          treated mod 360.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        @param forceMoveTo If true, always begin a new contour with the arc
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void    arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bool forceMoveTo);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Append a line and arc to the current path. This is the same as the
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PostScript call "arct".
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               SkScalar radius);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** Append a line and arc to the current path. This is the same as the
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PostScript call "arct".
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** Close the current contour. If the current point is not equal to the
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        first point of the contour, a line segment is automatically added.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void close();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Return the opposite of the specified direction. kUnknown is its own
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  opposite.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static Direction OppositeDirection(Direction dir) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static const Direction gOppositeDir[] = {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kUnknown_Direction, kCCW_Direction, kCW_Direction
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        };
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return gOppositeDir[dir];
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns whether or not a fill type is inverted
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kWinding_FillType        -> false
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kEvenOdd_FillType        -> false
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kInverseWinding_FillType -> true
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kInverseEvenOdd_FillType -> true
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool IsInverseFillType(FillType fill) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (fill & 2) != 0;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns the equivalent non-inverted fill type to the given fill type
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kWinding_FillType        -> kWinding_FillType
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kEvenOdd_FillType        -> kEvenOdd_FillType
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kInverseWinding_FillType -> kWinding_FillType
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static FillType ConvertToNonInverseFillType(FillType fill) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (FillType)(fill & 1);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Tries to quickly compute the direction of the first non-degenerate
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  contour. If it can be computed, return true and set dir to that
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  direction. If it cannot be (quickly) determined, return false and ignore
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  the dir parameter. If the direction was determined, it is cached to make
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  subsequent calls return quickly.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cheapComputeDirection(Direction* dir) const;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Returns true if the path's direction can be computed via
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  cheapComputDirection() and if that computed direction matches the
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  specified direction. If dir is kUnknown, returns true if the direction
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  cannot be computed.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cheapIsDirection(Direction dir) const {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Direction computedDir = kUnknown_Direction;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (void)this->cheapComputeDirection(&computedDir);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return computedDir == dir;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Add a closed rectangle contour to the path
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param rect The rectangle to add as a closed contour to the path
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param dir  The direction to wind the rectangle's contour. Cannot be
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *              kUnknown_Direction.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void    addRect(const SkRect& rect, Direction dir = kCW_Direction);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  Add a closed rectangle contour to the path
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param left     The left side of a rectangle to add as a closed contour
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *                  to the path
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param top      The top of a rectangle to add as a closed contour to the
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *                  path
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param right    The right side of a rectangle to add as a closed contour
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *                  to the path
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param bottom   The bottom of a rectangle to add as a closed contour to
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *                  the path
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *  @param dir  The direction to wind the rectangle's contour. Cannot be
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *              kUnknown_Direction.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
627    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
628                 Direction dir = kCW_Direction);
629
630    /**
631     *  Add a closed oval contour to the path
632     *
633     *  @param oval The bounding oval to add as a closed contour to the path
634     *  @param dir  The direction to wind the oval's contour. Cannot be
635     *              kUnknown_Direction.
636     */
637    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
638
639    /**
640     *  Add a closed circle contour to the path
641     *
642     *  @param x        The x-coordinate of the center of a circle to add as a
643     *                  closed contour to the path
644     *  @param y        The y-coordinate of the center of a circle to add as a
645     *                  closed contour to the path
646     *  @param radius   The radius of a circle to add as a closed contour to the
647     *                  path
648     *  @param dir  The direction to wind the circle's contour. Cannot be
649     *              kUnknown_Direction.
650     */
651    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
652                   Direction dir = kCW_Direction);
653
654    /** Add the specified arc to the path as a new contour.
655
656        @param oval The bounds of oval used to define the size of the arc
657        @param startAngle Starting angle (in degrees) where the arc begins
658        @param sweepAngle Sweep angle (in degrees) measured clockwise
659    */
660    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
661
662    /**
663     *  Add a closed round-rectangle contour to the path
664     *  @param rect The bounds of a round-rectangle to add as a closed contour
665     *  @param rx   The x-radius of the rounded corners on the round-rectangle
666     *  @param ry   The y-radius of the rounded corners on the round-rectangle
667     *  @param dir  The direction to wind the rectangle's contour. Cannot be
668     *              kUnknown_Direction.
669     */
670    void    addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
671                         Direction dir = kCW_Direction);
672
673    /**
674     *  Add a closed round-rectangle contour to the path. Each corner receives
675     *  two radius values [X, Y]. The corners are ordered top-left, top-right,
676     *  bottom-right, bottom-left.
677     *  @param rect The bounds of a round-rectangle to add as a closed contour
678     *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
679     *  @param dir  The direction to wind the rectangle's contour. Cannot be
680     *              kUnknown_Direction.
681     * Note: The radii here now go through the same constraint handling as the
682     *       SkRRect radii (i.e., either radii at a corner being 0 implies a
683     *       sqaure corner and oversized radii are proportionally scaled down).
684     */
685    void addRoundRect(const SkRect& rect, const SkScalar radii[],
686                      Direction dir = kCW_Direction);
687
688    /**
689     *  Add an SkRRect contour to the path
690     *  @param rrect The rounded rect to add as a closed contour
691     *  @param dir   The winding direction for the new contour. Cannot be
692     *               kUnknown_Direction.
693     */
694    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
695
696    /**
697     *  Add a new contour made of just lines. This is just a fast version of
698     *  the following:
699     *      this->moveTo(pts[0]);
700     *      for (int i = 1; i < count; ++i) {
701     *          this->lineTo(pts[i]);
702     *      }
703     *      if (close) {
704     *          this->close();
705     *      }
706     */
707    void addPoly(const SkPoint pts[], int count, bool close);
708
709    /** Add a copy of src to the path, offset by (dx,dy)
710        @param src  The path to add as a new contour
711        @param dx   The amount to translate the path in X as it is added
712        @param dx   The amount to translate the path in Y as it is added
713    */
714    void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
715
716    /** Add a copy of src to the path
717    */
718    void addPath(const SkPath& src) {
719        SkMatrix m;
720        m.reset();
721        this->addPath(src, m);
722    }
723
724    /** Add a copy of src to the path, transformed by matrix
725        @param src  The path to add as a new contour
726    */
727    void addPath(const SkPath& src, const SkMatrix& matrix);
728
729    /**
730     *  Same as addPath(), but reverses the src input
731     */
732    void reverseAddPath(const SkPath& src);
733
734    /** Offset the path by (dx,dy), returning true on success
735
736        @param dx   The amount in the X direction to offset the entire path
737        @param dy   The amount in the Y direction to offset the entire path
738        @param dst  The translated path is written here
739    */
740    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
741
742    /** Offset the path by (dx,dy), returning true on success
743
744        @param dx   The amount in the X direction to offset the entire path
745        @param dy   The amount in the Y direction to offset the entire path
746    */
747    void offset(SkScalar dx, SkScalar dy) {
748        this->offset(dx, dy, this);
749    }
750
751    /** Transform the points in this path by matrix, and write the answer into
752        dst.
753
754        @param matrix   The matrix to apply to the path
755        @param dst      The transformed path is written here
756    */
757    void transform(const SkMatrix& matrix, SkPath* dst) const;
758
759    /** Transform the points in this path by matrix
760
761        @param matrix The matrix to apply to the path
762    */
763    void transform(const SkMatrix& matrix) {
764        this->transform(matrix, this);
765    }
766
767    /** Return the last point on the path. If no points have been added, (0,0)
768        is returned. If there are no points, this returns false, otherwise it
769        returns true.
770
771        @param lastPt   The last point on the path is returned here
772    */
773    bool getLastPt(SkPoint* lastPt) const;
774
775    /** Set the last point on the path. If no points have been added,
776        moveTo(x,y) is automatically called.
777
778        @param x    The new x-coordinate for the last point
779        @param y    The new y-coordinate for the last point
780    */
781    void setLastPt(SkScalar x, SkScalar y);
782
783    /** Set the last point on the path. If no points have been added, moveTo(p)
784        is automatically called.
785
786        @param p    The new location for the last point
787    */
788    void setLastPt(const SkPoint& p) {
789        this->setLastPt(p.fX, p.fY);
790    }
791
792    enum SegmentMask {
793        kLine_SegmentMask   = 1 << 0,
794        kQuad_SegmentMask   = 1 << 1,
795        kConic_SegmentMask  = 1 << 2,
796        kCubic_SegmentMask  = 1 << 3,
797    };
798
799    /**
800     *  Returns a mask, where each bit corresponding to a SegmentMask is
801     *  set if the path contains 1 or more segments of that type.
802     *  Returns 0 for an empty path (no segments).
803     */
804    uint32_t getSegmentMasks() const { return fSegmentMask; }
805
806    enum Verb {
807        kMove_Verb,     //!< iter.next returns 1 point
808        kLine_Verb,     //!< iter.next returns 2 points
809        kQuad_Verb,     //!< iter.next returns 3 points
810        kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
811        kCubic_Verb,    //!< iter.next returns 4 points
812        kClose_Verb,    //!< iter.next returns 1 point (contour's moveTo pt)
813        kDone_Verb,     //!< iter.next returns 0 points
814    };
815
816    /** Iterate through all of the segments (lines, quadratics, cubics) of
817        each contours in a path.
818
819        The iterator cleans up the segments along the way, removing degenerate
820        segments and adding close verbs where necessary. When the forceClose
821        argument is provided, each contour (as defined by a new starting
822        move command) will be completed with a close verb regardless of the
823        contour's contents.
824    */
825    class SK_API Iter {
826    public:
827        Iter();
828        Iter(const SkPath&, bool forceClose);
829
830        void setPath(const SkPath&, bool forceClose);
831
832        /** Return the next verb in this iteration of the path. When all
833            segments have been visited, return kDone_Verb.
834
835            @param  pts The points representing the current verb and/or segment
836            @param doConsumeDegerates If true, first scan for segments that are
837                   deemed degenerate (too short) and skip those.
838            @return The verb for the current segment
839        */
840        Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
841            if (doConsumeDegerates) {
842                this->consumeDegenerateSegments();
843            }
844            return this->doNext(pts);
845        }
846
847        /**
848         *  Return the weight for the current conic. Only valid if the current
849         *  segment return by next() was a conic.
850         */
851        SkScalar conicWeight() const { return *fConicWeights; }
852
853        /** If next() returns kLine_Verb, then this query returns true if the
854            line was the result of a close() command (i.e. the end point is the
855            initial moveto for this contour). If next() returned a different
856            verb, this returns an undefined value.
857
858            @return If the last call to next() returned kLine_Verb, return true
859                    if it was the result of an explicit close command.
860        */
861        bool isCloseLine() const { return SkToBool(fCloseLine); }
862
863        /** Returns true if the current contour is closed (has a kClose_Verb)
864            @return true if the current contour is closed (has a kClose_Verb)
865        */
866        bool isClosedContour() const;
867
868    private:
869        const SkPoint*  fPts;
870        const uint8_t*  fVerbs;
871        const uint8_t*  fVerbStop;
872        const SkScalar* fConicWeights;
873        SkPoint         fMoveTo;
874        SkPoint         fLastPt;
875        SkBool8         fForceClose;
876        SkBool8         fNeedClose;
877        SkBool8         fCloseLine;
878        SkBool8         fSegmentState;
879
880        inline const SkPoint& cons_moveTo();
881        Verb autoClose(SkPoint pts[2]);
882        void consumeDegenerateSegments();
883        Verb doNext(SkPoint pts[4]);
884    };
885
886    /** Iterate through the verbs in the path, providing the associated points.
887    */
888    class SK_API RawIter {
889    public:
890        RawIter();
891        RawIter(const SkPath&);
892
893        void setPath(const SkPath&);
894
895        /** Return the next verb in this iteration of the path. When all
896            segments have been visited, return kDone_Verb.
897
898            @param  pts The points representing the current verb and/or segment
899                        This must not be NULL.
900            @return The verb for the current segment
901        */
902        Verb next(SkPoint pts[4]);
903
904        SkScalar conicWeight() const { return *fConicWeights; }
905
906    private:
907        const SkPoint*  fPts;
908        const uint8_t*  fVerbs;
909        const uint8_t*  fVerbStop;
910        const SkScalar* fConicWeights;
911        SkPoint         fMoveTo;
912        SkPoint         fLastPt;
913    };
914
915    /**
916     *  Returns true if the point { x, y } is contained by the path, taking into
917     *  account the FillType.
918     */
919    bool contains(SkScalar x, SkScalar y) const;
920
921    void dump(bool forceClose, const char title[] = NULL) const;
922    void dump() const;
923
924    /**
925     *  Write the region to the buffer, and return the number of bytes written.
926     *  If buffer is NULL, it still returns the number of bytes.
927     */
928    uint32_t writeToMemory(void* buffer) const;
929    /**
930     *  Initialized the region from the buffer, returning the number
931     *  of bytes actually read.
932     */
933    uint32_t readFromMemory(const void* buffer);
934
935#ifdef SK_BUILD_FOR_ANDROID
936    uint32_t getGenerationID() const;
937    const SkPath* getSourcePath() const;
938    void setSourcePath(const SkPath* path);
939#endif
940
941    SkDEBUGCODE(void validate() const;)
942
943private:
944    enum SerializationOffsets {
945        kDirection_SerializationShift = 26, // requires 2 bits
946        kIsFinite_SerializationShift = 25,  // requires 1 bit
947        kIsOval_SerializationShift = 24,    // requires 1 bit
948        kConvexity_SerializationShift = 16, // requires 2 bits
949        kFillType_SerializationShift = 8,   // requires 2 bits
950        kSegmentMask_SerializationShift = 0 // requires 4 bits
951    };
952
953#if SK_DEBUG_PATH_REF
954public:
955    /** Debugging wrapper for SkAutoTUnref<SkPathRef> used to track owners (SkPaths)
956        of SkPathRefs */
957    class PathRefDebugRef {
958    public:
959        PathRefDebugRef(SkPath* owner);
960        PathRefDebugRef(SkPathRef* pr, SkPath* owner);
961        ~PathRefDebugRef();
962        void reset(SkPathRef* ref);
963        void swap(PathRefDebugRef* other);
964        SkPathRef* get() const;
965        SkAutoTUnref<SkPathRef>::BlockRefType *operator->() const;
966        operator SkPathRef*();
967    private:
968        SkAutoTUnref<SkPathRef>   fPathRef;
969        SkPath*                   fOwner;
970    };
971
972private:
973    PathRefDebugRef     fPathRef;
974#else
975    SkAutoTUnref<SkPathRef> fPathRef;
976#endif
977
978    mutable SkRect      fBounds;
979    int                 fLastMoveToIndex;
980    uint8_t             fFillType;
981    uint8_t             fSegmentMask;
982    mutable uint8_t     fBoundsIsDirty;
983    mutable uint8_t     fConvexity;
984    mutable uint8_t     fDirection;
985    mutable SkBool8     fIsFinite;    // only meaningful if bounds are valid
986    mutable SkBool8     fIsOval;
987#ifdef SK_BUILD_FOR_ANDROID
988    uint32_t            fGenerationID;
989    const SkPath*       fSourcePath;
990#endif
991
992    /** Resets all fields other than fPathRef to their initial 'empty' values.
993     *  Assumes the caller has already emptied fPathRef.
994     *  On Android increments fGenerationID without reseting it.
995     */
996    void resetFields();
997
998    /** Sets all fields other than fPathRef to the values in 'that'.
999     *  Assumes the caller has already set fPathRef.
1000     *  On Android increments fGenerationID without copying it.
1001     *  On Android sets fSourcePath to NULL.
1002     */
1003    void copyFields(const SkPath& that);
1004
1005    // called, if dirty, by getBounds()
1006    void computeBounds() const;
1007
1008    friend class Iter;
1009
1010    friend class SkPathStroker;
1011    /*  Append the first contour of path, ignoring path's initial point. If no
1012        moveTo() call has been made for this contour, the first point is
1013        automatically set to (0,0).
1014    */
1015    void pathTo(const SkPath& path);
1016
1017    /*  Append, in reverse order, the first contour of path, ignoring path's
1018        last point. If no moveTo() call has been made for this contour, the
1019        first point is automatically set to (0,0).
1020    */
1021    void reversePathTo(const SkPath&);
1022
1023    // called before we add points for lineTo, quadTo, cubicTo, checking to see
1024    // if we need to inject a leading moveTo first
1025    //
1026    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
1027    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
1028    //
1029    inline void injectMoveToIfNeeded();
1030
1031    inline bool hasOnlyMoveTos() const;
1032
1033    Convexity internalGetConvexity() const;
1034
1035    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
1036                       bool* isClosed, Direction* direction) const;
1037
1038    friend class SkAutoPathBoundsUpdate;
1039    friend class SkAutoDisableOvalCheck;
1040    friend class SkAutoDisableDirectionCheck;
1041    friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo
1042};
1043
1044#endif
1045