11dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
21dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com/*
31dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * Copyright 2012 Google Inc.
41dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com *
51dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * Use of this source code is governed by a BSD-style license that can be
61dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * found in the LICENSE file.
71dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com */
81dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
91dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#ifndef SkPathRef_DEFINED
101dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#define SkPathRef_DEFINED
111dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
12ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkMatrix.h"
13ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkPoint.h"
14ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkRect.h"
151dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#include "SkRefCnt.h"
16ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com#include "SkTDArray.h"
171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#include <stddef.h> // ptrdiff_t
181dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
19ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.comclass SkRBuffer;
20ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.comclass SkWBuffer;
21ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
221dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com/**
231dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods
241dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an
251dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs
26466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's
271dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef after the editor's
281dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * constructor returns.
291dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com *
301dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * The points and verbs are stored in a single allocation. The points are at the begining of the
311dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points
321dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * and verbs both grow into the middle of the allocation until the meet. To access verb i in the
331dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first
341dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com * logical verb or the last verb in memory).
351dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com */
36ae09f2dc3fb1e8a8db99b214c8a71d0b9613a856bsalomon@google.com
37650ead2f1b1180b04cbdd1550bceb2ab45922db3robertphillips@google.comclass SK_API SkPathRef : public ::SkRefCnt {
381dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.compublic:
391dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    SK_DECLARE_INST_COUNT(SkPathRef);
401dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
411dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    class Editor {
421dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    public:
43f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        Editor(SkAutoTUnref<SkPathRef>* pathRef,
441dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com               int incReserveVerbs = 0,
453e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com               int incReservePoints = 0);
461dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
47f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
481dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
491dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
501dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * Returns the array of points.
511dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
520efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        SkPoint* points() { return fPathRef->getPoints(); }
530efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        const SkPoint* points() const { return fPathRef->points(); }
541dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
551dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
561dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * Gets the ith point. Shortcut for this->points() + i
571dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
581dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        SkPoint* atPoint(int i) {
591dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com            SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
601dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com            return this->points() + i;
611dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        };
620efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        const SkPoint* atPoint(int i) const {
630efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com            SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
640efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com            return this->points() + i;
650efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        };
661dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
671dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
681dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * Adds the verb and allocates space for the number of points indicated by the verb. The
691dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * return value is a pointer to where the points for the verb should be written.
706b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com         * 'weight' is only used if 'verb' is kConic_Verb
711dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
726b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com        SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) {
7303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com            SkDEBUGCODE(fPathRef->validate();)
746b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com            return fPathRef->growForVerb(verb, weight);
753e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com        }
761dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
771dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
786b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com         * Allocates space for multiple instances of a particular verb and the
796b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com         * requisite points & weights.
806b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com         * The return pointer points at the first new point (indexed normally [<i>]).
816b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com         * If 'verb' is kConic_Verb, 'weights' will return a pointer to the
8296f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com         * space for the conic weights (indexed normally).
831dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
8496f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com        SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb,
8596f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com                                     int numVbs,
8696f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com                                     SkScalar** weights = NULL) {
8796f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com            return fPathRef->growForRepeatedVerb(verb, numVbs, weights);
881dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        }
891dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
901dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
911dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * Resets the path ref to a new verb and point count. The new verbs and points are
921dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * uninitialized.
931dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
94277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) {
95277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com            fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount);
961dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        }
970efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
981dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        /**
991dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         * Gets the path ref that is wrapped in the Editor.
1001dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com         */
1011dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        SkPathRef* pathRef() { return fPathRef; }
1021dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
103466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); }
104466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com
1050efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); }
1060efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
1071dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    private:
1081dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        SkPathRef* fPathRef;
1091dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    };
1101dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
1111dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.compublic:
1121dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
1131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Gets a path ref with no verbs or points.
1141dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
1151f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    static SkPathRef* CreateEmpty();
1161dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
1171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
118ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com     *  Returns true if all of the points in this path are finite, meaning there
119ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com     *  are no infinities and no NaNs.
120ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com     */
121ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool isFinite() const {
122ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        if (fBoundsIsDirty) {
123ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com            this->computeBounds();
124ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        }
125ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return SkToBool(fIsFinite);
126ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
127ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
1286b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    /**
1296b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     *  Returns a mask, where each bit corresponding to a SegmentMask is
1306b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     *  set if the path contains 1 or more segments of that type.
1316b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     *  Returns 0 for an empty path (no segments).
1326b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     */
1336b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint32_t getSegmentMasks() const { return fSegmentMask; }
1346b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com
135466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    /** Returns true if the path is an oval.
136466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *
137466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     * @param rect      returns the bounding rect of this oval. It's a circle
138466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *                  if the height and width are the same.
139466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *
140466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     * @return true if this path is an oval.
141466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *              Tracking whether a path is an oval is considered an
142466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *              optimization for performance and so some paths that are in
143466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     *              fact ovals can report false.
144466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com     */
1456e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com    bool isOval(SkRect* rect) const {
146466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        if (fIsOval && NULL != rect) {
147466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com            *rect = getBounds();
148466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        }
149466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com
150466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        return SkToBool(fIsOval);
151466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    }
152466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com
153ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    bool hasComputedBounds() const {
154ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return !fBoundsIsDirty;
155ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
156ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
157ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    /** Returns the bounds of the path's points. If the path contains 0 or 1
158ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
159ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        Note: this bounds may be larger than the actual shape, since curves
160ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        do not extend as far as their control points.
161ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    */
16265caeaf32d09f5886f3c740cfef2f1c26ef9cb50skia.committer@gmail.com    const SkRect& getBounds() const {
163ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        if (fBoundsIsDirty) {
164ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com            this->computeBounds();
165ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        }
166ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        return fBounds;
167ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
168ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
169ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    /**
1701dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Transforms a path ref by a matrix, allocating a new one only if necessary.
1711dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
172f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org    static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
1731dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com                                      const SkPathRef& src,
1743e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com                                      const SkMatrix& matrix);
1751dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
176fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org    static SkPathRef* CreateFromBuffer(SkRBuffer* buffer);
1771dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
1781dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
1791dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be
1801dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * repopulated with approximately the same number of verbs and points. A new path ref is created
1811dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * only if necessary.
1821dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
1833e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com    static void Rewind(SkAutoTUnref<SkPathRef>* pathRef);
1841dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
1851dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    virtual ~SkPathRef() {
18603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com        SkDEBUGCODE(this->validate();)
1871dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        sk_free(fPoints);
188ae09f2dc3fb1e8a8db99b214c8a71d0b9613a856bsalomon@google.com
189f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fPoints = NULL;)
190f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fVerbs = NULL;)
191f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fVerbCnt = 0x9999999;)
192f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fPointCnt = 0xAAAAAAA;)
193f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fPointCnt = 0xBBBBBBB;)
194f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;)
195f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fEditorsAttached = 0x7777777;)
1961dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
1971dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
19803087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; }
19903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; }
2006b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); }
2011dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2021dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2031dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Returns a pointer one beyond the first logical verb (last verb in memory order).
2041dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
20503087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    const uint8_t* verbs() const { SkDEBUGCODE(this->validate();) return fVerbs; }
2061dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2071dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2081dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Returns a const pointer to the first verb in memory (which is the last logical verb).
2091dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
2101dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; }
2111dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2121dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Returns a const pointer to the first point.
2141dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
21503087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    const SkPoint* points() const { SkDEBUGCODE(this->validate();) return fPoints; }
2161dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2181dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Shortcut for this->points() + this->countPoints()
2191dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
2201dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); }
2211dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
22203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    const SkScalar* conicWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.begin(); }
22303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    const SkScalar* conicWeightsEnd() const { SkDEBUGCODE(this->validate();) return fConicWeights.end(); }
224277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
2251dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2261dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Convenience methods for getting to a verb or point by index.
2271dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
2286b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint8_t atVerb(int index) const {
2291dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        SkASSERT((unsigned) index < (unsigned) fVerbCnt);
2301dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        return this->verbs()[~index];
2311dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
2321dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    const SkPoint& atPoint(int index) const {
2331dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        SkASSERT((unsigned) index < (unsigned) fPointCnt);
2341dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        return this->points()[index];
2351dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
2361dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2373e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com    bool operator== (const SkPathRef& ref) const;
2381dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2391dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2401dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Writes the path points and verbs to a buffer.
2411dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
2426b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    void writeToBuffer(SkWBuffer* buffer) const;
2431dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2441dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
2451dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Gets the number of bytes that would be written in writeBuffer()
2461dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
2476b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint32_t writeSize() const;
2481dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2491ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    /**
2501ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org     * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
2511ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org     * same ID then they have the same verbs and points. However, two path refs may have the same
2521ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org     * contents but different genIDs.
2531ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org     */
2541ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    uint32_t genID() const;
2551ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org
2561dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.comprivate:
257ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    enum SerializationOffsets {
258ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        kIsFinite_SerializationShift = 25,  // requires 1 bit
259466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        kIsOval_SerializationShift = 24,    // requires 1 bit
2606b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com        kSegmentMask_SerializationShift = 0 // requires 4 bits
261ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    };
262ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
2631dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    SkPathRef() {
264ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        fBoundsIsDirty = true;    // this also invalidates fIsFinite
2651dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fPointCnt = 0;
2661dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fVerbCnt = 0;
2671dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fVerbs = NULL;
2681dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fPoints = NULL;
2691dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fFreeSpace = 0;
2701dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fGenerationID = kEmptyGenID;
2716b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com        fSegmentMask = 0;
272466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        fIsOval = false;
273f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org        SkDEBUGCODE(fEditorsAttached = 0;)
27403087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com        SkDEBUGCODE(this->validate();)
2751dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
2761dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
2773e292aa398dc40f5188bc4f0b36c8916ac552308robertphillips@google.com    void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints);
2781dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
279ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    // Return true if the computed bounds are finite.
280ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) {
281ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        int count = ref.countPoints();
282ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        if (count <= 1) {  // we ignore just 1 point (moveto)
283ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com            bounds->setEmpty();
284ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com            return count ? ref.points()->isFinite() : true;
285ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        } else {
286ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com            return bounds->setBoundsCheck(ref.points(), count);
287ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        }
288ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
289ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
290ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    // called, if dirty, by getBounds()
291ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    void computeBounds() const {
292ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkDEBUGCODE(this->validate();)
293ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        SkASSERT(fBoundsIsDirty);
294ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
295ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        fIsFinite = ComputePtBounds(&fBounds, *this);
296ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com        fBoundsIsDirty = false;
297ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    }
298ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
2990efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com    void setBounds(const SkRect& rect) {
3000efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom);
3010efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        fBounds = rect;
3020efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        fBoundsIsDirty = false;
3030efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        fIsFinite = fBounds.isFinite();
3040efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com    }
3050efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
3061dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /** Makes additional room but does not change the counts or change the genID */
3071dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    void incReserve(int additionalVerbs, int additionalPoints) {
30803087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com        SkDEBUGCODE(this->validate();)
3091dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint);
3101dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        this->makeSpace(space);
31103087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com        SkDEBUGCODE(this->validate();)
3121dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
3131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
314ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    /** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also
3151dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     *  allocates space for reserveVerb additional verbs and reservePoints additional points.*/
316277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    void resetToSize(int verbCount, int pointCount, int conicCount,
317aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com                     int reserveVerbs = 0, int reservePoints = 0) {
318aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        SkDEBUGCODE(this->validate();)
319aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fBoundsIsDirty = true;      // this also invalidates fIsFinite
320aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fGenerationID = 0;
321aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com
3226b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com        fSegmentMask = 0;
323466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com        fIsOval = false;
324466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com
325aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount;
326aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints;
327aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t minSize = newSize + newReserve;
328aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com
329aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        ptrdiff_t sizeDelta = this->currSize() - minSize;
330aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com
331aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) {
332aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            sk_free(fPoints);
333aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fPoints = NULL;
334aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fVerbs = NULL;
335aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fFreeSpace = 0;
336aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fVerbCnt = 0;
337aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fPointCnt = 0;
338aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            this->makeSpace(minSize);
339aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fVerbCnt = verbCount;
340aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fPointCnt = pointCount;
341aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fFreeSpace -= newSize;
342aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        } else {
343aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fPointCnt = pointCount;
344aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fVerbCnt = verbCount;
345aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            fFreeSpace = this->currSize() - minSize;
346aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        }
347aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fConicWeights.setCount(conicCount);
348aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        SkDEBUGCODE(this->validate();)
349aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com    }
3501dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
3511dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
35296f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com     * Increases the verb count by numVbs and point count by the required amount.
35396f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com     * The new points are uninitialized. All the new verbs are set to the specified
3546b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the
3556b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com     * uninitialized conic weights.
3561dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
3576b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights);
3581dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
3591dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
3601dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Increases the verb count 1, records the new verb, and creates room for the requisite number
3611dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * of additional points. A pointer to the first point is returned. Any new points are
3621dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * uninitialized.
3631dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
3646b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight);
3651dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
3661dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
3671dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Ensures that the free space available in the path ref is >= size. The verb and point counts
3681dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * are not changed.
3691dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
370aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com    void makeSpace(size_t size) {
371aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        SkDEBUGCODE(this->validate();)
372aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        ptrdiff_t growSize = size - fFreeSpace;
373aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        if (growSize <= 0) {
374aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            return;
375aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        }
376aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t oldSize = this->currSize();
377aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        // round to next multiple of 8 bytes
378aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        growSize = (growSize + 7) & ~static_cast<size_t>(7);
379aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        // we always at least double the allocation
380aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        if (static_cast<size_t>(growSize) < oldSize) {
381aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            growSize = oldSize;
382aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        }
383aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        if (growSize < kMinSize) {
384aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com            growSize = kMinSize;
385aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        }
386aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t newSize = oldSize + growSize;
387aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO:
388aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        // encapsulate this.
389aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize));
390aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);
391aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        void* newVerbsDst = reinterpret_cast<void*>(
392aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com                                reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize);
393aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        void* oldVerbsSrc = reinterpret_cast<void*>(
394aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com                                reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize);
395aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);
396aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize);
397aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        fFreeSpace += growSize;
398aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com        SkDEBUGCODE(this->validate();)
399aaf3e64b2c867dff1b750cebdeff9e57784b8f22robertphillips@google.com    }
4001dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
4011dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
4021dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Private, non-const-ptr version of the public function verbsMemBegin().
4031dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
4041dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    uint8_t* verbsMemWritable() {
40503087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com        SkDEBUGCODE(this->validate();)
4061dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        return fVerbs - fVerbCnt;
4071dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
4081dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
4091dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    /**
4101dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     * Gets the total amount of space allocated for verbs, points, and reserve.
4111dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com     */
4121dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    size_t currSize() const {
4131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints);
4141dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
4151dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
41603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com    SkDEBUGCODE(void validate() const;)
4171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
4181f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    /**
4191f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org     * Called the first time someone calls CreateEmpty to actually create the singleton.
4201f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org     */
42178358bf624c7e7c09ffccf638c50870808d884d6mtklein    static SkPathRef* CreateEmptyImpl();
4221f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org
423466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    void setIsOval(bool isOval) { fIsOval = isOval; }
424466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com
42596f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com    SkPoint* getPoints() {
42696f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com        SkDEBUGCODE(this->validate();)
4270efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com        fIsOval = false;
42896f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com        return fPoints;
4290efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com    }
4300efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com
4311dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    enum {
4321dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        kMinSize = 256,
4331dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    };
4341dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
435ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    mutable SkRect      fBounds;
4366b8dbb668f1f069270d35a47cfe98decd059c625robertphillips@google.com    uint8_t             fSegmentMask;
437ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    mutable uint8_t     fBoundsIsDirty;
438ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com    mutable SkBool8     fIsFinite;    // only meaningful if bounds are valid
439466310dbd3073add2ec934e336c30deaaf702eaerobertphillips@google.com    mutable SkBool8     fIsOval;
440ca0c8389e2fd1c7f528869beb77a6c8587d59f29robertphillips@google.com
4411dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    SkPoint*            fPoints; // points to begining of the allocation
4421dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    uint8_t*            fVerbs; // points just past the end of the allocation (verbs grow backwards)
4431dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int                 fVerbCnt;
4441dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    int                 fPointCnt;
4451dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    size_t              fFreeSpace; // redundant but saves computation
446277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com    SkTDArray<SkScalar> fConicWeights;
447277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com
4481dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    enum {
4491dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs.
4501dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    };
4511ab9f737f000e530f0c7713c8fad282f39e26efecommit-bot@chromium.org    mutable uint32_t    fGenerationID;
452f48e4755282d3d185f42fd2dd964d4bbd9887ee4commit-bot@chromium.org    SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
4531dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
4540efb21bd1cd359b732a59753f3c1da096aab561arobertphillips@google.com    friend class PathRefTest_Private;
4551dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    typedef SkRefCnt INHERITED;
4561dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com};
4571dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
4581dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com#endif
459