12179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com/*
22179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com * Copyright 2012 Google Inc.
32179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com *
42179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
52179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com * found in the LICENSE file.
62179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com */
72179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
82179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com#ifndef SkRRect_DEFINED
92179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com#define SkRRect_DEFINED
102179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
112179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com#include "SkRect.h"
122179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com#include "SkPoint.h"
132179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1440bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.comclass SkPath;
15c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.comclass SkMatrix;
1640bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
172179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com// Path forward:
182179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//   core work
192179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add validate method (all radii positive, all radii sums < rect size, etc.)
202179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add contains(SkRect&)  - for clip stack
212179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add contains(SkRRect&) - for clip stack
222179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add heart rect computation (max rect inside RR)
232179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add 9patch rect computation
242179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add growToInclude(SkPath&)
252179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//   analysis
262179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
272179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      check on # of rectorus's the RRs could handle
282179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//   rendering work
298a428faa7234318fe74571ddb417e1cc43f7d193robertphillips@google.com//      add entry points (clipRRect, drawRRect) - plumb down to SkBaseDevice
302179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      update SkPath.addRRect() to take an SkRRect - only use quads
312179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//          -- alternatively add addRRectToPath here
322179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add GM and bench
332179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//   clipping opt
342179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      update SkClipStack to perform logic with RRs
352179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//   further out
362179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      add RR rendering shader to Ganesh (akin to cicle drawing code)
372179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//          - only for simple RRs
382179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com//      detect and triangulate RRectorii rather than falling back to SW in Ganesh
39f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com//
402179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
412179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com/** \class SkRRect
422179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
43f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    The SkRRect class represents a rounded rect with a potentially different
44f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    radii for each corner. It does not have a constructor so must be
45f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    initialized with one of the initialization functions (e.g., setEmpty,
462179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    setRectRadii, etc.)
472179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
48f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    This class is intended to roughly match CSS' border-*-*-radius capabilities.
492179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    This means:
50f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        If either of a corner's radii are 0 the corner will be square.
512179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        Negative radii are not allowed (they are clamped to zero).
522179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        If the corner curves overlap they will be proportionally reduced to fit.
532179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com*/
542179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.comclass SK_API SkRRect {
552179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.compublic:
56f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
572179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Enum to capture the various possible subtypes of RR. Accessed
582179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * by type(). The subtypes become progressively less restrictive.
592179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
602179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    enum Type {
619c8e9fb3f1b5aac7503ddfe267cdeac6f6ba6fc6tomhudson@google.com        // !< Internal indicator that the sub type must be computed.
629c8e9fb3f1b5aac7503ddfe267cdeac6f6ba6fc6tomhudson@google.com        kUnknown_Type = -1,
639c8e9fb3f1b5aac7503ddfe267cdeac6f6ba6fc6tomhudson@google.com
642179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        // !< The RR is empty
652179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kEmpty_Type,
662179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
672179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< The RR is actually a (non-empty) rect (i.e., at least one radius
682179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< at each corner is zero)
69f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        kRect_Type,
702179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
71f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
722179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< and >= width/2 and all the y radii are equal and >= height/2
73f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        kOval_Type,
742179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
75f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        //!< The RR is non-empty and all the x radii are equal & all y radii
76f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        //!< are equal but it is not an oval (i.e., there are lines between
772179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< the curves) nor a rect (i.e., both radii are non-zero)
78f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com        kSimple_Type,
792179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
802179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< A fully general (non-empty) RR. Some of the x and/or y radii are
812179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< different from the others and there must be one corner where
822179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        //!< both radii are non-zero.
832179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kComplex_Type,
842179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    };
852179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
86f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
872179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Returns the RR's sub type.
882179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
8940bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    Type getType() const {
902179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkDEBUGCODE(this->validate();)
912179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
922179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        if (kUnknown_Type == fType) {
932179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            this->computeType();
942179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        }
952179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkASSERT(kUnknown_Type != fType);
962179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        return fType;
972179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
982179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
9940bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    Type type() const { return this->getType(); }
10040bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
10140bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
10240bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    inline bool isRect() const { return kRect_Type == this->getType(); }
10340bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    inline bool isOval() const { return kOval_Type == this->getType(); }
10440bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    inline bool isSimple() const { return kSimple_Type == this->getType(); }
10540bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    inline bool isComplex() const { return kComplex_Type == this->getType(); }
10640bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
107703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    SkScalar width() const { return fRect.width(); }
108703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    SkScalar height() const { return fRect.height(); }
109703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org
110f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
1112179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
1122179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
113f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    void setEmpty() {
1142179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fRect.setEmpty();
1152179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        memset(fRadii, 0, sizeof(fRadii));
1162179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fType = kEmpty_Type;
1172179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1182179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkDEBUGCODE(this->validate();)
1192179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
1202179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
121f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
1222179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Set this RR to match the supplied rect. All radii will be 0.
1232179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
1242179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    void setRect(const SkRect& rect) {
1252179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        if (rect.isEmpty()) {
1262179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            this->setEmpty();
1272179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            return;
1282179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        }
1292179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1302179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fRect = rect;
1312179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        memset(fRadii, 0, sizeof(fRadii));
1322179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fType = kRect_Type;
1332179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1342179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkDEBUGCODE(this->validate();)
1352179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
1362179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
137f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
1382179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Set this RR to match the supplied oval. All x radii will equal half the
1392179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * width and all y radii will equal half the height.
1402179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
1412179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    void setOval(const SkRect& oval) {
1422179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        if (oval.isEmpty()) {
1432179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            this->setEmpty();
1442179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            return;
1452179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        }
1462179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1472179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkScalar xRad = SkScalarHalf(oval.width());
1482179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkScalar yRad = SkScalarHalf(oval.height());
1492179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1502179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fRect = oval;
1512179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        for (int i = 0; i < 4; ++i) {
1522179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com            fRadii[i].set(xRad, yRad);
1532179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        }
1542179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        fType = kOval_Type;
1552179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1562179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        SkDEBUGCODE(this->validate();)
1572179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
1582179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
159f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
1602179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Initialize the RR with the same radii for all four corners.
1612179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
1622179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
1632179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
164f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    /**
1652179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     * Initialize the RR with potentially different radii for all four corners.
1662179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com     */
1672179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    void setRectRadii(const SkRect& rect, const SkVector radii[4]);
1682179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
169f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    // The radii are stored in UL, UR, LR, LL order.
1702179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    enum Corner {
1712179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kUpperLeft_Corner,
1722179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kUpperRight_Corner,
1732179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kLowerRight_Corner,
1742179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        kLowerLeft_Corner
1752179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    };
1762179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1772179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    const SkRect& rect() const { return fRect; }
1782179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    const SkVector& radii(Corner corner) const { return fRadii[corner]; }
17940bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    const SkRect& getBounds() const { return fRect; }
18040bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
18140bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    /**
18240bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     *  When a rrect is simple, all of its radii are equal. This returns one
18340bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     *  of those radii. This call requires the rrect to be non-complex.
18440bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     */
18540bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    const SkVector& getSimpleRadii() const {
18640bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com        SkASSERT(!this->isComplex());
18740bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com        return fRadii[0];
18840bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    }
1892179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1902179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    friend bool operator==(const SkRRect& a, const SkRRect& b) {
1912179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        return a.fRect == b.fRect &&
1923f48c83fb549a9843334cd3f86a0429d5c62e74adjsollen@google.com               SkScalarsEqual(a.fRadii[0].asScalars(),
1933f48c83fb549a9843334cd3f86a0429d5c62e74adjsollen@google.com                              b.fRadii[0].asScalars(), 8);
1942179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
1952179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
1962179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    friend bool operator!=(const SkRRect& a, const SkRRect& b) {
1972179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com        return a.fRect != b.fRect ||
1983f48c83fb549a9843334cd3f86a0429d5c62e74adjsollen@google.com               !SkScalarsEqual(a.fRadii[0].asScalars(),
1993f48c83fb549a9843334cd3f86a0429d5c62e74adjsollen@google.com                               b.fRadii[0].asScalars(), 8);
2002179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    }
2012179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
2022179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    /**
203fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  Call inset on the bounds, and adjust the radii to reflect what happens
204fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  in stroking: If the corner is sharp (no curvature), leave it alone,
205fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  otherwise we grow/shrink the radii by the amount of the inset. If a
206fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  given radius becomes negative, it is pinned to 0.
207fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *
208fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  It is valid for dst == this.
209fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     */
210703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
211fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org
212703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    void inset(SkScalar dx, SkScalar dy) {
213703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org        this->inset(dx, dy, this);
214703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    }
215fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org
216fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org    /**
217fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  Call outset on the bounds, and adjust the radii to reflect what happens
218fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  in stroking: If the corner is sharp (no curvature), leave it alone,
219fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  otherwise we grow/shrink the radii by the amount of the inset. If a
220fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  given radius becomes negative, it is pinned to 0.
221fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *
222fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     *  It is valid for dst == this.
223fe41375efa844fe61802cf51ac4dd92ab8a411d1mike@reedtribe.org     */
224703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
225703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org        this->inset(-dx, -dy, dst);
226703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    }
227703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    void outset(SkScalar dx, SkScalar dy) {
228703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org        this->inset(-dx, -dy, this);
229703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org    }
230703e6a0464633243ca12850fead31f61fd6b9a2bmike@reedtribe.org
231d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com    /**
232d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com     *  Returns true if 'rect' is wholy inside the RR, and both
233d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com     *  are not empty.
234d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com     */
235d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com    bool contains(const SkRect& rect) const;
236d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com
2372179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    SkDEBUGCODE(void validate() const;)
2382179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
23940bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    enum {
24040bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com        kSizeInMemory = 12 * sizeof(SkScalar)
24140bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    };
24208326dfc5f1f166488f6beaee3a3108c46b65bbfskia.committer@gmail.com
24340bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    /**
24440bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     *  Write the rrect into the specified buffer. This is guaranteed to always
24540bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     *  write kSizeInMemory bytes, and that value is guaranteed to always be
24640bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     *  a multiple of 4. Return kSizeInMemory.
24740bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     */
2483a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org    size_t writeToMemory(void* buffer) const;
24940bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
25040bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    /**
2513a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * Reads the rrect from the specified buffer
2523a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     *
2533a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * If the specified buffer is large enough, this will read kSizeInMemory bytes,
2543a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * and that value is guaranteed to always be a multiple of 4.
2553a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     *
2563a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * @param buffer Memory to read from
2573a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * @param length Amount of memory available in the buffer
2583a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     * @return number of bytes read (must be a multiple of 4) or
2593a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org     *         0 if there was not enough memory available
26040bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com     */
2613a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org    size_t readFromMemory(const void* buffer, size_t length);
26240bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
263c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com    /**
264c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *  Transform by the specified matrix, and put the result in dst.
265c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *
266c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *  @param matrix SkMatrix specifying the transform. Must only contain
267c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *      scale and/or translate, or this call will fail.
268c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *  @param dst SkRRect to store the result. It is an error to use this,
269c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *      which would make this function no longer const.
270c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     *  @return true on success, false on failure. If false, dst is unmodified.
271c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com     */
272c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com    bool transform(const SkMatrix& matrix, SkRRect* dst) const;
273c54761f13ae28def75a31eb0dc5963aba978e228scroggo@google.com
2742179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.comprivate:
2752179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    SkRect fRect;
2762179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
277f8f29177dd064bcfa4a7458e24434a807bca20b4skia.committer@gmail.com    SkVector fRadii[4];
2782179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    mutable Type fType;
2792179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    // TODO: add padding so we can use memcpy for flattening and not copy
2802179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    // uninitialized data
2812179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
2822179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com    void computeType() const;
283d6b76351fcc447f5ef8c883b6d6fbf7039f13c94robertphillips@google.com    bool checkCornerContainment(SkScalar x, SkScalar y) const;
28440bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com
28540bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    // to access fRadii directly
28640bb1e071dfd54678c0e9458bec337a1a38ed2d7reed@google.com    friend class SkPath;
2872179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com};
2882179b65d2ff87638ac83545bf3db1f59cf425457robertphillips@google.com
289d96f8bfd294adc44d3ee771150f2f3721d60855brobertphillips@google.com#endif
290