gfx/skia/trunk/include/core/SkPath.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkPath.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1049 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#ifndef SkPath_DEFINED
    1.14 +#define SkPath_DEFINED
    1.15 +
    1.16 +#include "SkInstCnt.h"
    1.17 +#include "SkMatrix.h"
    1.18 +#include "SkPathRef.h"
    1.19 +#include "SkTDArray.h"
    1.20 +#include "SkRefCnt.h"
    1.21 +
    1.22 +class SkReader32;
    1.23 +class SkWriter32;
    1.24 +class SkAutoPathBoundsUpdate;
    1.25 +class SkString;
    1.26 +class SkRRect;
    1.27 +
    1.28 +/** \class SkPath
    1.29 +
    1.30 +    The SkPath class encapsulates compound (multiple contour) geometric paths
    1.31 +    consisting of straight line segments, quadratic curves, and cubic curves.
    1.32 +*/
    1.33 +class SK_API SkPath {
    1.34 +public:
    1.35 +    SK_DECLARE_INST_COUNT_ROOT(SkPath);
    1.36 +
    1.37 +    SkPath();
    1.38 +    SkPath(const SkPath&);
    1.39 +    ~SkPath();
    1.40 +
    1.41 +    SkPath& operator=(const SkPath&);
    1.42 +    friend  SK_API bool operator==(const SkPath&, const SkPath&);
    1.43 +    friend bool operator!=(const SkPath& a, const SkPath& b) {
    1.44 +        return !(a == b);
    1.45 +    }
    1.46 +
    1.47 +    enum FillType {
    1.48 +        /** Specifies that "inside" is computed by a non-zero sum of signed
    1.49 +            edge crossings
    1.50 +        */
    1.51 +        kWinding_FillType,
    1.52 +        /** Specifies that "inside" is computed by an odd number of edge
    1.53 +            crossings
    1.54 +        */
    1.55 +        kEvenOdd_FillType,
    1.56 +        /** Same as Winding, but draws outside of the path, rather than inside
    1.57 +        */
    1.58 +        kInverseWinding_FillType,
    1.59 +        /** Same as EvenOdd, but draws outside of the path, rather than inside
    1.60 +         */
    1.61 +        kInverseEvenOdd_FillType
    1.62 +    };
    1.63 +
    1.64 +    /** Return the path's fill type. This is used to define how "inside" is
    1.65 +        computed. The default value is kWinding_FillType.
    1.66 +
    1.67 +        @return the path's fill type
    1.68 +    */
    1.69 +    FillType getFillType() const { return (FillType)fFillType; }
    1.70 +
    1.71 +    /** Set the path's fill type. This is used to define how "inside" is
    1.72 +        computed. The default value is kWinding_FillType.
    1.73 +
    1.74 +        @param ft The new fill type for this path
    1.75 +    */
    1.76 +    void setFillType(FillType ft) {
    1.77 +        fFillType = SkToU8(ft);
    1.78 +    }
    1.79 +
    1.80 +    /** Returns true if the filltype is one of the Inverse variants */
    1.81 +    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
    1.82 +
    1.83 +    /**
    1.84 +     *  Toggle between inverse and normal filltypes. This reverse the return
    1.85 +     *  value of isInverseFillType()
    1.86 +     */
    1.87 +    void toggleInverseFillType() {
    1.88 +        fFillType ^= 2;
    1.89 +    }
    1.90 +
    1.91 +    enum Convexity {
    1.92 +        kUnknown_Convexity,
    1.93 +        kConvex_Convexity,
    1.94 +        kConcave_Convexity
    1.95 +    };
    1.96 +
    1.97 +    /**
    1.98 +     *  Return the path's convexity, as stored in the path. If it is currently unknown,
    1.99 +     *  then this function will attempt to compute the convexity (and cache the result).
   1.100 +     */
   1.101 +    Convexity getConvexity() const {
   1.102 +        if (kUnknown_Convexity != fConvexity) {
   1.103 +            return static_cast<Convexity>(fConvexity);
   1.104 +        } else {
   1.105 +            return this->internalGetConvexity();
   1.106 +        }
   1.107 +    }
   1.108 +
   1.109 +    /**
   1.110 +     *  Return the currently cached value for convexity, even if that is set to
   1.111 +     *  kUnknown_Convexity. Note: getConvexity() will automatically call
   1.112 +     *  ComputeConvexity and cache its return value if the current setting is
   1.113 +     *  kUnknown.
   1.114 +     */
   1.115 +    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
   1.116 +
   1.117 +    /**
   1.118 +     *  Store a convexity setting in the path. There is no automatic check to
   1.119 +     *  see if this value actually agrees with the return value that would be
   1.120 +     *  computed by getConvexity().
   1.121 +     *
   1.122 +     *  Note: even if this is set to a "known" value, if the path is later
   1.123 +     *  changed (e.g. lineTo(), addRect(), etc.) then the cached value will be
   1.124 +     *  reset to kUnknown_Convexity.
   1.125 +     */
   1.126 +    void setConvexity(Convexity);
   1.127 +
   1.128 +    /**
   1.129 +     *  Returns true if the path is flagged as being convex. This is not a
   1.130 +     *  confirmed by any analysis, it is just the value set earlier.
   1.131 +     */
   1.132 +    bool isConvex() const {
   1.133 +        return kConvex_Convexity == this->getConvexity();
   1.134 +    }
   1.135 +
   1.136 +    /**
   1.137 +     *  Set the isConvex flag to true or false. Convex paths may draw faster if
   1.138 +     *  this flag is set, though setting this to true on a path that is in fact
   1.139 +     *  not convex can give undefined results when drawn. Paths default to
   1.140 +     *  isConvex == false
   1.141 +     */
   1.142 +    SK_ATTR_DEPRECATED("use setConvexity")
   1.143 +    void setIsConvex(bool isConvex) {
   1.144 +        this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
   1.145 +    }
   1.146 +
   1.147 +    /** Returns true if the path is an oval.
   1.148 +     *
   1.149 +     * @param rect      returns the bounding rect of this oval. It's a circle
   1.150 +     *                  if the height and width are the same.
   1.151 +     *
   1.152 +     * @return true if this path is an oval.
   1.153 +     *              Tracking whether a path is an oval is considered an
   1.154 +     *              optimization for performance and so some paths that are in
   1.155 +     *              fact ovals can report false.
   1.156 +     */
   1.157 +    bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
   1.158 +
   1.159 +    /** Clear any lines and curves from the path, making it empty. This frees up
   1.160 +        internal storage associated with those segments.
   1.161 +        On Android, does not change fSourcePath.
   1.162 +    */
   1.163 +    void reset();
   1.164 +
   1.165 +    /** Similar to reset(), in that all lines and curves are removed from the
   1.166 +        path. However, any internal storage for those lines/curves is retained,
   1.167 +        making reuse of the path potentially faster.
   1.168 +        On Android, does not change fSourcePath.
   1.169 +    */
   1.170 +    void rewind();
   1.171 +
   1.172 +    /** Returns true if the path is empty (contains no lines or curves)
   1.173 +
   1.174 +        @return true if the path is empty (contains no lines or curves)
   1.175 +    */
   1.176 +    bool isEmpty() const {
   1.177 +        SkDEBUGCODE(this->validate();)
   1.178 +        return 0 == fPathRef->countVerbs();
   1.179 +    }
   1.180 +
   1.181 +    /**
   1.182 +     *  Returns true if all of the points in this path are finite, meaning there
   1.183 +     *  are no infinities and no NaNs.
   1.184 +     */
   1.185 +    bool isFinite() const {
   1.186 +        SkDEBUGCODE(this->validate();)
   1.187 +        return fPathRef->isFinite();
   1.188 +    }
   1.189 +
   1.190 +    /** Test a line for zero length
   1.191 +
   1.192 +        @return true if the line is of zero length; otherwise false.
   1.193 +    */
   1.194 +    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) {
   1.195 +        return p1.equalsWithinTolerance(p2);
   1.196 +    }
   1.197 +
   1.198 +    /** Test a quad for zero length
   1.199 +
   1.200 +        @return true if the quad is of zero length; otherwise false.
   1.201 +    */
   1.202 +    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
   1.203 +                                 const SkPoint& p3) {
   1.204 +        return p1.equalsWithinTolerance(p2) &&
   1.205 +               p2.equalsWithinTolerance(p3);
   1.206 +    }
   1.207 +
   1.208 +    /** Test a cubic curve for zero length
   1.209 +
   1.210 +        @return true if the cubic is of zero length; otherwise false.
   1.211 +    */
   1.212 +    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
   1.213 +                                  const SkPoint& p3, const SkPoint& p4) {
   1.214 +        return p1.equalsWithinTolerance(p2) &&
   1.215 +               p2.equalsWithinTolerance(p3) &&
   1.216 +               p3.equalsWithinTolerance(p4);
   1.217 +    }
   1.218 +
   1.219 +    /**
   1.220 +     *  Returns true if the path specifies a single line (i.e. it contains just
   1.221 +     *  a moveTo and a lineTo). If so, and line[] is not null, it sets the 2
   1.222 +     *  points in line[] to the end-points of the line. If the path is not a
   1.223 +     *  line, returns false and ignores line[].
   1.224 +     */
   1.225 +    bool isLine(SkPoint line[2]) const;
   1.226 +
   1.227 +    /** Returns true if the path specifies a rectangle. If so, and if rect is
   1.228 +        not null, set rect to the bounds of the path. If the path does not
   1.229 +        specify a rectangle, return false and ignore rect.
   1.230 +
   1.231 +        @param rect If not null, returns the bounds of the path if it specifies
   1.232 +                    a rectangle
   1.233 +        @return true if the path specifies a rectangle
   1.234 +    */
   1.235 +    bool isRect(SkRect* rect) const;
   1.236 +
   1.237 +    /** Return the number of points in the path
   1.238 +     */
   1.239 +    int countPoints() const;
   1.240 +
   1.241 +    /** Return the point at the specified index. If the index is out of range
   1.242 +         (i.e. is not 0 <= index < countPoints()) then the returned coordinates
   1.243 +         will be (0,0)
   1.244 +     */
   1.245 +    SkPoint getPoint(int index) const;
   1.246 +
   1.247 +    /** Returns the number of points in the path. Up to max points are copied.
   1.248 +
   1.249 +        @param points If not null, receives up to max points
   1.250 +        @param max The maximum number of points to copy into points
   1.251 +        @return the actual number of points in the path
   1.252 +    */
   1.253 +    int getPoints(SkPoint points[], int max) const;
   1.254 +
   1.255 +    /** Return the number of verbs in the path
   1.256 +     */
   1.257 +    int countVerbs() const;
   1.258 +
   1.259 +    /** Returns the number of verbs in the path. Up to max verbs are copied. The
   1.260 +        verbs are copied as one byte per verb.
   1.261 +
   1.262 +        @param verbs If not null, receives up to max verbs
   1.263 +        @param max The maximum number of verbs to copy into verbs
   1.264 +        @return the actual number of verbs in the path
   1.265 +    */
   1.266 +    int getVerbs(uint8_t verbs[], int max) const;
   1.267 +
   1.268 +    //! Swap contents of this and other. Guaranteed not to throw
   1.269 +    void swap(SkPath& other);
   1.270 +
   1.271 +    /** Returns the bounds of the path's points. If the path contains 0 or 1
   1.272 +        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
   1.273 +        Note: this bounds may be larger than the actual shape, since curves
   1.274 +        do not extend as far as their control points.
   1.275 +    */
   1.276 +    const SkRect& getBounds() const {
   1.277 +        return fPathRef->getBounds();
   1.278 +    }
   1.279 +
   1.280 +    /** Calling this will, if the internal cache of the bounds is out of date,
   1.281 +        update it so that subsequent calls to getBounds will be instantaneous.
   1.282 +        This also means that any copies or simple transformations of the path
   1.283 +        will inherit the cached bounds.
   1.284 +     */
   1.285 +    void updateBoundsCache() const {
   1.286 +        // for now, just calling getBounds() is sufficient
   1.287 +        this->getBounds();
   1.288 +    }
   1.289 +
   1.290 +    /**
   1.291 +     * Does a conservative test to see whether a rectangle is inside a path. Currently it only
   1.292 +     * will ever return true for single convex contour paths. The empty-status of the rect is not
   1.293 +     * considered (e.g. a rect that is a point can be inside a path). Points or line segments where
   1.294 +     * the rect edge touches the path border are not considered containment violations.
   1.295 +     */
   1.296 +    bool conservativelyContainsRect(const SkRect& rect) const;
   1.297 +
   1.298 +    //  Construction methods
   1.299 +
   1.300 +    /** Hint to the path to prepare for adding more points. This can allow the
   1.301 +        path to more efficiently grow its storage.
   1.302 +
   1.303 +        @param extraPtCount The number of extra points the path should
   1.304 +                            preallocate for.
   1.305 +    */
   1.306 +    void incReserve(unsigned extraPtCount);
   1.307 +
   1.308 +    /** Set the beginning of the next contour to the point (x,y).
   1.309 +
   1.310 +        @param x    The x-coordinate of the start of a new contour
   1.311 +        @param y    The y-coordinate of the start of a new contour
   1.312 +    */
   1.313 +    void moveTo(SkScalar x, SkScalar y);
   1.314 +
   1.315 +    /** Set the beginning of the next contour to the point
   1.316 +
   1.317 +        @param p    The start of a new contour
   1.318 +    */
   1.319 +    void moveTo(const SkPoint& p) {
   1.320 +        this->moveTo(p.fX, p.fY);
   1.321 +    }
   1.322 +
   1.323 +    /** Set the beginning of the next contour relative to the last point on the
   1.324 +        previous contour. If there is no previous contour, this is treated the
   1.325 +        same as moveTo().
   1.326 +
   1.327 +        @param dx   The amount to add to the x-coordinate of the end of the
   1.328 +                    previous contour, to specify the start of a new contour
   1.329 +        @param dy   The amount to add to the y-coordinate of the end of the
   1.330 +                    previous contour, to specify the start of a new contour
   1.331 +    */
   1.332 +    void rMoveTo(SkScalar dx, SkScalar dy);
   1.333 +
   1.334 +    /** Add a line from the last point to the specified point (x,y). If no
   1.335 +        moveTo() call has been made for this contour, the first point is
   1.336 +        automatically set to (0,0).
   1.337 +
   1.338 +        @param x    The x-coordinate of the end of a line
   1.339 +        @param y    The y-coordinate of the end of a line
   1.340 +    */
   1.341 +    void lineTo(SkScalar x, SkScalar y);
   1.342 +
   1.343 +    /** Add a line from the last point to the specified point. If no moveTo()
   1.344 +        call has been made for this contour, the first point is automatically
   1.345 +        set to (0,0).
   1.346 +
   1.347 +        @param p    The end of a line
   1.348 +    */
   1.349 +    void lineTo(const SkPoint& p) {
   1.350 +        this->lineTo(p.fX, p.fY);
   1.351 +    }
   1.352 +
   1.353 +    /** Same as lineTo, but the coordinates are considered relative to the last
   1.354 +        point on this contour. If there is no previous point, then a moveTo(0,0)
   1.355 +        is inserted automatically.
   1.356 +
   1.357 +        @param dx   The amount to add to the x-coordinate of the previous point
   1.358 +                    on this contour, to specify a line
   1.359 +        @param dy   The amount to add to the y-coordinate of the previous point
   1.360 +                    on this contour, to specify a line
   1.361 +    */
   1.362 +    void rLineTo(SkScalar dx, SkScalar dy);
   1.363 +
   1.364 +    /** Add a quadratic bezier from the last point, approaching control point
   1.365 +        (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
   1.366 +        this contour, the first point is automatically set to (0,0).
   1.367 +
   1.368 +        @param x1   The x-coordinate of the control point on a quadratic curve
   1.369 +        @param y1   The y-coordinate of the control point on a quadratic curve
   1.370 +        @param x2   The x-coordinate of the end point on a quadratic curve
   1.371 +        @param y2   The y-coordinate of the end point on a quadratic curve
   1.372 +    */
   1.373 +    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
   1.374 +
   1.375 +    /** Add a quadratic bezier from the last point, approaching control point
   1.376 +        p1, and ending at p2. If no moveTo() call has been made for this
   1.377 +        contour, the first point is automatically set to (0,0).
   1.378 +
   1.379 +        @param p1   The control point on a quadratic curve
   1.380 +        @param p2   The end point on a quadratic curve
   1.381 +    */
   1.382 +    void quadTo(const SkPoint& p1, const SkPoint& p2) {
   1.383 +        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
   1.384 +    }
   1.385 +
   1.386 +    /** Same as quadTo, but the coordinates are considered relative to the last
   1.387 +        point on this contour. If there is no previous point, then a moveTo(0,0)
   1.388 +        is inserted automatically.
   1.389 +
   1.390 +        @param dx1   The amount to add to the x-coordinate of the last point on
   1.391 +                this contour, to specify the control point of a quadratic curve
   1.392 +        @param dy1   The amount to add to the y-coordinate of the last point on
   1.393 +                this contour, to specify the control point of a quadratic curve
   1.394 +        @param dx2   The amount to add to the x-coordinate of the last point on
   1.395 +                     this contour, to specify the end point of a quadratic curve
   1.396 +        @param dy2   The amount to add to the y-coordinate of the last point on
   1.397 +                     this contour, to specify the end point of a quadratic curve
   1.398 +    */
   1.399 +    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
   1.400 +
   1.401 +    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
   1.402 +                 SkScalar w);
   1.403 +    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
   1.404 +        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
   1.405 +    }
   1.406 +    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
   1.407 +                  SkScalar w);
   1.408 +
   1.409 +    /** Add a cubic bezier from the last point, approaching control points
   1.410 +        (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
   1.411 +        made for this contour, the first point is automatically set to (0,0).
   1.412 +
   1.413 +        @param x1   The x-coordinate of the 1st control point on a cubic curve
   1.414 +        @param y1   The y-coordinate of the 1st control point on a cubic curve
   1.415 +        @param x2   The x-coordinate of the 2nd control point on a cubic curve
   1.416 +        @param y2   The y-coordinate of the 2nd control point on a cubic curve
   1.417 +        @param x3   The x-coordinate of the end point on a cubic curve
   1.418 +        @param y3   The y-coordinate of the end point on a cubic curve
   1.419 +    */
   1.420 +    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
   1.421 +                 SkScalar x3, SkScalar y3);
   1.422 +
   1.423 +    /** Add a cubic bezier from the last point, approaching control points p1
   1.424 +        and p2, and ending at p3. If no moveTo() call has been made for this
   1.425 +        contour, the first point is automatically set to (0,0).
   1.426 +
   1.427 +        @param p1   The 1st control point on a cubic curve
   1.428 +        @param p2   The 2nd control point on a cubic curve
   1.429 +        @param p3   The end point on a cubic curve
   1.430 +    */
   1.431 +    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
   1.432 +        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
   1.433 +    }
   1.434 +
   1.435 +    /** Same as cubicTo, but the coordinates are considered relative to the
   1.436 +        current point on this contour. If there is no previous point, then a
   1.437 +        moveTo(0,0) is inserted automatically.
   1.438 +
   1.439 +        @param dx1   The amount to add to the x-coordinate of the last point on
   1.440 +                this contour, to specify the 1st control point of a cubic curve
   1.441 +        @param dy1   The amount to add to the y-coordinate of the last point on
   1.442 +                this contour, to specify the 1st control point of a cubic curve
   1.443 +        @param dx2   The amount to add to the x-coordinate of the last point on
   1.444 +                this contour, to specify the 2nd control point of a cubic curve
   1.445 +        @param dy2   The amount to add to the y-coordinate of the last point on
   1.446 +                this contour, to specify the 2nd control point of a cubic curve
   1.447 +        @param dx3   The amount to add to the x-coordinate of the last point on
   1.448 +                     this contour, to specify the end point of a cubic curve
   1.449 +        @param dy3   The amount to add to the y-coordinate of the last point on
   1.450 +                     this contour, to specify the end point of a cubic curve
   1.451 +    */
   1.452 +    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
   1.453 +                  SkScalar x3, SkScalar y3);
   1.454 +
   1.455 +    /** Append the specified arc to the path as a new contour. If the start of
   1.456 +        the path is different from the path's current last point, then an
   1.457 +        automatic lineTo() is added to connect the current contour to the start
   1.458 +        of the arc. However, if the path is empty, then we call moveTo() with
   1.459 +        the first point of the arc. The sweep angle is treated mod 360.
   1.460 +
   1.461 +        @param oval The bounding oval defining the shape and size of the arc
   1.462 +        @param startAngle Starting angle (in degrees) where the arc begins
   1.463 +        @param sweepAngle Sweep angle (in degrees) measured clockwise. This is
   1.464 +                          treated mod 360.
   1.465 +        @param forceMoveTo If true, always begin a new contour with the arc
   1.466 +    */
   1.467 +    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
   1.468 +               bool forceMoveTo);
   1.469 +
   1.470 +    /** Append a line and arc to the current path. This is the same as the
   1.471 +        PostScript call "arct".
   1.472 +    */
   1.473 +    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
   1.474 +               SkScalar radius);
   1.475 +
   1.476 +    /** Append a line and arc to the current path. This is the same as the
   1.477 +        PostScript call "arct".
   1.478 +    */
   1.479 +    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
   1.480 +        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
   1.481 +    }
   1.482 +
   1.483 +    /** Close the current contour. If the current point is not equal to the
   1.484 +        first point of the contour, a line segment is automatically added.
   1.485 +    */
   1.486 +    void close();
   1.487 +
   1.488 +    enum Direction {
   1.489 +        /** Direction either has not been or could not be computed */
   1.490 +        kUnknown_Direction,
   1.491 +        /** clockwise direction for adding closed contours */
   1.492 +        kCW_Direction,
   1.493 +        /** counter-clockwise direction for adding closed contours */
   1.494 +        kCCW_Direction,
   1.495 +    };
   1.496 +
   1.497 +    /**
   1.498 +     *  Return the opposite of the specified direction. kUnknown is its own
   1.499 +     *  opposite.
   1.500 +     */
   1.501 +    static Direction OppositeDirection(Direction dir) {
   1.502 +        static const Direction gOppositeDir[] = {
   1.503 +            kUnknown_Direction, kCCW_Direction, kCW_Direction
   1.504 +        };
   1.505 +        return gOppositeDir[dir];
   1.506 +    }
   1.507 +
   1.508 +    /**
   1.509 +     *  Returns whether or not a fill type is inverted
   1.510 +     *
   1.511 +     *  kWinding_FillType        -> false
   1.512 +     *  kEvenOdd_FillType        -> false
   1.513 +     *  kInverseWinding_FillType -> true
   1.514 +     *  kInverseEvenOdd_FillType -> true
   1.515 +     */
   1.516 +    static bool IsInverseFillType(FillType fill) {
   1.517 +        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
   1.518 +        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
   1.519 +        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
   1.520 +        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
   1.521 +        return (fill & 2) != 0;
   1.522 +    }
   1.523 +
   1.524 +    /**
   1.525 +     *  Returns the equivalent non-inverted fill type to the given fill type
   1.526 +     *
   1.527 +     *  kWinding_FillType        -> kWinding_FillType
   1.528 +     *  kEvenOdd_FillType        -> kEvenOdd_FillType
   1.529 +     *  kInverseWinding_FillType -> kWinding_FillType
   1.530 +     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
   1.531 +     */
   1.532 +    static FillType ConvertToNonInverseFillType(FillType fill) {
   1.533 +        SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
   1.534 +        SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
   1.535 +        SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
   1.536 +        SK_COMPILE_ASSERT(3 == kInverseEvenOdd_FillType, fill_type_mismatch);
   1.537 +        return (FillType)(fill & 1);
   1.538 +    }
   1.539 +
   1.540 +    /**
   1.541 +     *  Tries to quickly compute the direction of the first non-degenerate
   1.542 +     *  contour. If it can be computed, return true and set dir to that
   1.543 +     *  direction. If it cannot be (quickly) determined, return false and ignore
   1.544 +     *  the dir parameter. If the direction was determined, it is cached to make
   1.545 +     *  subsequent calls return quickly.
   1.546 +     */
   1.547 +    bool cheapComputeDirection(Direction* dir) const;
   1.548 +
   1.549 +    /**
   1.550 +     *  Returns true if the path's direction can be computed via
   1.551 +     *  cheapComputDirection() and if that computed direction matches the
   1.552 +     *  specified direction. If dir is kUnknown, returns true if the direction
   1.553 +     *  cannot be computed.
   1.554 +     */
   1.555 +    bool cheapIsDirection(Direction dir) const {
   1.556 +        Direction computedDir = kUnknown_Direction;
   1.557 +        (void)this->cheapComputeDirection(&computedDir);
   1.558 +        return computedDir == dir;
   1.559 +    }
   1.560 +
   1.561 +    enum PathAsRect {
   1.562 +        /** The path can not draw the same as its bounds. */
   1.563 +        kNone_PathAsRect,
   1.564 +        /** The path draws the same as its bounds when filled. */
   1.565 +        kFill_PathAsRect,
   1.566 +        /** The path draws the same as its bounds when stroked or filled. */
   1.567 +        kStroke_PathAsRect,
   1.568 +    };
   1.569 +
   1.570 +    /** Returns kFill_PathAsRect or kStroke_PathAsRect if drawing the path (either filled or
   1.571 +        stroked) will be equivalent to filling/stroking the path's bounding rect. If
   1.572 +        either is true, and direction is not null, sets the direction of the contour. If the
   1.573 +        path is not drawn equivalent to a rect, returns kNone_PathAsRect and ignores direction.
   1.574 +
   1.575 +        @param direction If not null, set to the contour's direction when it is drawn as a rect
   1.576 +        @return the path's PathAsRect type
   1.577 +     */
   1.578 +    PathAsRect asRect(Direction* direction = NULL) const;
   1.579 +
   1.580 +    /** Returns true if the path specifies a rectangle. If so, and if isClosed is
   1.581 +        not null, set isClosed to true if the path is closed. Also, if returning true
   1.582 +        and direction is not null, return the rect direction. If the path does not
   1.583 +        specify a rectangle, return false and ignore isClosed and direction.
   1.584 +
   1.585 +        @param isClosed If not null, set to true if the path is closed
   1.586 +        @param direction If not null, set to the rectangle's direction
   1.587 +        @return true if the path specifies a rectangle
   1.588 +    */
   1.589 +    bool isRect(bool* isClosed, Direction* direction) const;
   1.590 +
   1.591 +    /** Returns true if the path specifies a pair of nested rectangles. If so, and if
   1.592 +        rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
   1.593 +        rectangle. If so, and dirs is not null, set dirs[0] to the direction of
   1.594 +        the outer rectangle and dirs[1] to the direction of the inner rectangle. If
   1.595 +        the path does not specify a pair of nested rectangles, return
   1.596 +        false and ignore rect and dirs.
   1.597 +
   1.598 +        @param rect If not null, returns the path as a pair of nested rectangles
   1.599 +        @param dirs If not null, returns the direction of the rects
   1.600 +        @return true if the path describes a pair of nested rectangles
   1.601 +    */
   1.602 +    bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
   1.603 +
   1.604 +    /**
   1.605 +     *  Add a closed rectangle contour to the path
   1.606 +     *  @param rect The rectangle to add as a closed contour to the path
   1.607 +     *  @param dir  The direction to wind the rectangle's contour. Cannot be
   1.608 +     *              kUnknown_Direction.
   1.609 +     */
   1.610 +    void addRect(const SkRect& rect, Direction dir = kCW_Direction);
   1.611 +
   1.612 +    /**
   1.613 +     *  Add a closed rectangle contour to the path
   1.614 +     *
   1.615 +     *  @param left     The left side of a rectangle to add as a closed contour
   1.616 +     *                  to the path
   1.617 +     *  @param top      The top of a rectangle to add as a closed contour to the
   1.618 +     *                  path
   1.619 +     *  @param right    The right side of a rectangle to add as a closed contour
   1.620 +     *                  to the path
   1.621 +     *  @param bottom   The bottom of a rectangle to add as a closed contour to
   1.622 +     *                  the path
   1.623 +     *  @param dir  The direction to wind the rectangle's contour. Cannot be
   1.624 +     *              kUnknown_Direction.
   1.625 +     */
   1.626 +    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
   1.627 +                 Direction dir = kCW_Direction);
   1.628 +
   1.629 +    /**
   1.630 +     *  Add a closed oval contour to the path
   1.631 +     *
   1.632 +     *  @param oval The bounding oval to add as a closed contour to the path
   1.633 +     *  @param dir  The direction to wind the oval's contour. Cannot be
   1.634 +     *              kUnknown_Direction.
   1.635 +     */
   1.636 +    void addOval(const SkRect& oval, Direction dir = kCW_Direction);
   1.637 +
   1.638 +    /**
   1.639 +     *  Add a closed circle contour to the path
   1.640 +     *
   1.641 +     *  @param x        The x-coordinate of the center of a circle to add as a
   1.642 +     *                  closed contour to the path
   1.643 +     *  @param y        The y-coordinate of the center of a circle to add as a
   1.644 +     *                  closed contour to the path
   1.645 +     *  @param radius   The radius of a circle to add as a closed contour to the
   1.646 +     *                  path
   1.647 +     *  @param dir  The direction to wind the circle's contour. Cannot be
   1.648 +     *              kUnknown_Direction.
   1.649 +     */
   1.650 +    void addCircle(SkScalar x, SkScalar y, SkScalar radius,
   1.651 +                   Direction dir = kCW_Direction);
   1.652 +
   1.653 +    /** Add the specified arc to the path as a new contour.
   1.654 +
   1.655 +        @param oval The bounds of oval used to define the size of the arc
   1.656 +        @param startAngle Starting angle (in degrees) where the arc begins
   1.657 +        @param sweepAngle Sweep angle (in degrees) measured clockwise
   1.658 +    */
   1.659 +    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
   1.660 +
   1.661 +    /**
   1.662 +     *  Add a closed round-rectangle contour to the path
   1.663 +     *  @param rect The bounds of a round-rectangle to add as a closed contour
   1.664 +     *  @param rx   The x-radius of the rounded corners on the round-rectangle
   1.665 +     *  @param ry   The y-radius of the rounded corners on the round-rectangle
   1.666 +     *  @param dir  The direction to wind the rectangle's contour. Cannot be
   1.667 +     *              kUnknown_Direction.
   1.668 +     */
   1.669 +    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
   1.670 +                      Direction dir = kCW_Direction);
   1.671 +
   1.672 +    /**
   1.673 +     *  Add a closed round-rectangle contour to the path. Each corner receives
   1.674 +     *  two radius values [X, Y]. The corners are ordered top-left, top-right,
   1.675 +     *  bottom-right, bottom-left.
   1.676 +     *  @param rect The bounds of a round-rectangle to add as a closed contour
   1.677 +     *  @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner
   1.678 +     *  @param dir  The direction to wind the rectangle's contour. Cannot be
   1.679 +     *              kUnknown_Direction.
   1.680 +     * Note: The radii here now go through the same constraint handling as the
   1.681 +     *       SkRRect radii (i.e., either radii at a corner being 0 implies a
   1.682 +     *       sqaure corner and oversized radii are proportionally scaled down).
   1.683 +     */
   1.684 +    void addRoundRect(const SkRect& rect, const SkScalar radii[],
   1.685 +                      Direction dir = kCW_Direction);
   1.686 +
   1.687 +    /**
   1.688 +     *  Add an SkRRect contour to the path
   1.689 +     *  @param rrect The rounded rect to add as a closed contour
   1.690 +     *  @param dir   The winding direction for the new contour. Cannot be
   1.691 +     *               kUnknown_Direction.
   1.692 +     */
   1.693 +    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
   1.694 +
   1.695 +    /**
   1.696 +     *  Add a new contour made of just lines. This is just a fast version of
   1.697 +     *  the following:
   1.698 +     *      this->moveTo(pts[0]);
   1.699 +     *      for (int i = 1; i < count; ++i) {
   1.700 +     *          this->lineTo(pts[i]);
   1.701 +     *      }
   1.702 +     *      if (close) {
   1.703 +     *          this->close();
   1.704 +     *      }
   1.705 +     */
   1.706 +    void addPoly(const SkPoint pts[], int count, bool close);
   1.707 +
   1.708 +    enum AddPathMode {
   1.709 +        /** Source path contours are added as new contours.
   1.710 +        */
   1.711 +        kAppend_AddPathMode,
   1.712 +        /** Path is added by extending the last contour of the destination path
   1.713 +            with the first contour of the source path. If the last contour of
   1.714 +            the destination path is closed, then it will not be extended.
   1.715 +            Instead, the start of source path will be extended by a straight
   1.716 +            line to the end point of the destination path.
   1.717 +        */
   1.718 +        kExtend_AddPathMode
   1.719 +    };
   1.720 +
   1.721 +    /** Add a copy of src to the path, offset by (dx,dy)
   1.722 +        @param src  The path to add as a new contour
   1.723 +        @param dx   The amount to translate the path in X as it is added
   1.724 +        @param dx   The amount to translate the path in Y as it is added
   1.725 +    */
   1.726 +    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
   1.727 +                 AddPathMode mode = kAppend_AddPathMode);
   1.728 +
   1.729 +    /** Add a copy of src to the path
   1.730 +    */
   1.731 +    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
   1.732 +        SkMatrix m;
   1.733 +        m.reset();
   1.734 +        this->addPath(src, m, mode);
   1.735 +    }
   1.736 +
   1.737 +    /** Add a copy of src to the path, transformed by matrix
   1.738 +        @param src  The path to add as a new contour
   1.739 +        @param matrix  Transform applied to src
   1.740 +        @param mode  Determines how path is added
   1.741 +    */
   1.742 +    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
   1.743 +
   1.744 +    /**
   1.745 +     *  Same as addPath(), but reverses the src input
   1.746 +     */
   1.747 +    void reverseAddPath(const SkPath& src);
   1.748 +
   1.749 +    /** Offset the path by (dx,dy), returning true on success
   1.750 +
   1.751 +        @param dx   The amount in the X direction to offset the entire path
   1.752 +        @param dy   The amount in the Y direction to offset the entire path
   1.753 +        @param dst  The translated path is written here
   1.754 +    */
   1.755 +    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
   1.756 +
   1.757 +    /** Offset the path by (dx,dy), returning true on success
   1.758 +
   1.759 +        @param dx   The amount in the X direction to offset the entire path
   1.760 +        @param dy   The amount in the Y direction to offset the entire path
   1.761 +    */
   1.762 +    void offset(SkScalar dx, SkScalar dy) {
   1.763 +        this->offset(dx, dy, this);
   1.764 +    }
   1.765 +
   1.766 +    /** Transform the points in this path by matrix, and write the answer into
   1.767 +        dst.
   1.768 +
   1.769 +        @param matrix   The matrix to apply to the path
   1.770 +        @param dst      The transformed path is written here
   1.771 +    */
   1.772 +    void transform(const SkMatrix& matrix, SkPath* dst) const;
   1.773 +
   1.774 +    /** Transform the points in this path by matrix
   1.775 +
   1.776 +        @param matrix The matrix to apply to the path
   1.777 +    */
   1.778 +    void transform(const SkMatrix& matrix) {
   1.779 +        this->transform(matrix, this);
   1.780 +    }
   1.781 +
   1.782 +    /** Return the last point on the path. If no points have been added, (0,0)
   1.783 +        is returned. If there are no points, this returns false, otherwise it
   1.784 +        returns true.
   1.785 +
   1.786 +        @param lastPt   The last point on the path is returned here
   1.787 +    */
   1.788 +    bool getLastPt(SkPoint* lastPt) const;
   1.789 +
   1.790 +    /** Set the last point on the path. If no points have been added,
   1.791 +        moveTo(x,y) is automatically called.
   1.792 +
   1.793 +        @param x    The new x-coordinate for the last point
   1.794 +        @param y    The new y-coordinate for the last point
   1.795 +    */
   1.796 +    void setLastPt(SkScalar x, SkScalar y);
   1.797 +
   1.798 +    /** Set the last point on the path. If no points have been added, moveTo(p)
   1.799 +        is automatically called.
   1.800 +
   1.801 +        @param p    The new location for the last point
   1.802 +    */
   1.803 +    void setLastPt(const SkPoint& p) {
   1.804 +        this->setLastPt(p.fX, p.fY);
   1.805 +    }
   1.806 +
   1.807 +    enum SegmentMask {
   1.808 +        kLine_SegmentMask   = 1 << 0,
   1.809 +        kQuad_SegmentMask   = 1 << 1,
   1.810 +        kConic_SegmentMask  = 1 << 2,
   1.811 +        kCubic_SegmentMask  = 1 << 3,
   1.812 +    };
   1.813 +
   1.814 +    /**
   1.815 +     *  Returns a mask, where each bit corresponding to a SegmentMask is
   1.816 +     *  set if the path contains 1 or more segments of that type.
   1.817 +     *  Returns 0 for an empty path (no segments).
   1.818 +     */
   1.819 +    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
   1.820 +
   1.821 +    enum Verb {
   1.822 +        kMove_Verb,     //!< iter.next returns 1 point
   1.823 +        kLine_Verb,     //!< iter.next returns 2 points
   1.824 +        kQuad_Verb,     //!< iter.next returns 3 points
   1.825 +        kConic_Verb,    //!< iter.next returns 3 points + iter.conicWeight()
   1.826 +        kCubic_Verb,    //!< iter.next returns 4 points
   1.827 +        kClose_Verb,    //!< iter.next returns 1 point (contour's moveTo pt)
   1.828 +        kDone_Verb,     //!< iter.next returns 0 points
   1.829 +    };
   1.830 +
   1.831 +    /** Iterate through all of the segments (lines, quadratics, cubics) of
   1.832 +        each contours in a path.
   1.833 +
   1.834 +        The iterator cleans up the segments along the way, removing degenerate
   1.835 +        segments and adding close verbs where necessary. When the forceClose
   1.836 +        argument is provided, each contour (as defined by a new starting
   1.837 +        move command) will be completed with a close verb regardless of the
   1.838 +        contour's contents.
   1.839 +    */
   1.840 +    class SK_API Iter {
   1.841 +    public:
   1.842 +        Iter();
   1.843 +        Iter(const SkPath&, bool forceClose);
   1.844 +
   1.845 +        void setPath(const SkPath&, bool forceClose);
   1.846 +
   1.847 +        /** Return the next verb in this iteration of the path. When all
   1.848 +            segments have been visited, return kDone_Verb.
   1.849 +
   1.850 +            @param  pts The points representing the current verb and/or segment
   1.851 +            @param doConsumeDegerates If true, first scan for segments that are
   1.852 +                   deemed degenerate (too short) and skip those.
   1.853 +            @return The verb for the current segment
   1.854 +        */
   1.855 +        Verb next(SkPoint pts[4], bool doConsumeDegerates = true) {
   1.856 +            if (doConsumeDegerates) {
   1.857 +                this->consumeDegenerateSegments();
   1.858 +            }
   1.859 +            return this->doNext(pts);
   1.860 +        }
   1.861 +
   1.862 +        /**
   1.863 +         *  Return the weight for the current conic. Only valid if the current
   1.864 +         *  segment return by next() was a conic.
   1.865 +         */
   1.866 +        SkScalar conicWeight() const { return *fConicWeights; }
   1.867 +
   1.868 +        /** If next() returns kLine_Verb, then this query returns true if the
   1.869 +            line was the result of a close() command (i.e. the end point is the
   1.870 +            initial moveto for this contour). If next() returned a different
   1.871 +            verb, this returns an undefined value.
   1.872 +
   1.873 +            @return If the last call to next() returned kLine_Verb, return true
   1.874 +                    if it was the result of an explicit close command.
   1.875 +        */
   1.876 +        bool isCloseLine() const { return SkToBool(fCloseLine); }
   1.877 +
   1.878 +        /** Returns true if the current contour is closed (has a kClose_Verb)
   1.879 +            @return true if the current contour is closed (has a kClose_Verb)
   1.880 +        */
   1.881 +        bool isClosedContour() const;
   1.882 +
   1.883 +    private:
   1.884 +        const SkPoint*  fPts;
   1.885 +        const uint8_t*  fVerbs;
   1.886 +        const uint8_t*  fVerbStop;
   1.887 +        const SkScalar* fConicWeights;
   1.888 +        SkPoint         fMoveTo;
   1.889 +        SkPoint         fLastPt;
   1.890 +        SkBool8         fForceClose;
   1.891 +        SkBool8         fNeedClose;
   1.892 +        SkBool8         fCloseLine;
   1.893 +        SkBool8         fSegmentState;
   1.894 +
   1.895 +        inline const SkPoint& cons_moveTo();
   1.896 +        Verb autoClose(SkPoint pts[2]);
   1.897 +        void consumeDegenerateSegments();
   1.898 +        Verb doNext(SkPoint pts[4]);
   1.899 +    };
   1.900 +
   1.901 +    /** Iterate through the verbs in the path, providing the associated points.
   1.902 +    */
   1.903 +    class SK_API RawIter {
   1.904 +    public:
   1.905 +        RawIter();
   1.906 +        RawIter(const SkPath&);
   1.907 +
   1.908 +        void setPath(const SkPath&);
   1.909 +
   1.910 +        /** Return the next verb in this iteration of the path. When all
   1.911 +            segments have been visited, return kDone_Verb.
   1.912 +
   1.913 +            @param  pts The points representing the current verb and/or segment
   1.914 +                        This must not be NULL.
   1.915 +            @return The verb for the current segment
   1.916 +        */
   1.917 +        Verb next(SkPoint pts[4]);
   1.918 +
   1.919 +        SkScalar conicWeight() const { return *fConicWeights; }
   1.920 +
   1.921 +    private:
   1.922 +        const SkPoint*  fPts;
   1.923 +        const uint8_t*  fVerbs;
   1.924 +        const uint8_t*  fVerbStop;
   1.925 +        const SkScalar* fConicWeights;
   1.926 +        SkPoint         fMoveTo;
   1.927 +        SkPoint         fLastPt;
   1.928 +    };
   1.929 +
   1.930 +    /**
   1.931 +     *  Returns true if the point { x, y } is contained by the path, taking into
   1.932 +     *  account the FillType.
   1.933 +     */
   1.934 +    bool contains(SkScalar x, SkScalar y) const;
   1.935 +
   1.936 +    void dump(bool forceClose, const char title[] = NULL) const;
   1.937 +    void dump() const;
   1.938 +
   1.939 +    /**
   1.940 +     *  Write the path to the buffer, and return the number of bytes written.
   1.941 +     *  If buffer is NULL, it still returns the number of bytes.
   1.942 +     */
   1.943 +    size_t writeToMemory(void* buffer) const;
   1.944 +    /**
   1.945 +     * Initializes the path from the buffer
   1.946 +     *
   1.947 +     * @param buffer Memory to read from
   1.948 +     * @param length Amount of memory available in the buffer
   1.949 +     * @return number of bytes read (must be a multiple of 4) or
   1.950 +     *         0 if there was not enough memory available
   1.951 +     */
   1.952 +    size_t readFromMemory(const void* buffer, size_t length);
   1.953 +
   1.954 +    /** Returns a non-zero, globally unique value corresponding to the set of verbs
   1.955 +        and points in the path (but not the fill type [except on Android skbug.com/1762]).
   1.956 +        Each time the path is modified, a different generation ID will be returned.
   1.957 +    */
   1.958 +    uint32_t getGenerationID() const;
   1.959 +
   1.960 +#ifdef SK_BUILD_FOR_ANDROID
   1.961 +    static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
   1.962 +    const SkPath* getSourcePath() const;
   1.963 +    void setSourcePath(const SkPath* path);
   1.964 +#else
   1.965 +    static const int kPathRefGenIDBitCnt = 32;
   1.966 +#endif
   1.967 +
   1.968 +    SkDEBUGCODE(void validate() const;)
   1.969 +
   1.970 +private:
   1.971 +    enum SerializationOffsets {
   1.972 +        // 1 free bit at 29
   1.973 +        kUnused1_SerializationShift = 28,    // 1 free bit
   1.974 +        kDirection_SerializationShift = 26, // requires 2 bits
   1.975 +        kUnused2_SerializationShift = 25,    // 1 free bit
   1.976 +        // 1 free bit at 24
   1.977 +        kConvexity_SerializationShift = 16, // requires 8 bits
   1.978 +        kFillType_SerializationShift = 8,   // requires 8 bits
   1.979 +        // 8 free bits at 0
   1.980 +    };
   1.981 +
   1.982 +    SkAutoTUnref<SkPathRef> fPathRef;
   1.983 +
   1.984 +    int                 fLastMoveToIndex;
   1.985 +    uint8_t             fFillType;
   1.986 +    mutable uint8_t     fConvexity;
   1.987 +    mutable uint8_t     fDirection;
   1.988 +#ifdef SK_BUILD_FOR_ANDROID
   1.989 +    const SkPath*       fSourcePath;
   1.990 +#endif
   1.991 +
   1.992 +    /** Resets all fields other than fPathRef to their initial 'empty' values.
   1.993 +     *  Assumes the caller has already emptied fPathRef.
   1.994 +     *  On Android increments fGenerationID without reseting it.
   1.995 +     */
   1.996 +    void resetFields();
   1.997 +
   1.998 +    /** Sets all fields other than fPathRef to the values in 'that'.
   1.999 +     *  Assumes the caller has already set fPathRef.
  1.1000 +     *  Doesn't change fGenerationID or fSourcePath on Android.
  1.1001 +     */
  1.1002 +    void copyFields(const SkPath& that);
  1.1003 +
  1.1004 +    friend class Iter;
  1.1005 +
  1.1006 +    friend class SkPathStroker;
  1.1007 +
  1.1008 +    /*  Append, in reverse order, the first contour of path, ignoring path's
  1.1009 +        last point. If no moveTo() call has been made for this contour, the
  1.1010 +        first point is automatically set to (0,0).
  1.1011 +    */
  1.1012 +    void reversePathTo(const SkPath&);
  1.1013 +
  1.1014 +    // called before we add points for lineTo, quadTo, cubicTo, checking to see
  1.1015 +    // if we need to inject a leading moveTo first
  1.1016 +    //
  1.1017 +    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
  1.1018 +    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
  1.1019 +    //
  1.1020 +    inline void injectMoveToIfNeeded();
  1.1021 +
  1.1022 +    inline bool hasOnlyMoveTos() const;
  1.1023 +
  1.1024 +    Convexity internalGetConvexity() const;
  1.1025 +
  1.1026 +    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
  1.1027 +                       bool* isClosed, Direction* direction) const;
  1.1028 +
  1.1029 +    /** Returns if the path can return a bound at no cost (true) or will have to
  1.1030 +        perform some computation (false).
  1.1031 +     */
  1.1032 +    bool hasComputedBounds() const {
  1.1033 +        SkDEBUGCODE(this->validate();)
  1.1034 +        return fPathRef->hasComputedBounds();
  1.1035 +    }
  1.1036 +
  1.1037 +
  1.1038 +    // 'rect' needs to be sorted
  1.1039 +    void setBounds(const SkRect& rect) {
  1.1040 +        SkPathRef::Editor ed(&fPathRef);
  1.1041 +
  1.1042 +        ed.setBounds(rect);
  1.1043 +    }
  1.1044 +
  1.1045 +    friend class SkAutoPathBoundsUpdate;
  1.1046 +    friend class SkAutoDisableOvalCheck;
  1.1047 +    friend class SkAutoDisableDirectionCheck;
  1.1048 +    friend class SkBench_AddPathTest; // perf test reversePathTo
  1.1049 +    friend class PathTest_Private; // unit test reversePathTo
  1.1050 +};
  1.1051 +
  1.1052 +#endif

mercurial