1363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger/*
2363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Copyright 2012 Google Inc.
3363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger *
4363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
5363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * found in the LICENSE file.
6363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */
7363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
8363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifndef SkRRect_DEFINED
9363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#define SkRRect_DEFINED
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkRect.h"
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkPoint.h"
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SkPath;
15910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerclass SkMatrix;
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// Path forward:
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//   core work
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add validate method (all radii positive, all radii sums < rect size, etc.)
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add contains(SkRect&)  - for clip stack
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add contains(SkRRect&) - for clip stack
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add heart rect computation (max rect inside RR)
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add 9patch rect computation
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add growToInclude(SkPath&)
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//   analysis
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      check on # of rectorus's the RRs could handle
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//   rendering work
290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger//      add entry points (clipRRect, drawRRect) - plumb down to SkBaseDevice
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      update SkPath.addRRect() to take an SkRRect - only use quads
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//          -- alternatively add addRRectToPath here
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add GM and bench
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//   clipping opt
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      update SkClipStack to perform logic with RRs
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//   further out
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      add RR rendering shader to Ganesh (akin to cicle drawing code)
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//          - only for simple RRs
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//      detect and triangulate RRectorii rather than falling back to SW in Ganesh
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger//
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger/** \class SkRRect
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    The SkRRect class represents a rounded rect with a potentially different
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    radii for each corner. It does not have a constructor so must be
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    initialized with one of the initialization functions (e.g., setEmpty,
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    setRectRadii, etc.)
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    This class is intended to roughly match CSS' border-*-*-radius capabilities.
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    This means:
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        If either of a corner's radii are 0 the corner will be square.
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Negative radii are not allowed (they are clamped to zero).
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        If the corner curves overlap they will be proportionally reduced to fit.
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger*/
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass SK_API SkRRect {
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerpublic:
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Enum to capture the various possible subtypes of RR. Accessed
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * by type(). The subtypes become progressively less restrictive.
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    enum Type {
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // !< Internal indicator that the sub type must be computed.
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kUnknown_Type = -1,
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // !< The RR is empty
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kEmpty_Type,
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< The RR is actually a (non-empty) rect (i.e., at least one radius
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< at each corner is zero)
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kRect_Type,
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< and >= width/2 and all the y radii are equal and >= height/2
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kOval_Type,
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< The RR is non-empty and all the x radii are equal & all y radii
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< are equal but it is not an oval (i.e., there are lines between
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< the curves) nor a rect (i.e., both radii are non-zero)
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kSimple_Type,
79363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< A fully general (non-empty) RR. Some of the x and/or y radii are
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< different from the others and there must be one corner where
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< both radii are non-zero.
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kComplex_Type,
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Returns the RR's sub type.
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Type getType() const {
90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkDEBUGCODE(this->validate();)
91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (kUnknown_Type == fType) {
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->computeType();
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkASSERT(kUnknown_Type != fType);
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return fType;
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Type type() const { return this->getType(); }
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inline bool isRect() const { return kRect_Type == this->getType(); }
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inline bool isOval() const { return kOval_Type == this->getType(); }
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inline bool isSimple() const { return kSimple_Type == this->getType(); }
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    inline bool isComplex() const { return kComplex_Type == this->getType(); }
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar width() const { return fRect.width(); }
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkScalar height() const { return fRect.height(); }
109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setEmpty() {
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRect.setEmpty();
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        memset(fRadii, 0, sizeof(fRadii));
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fType = kEmpty_Type;
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkDEBUGCODE(this->validate();)
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Set this RR to match the supplied rect. All radii will be 0.
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setRect(const SkRect& rect) {
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (rect.isEmpty()) {
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->setEmpty();
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return;
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRect = rect;
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        memset(fRadii, 0, sizeof(fRadii));
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fType = kRect_Type;
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkDEBUGCODE(this->validate();)
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Set this RR to match the supplied oval. All x radii will equal half the
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * width and all y radii will equal half the height.
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setOval(const SkRect& oval) {
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (oval.isEmpty()) {
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->setEmpty();
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return;
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkScalar xRad = SkScalarHalf(oval.width());
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkScalar yRad = SkScalarHalf(oval.height());
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRect = oval;
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int i = 0; i < 4; ++i) {
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fRadii[i].set(xRad, yRad);
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fType = kOval_Type;
155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkDEBUGCODE(this->validate();)
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Initialize the RR with the same radii for all four corners.
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Initialize the RR with potentially different radii for all four corners.
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setRectRadii(const SkRect& rect, const SkVector radii[4]);
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // The radii are stored in UL, UR, LR, LL order.
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    enum Corner {
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kUpperLeft_Corner,
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kUpperRight_Corner,
173363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kLowerRight_Corner,
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kLowerLeft_Corner
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkRect& rect() const { return fRect; }
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkVector& radii(Corner corner) const { return fRadii[corner]; }
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkRect& getBounds() const { return fRect; }
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  When a rrect is simple, all of its radii are equal. This returns one
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  of those radii. This call requires the rrect to be non-complex.
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
185363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkVector& getSimpleRadii() const {
186363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkASSERT(!this->isComplex());
187363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return fRadii[0];
188363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
190363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    friend bool operator==(const SkRRect& a, const SkRRect& b) {
191363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return a.fRect == b.fRect &&
192096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger               SkScalarsEqual(a.fRadii[0].asScalars(),
193096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                              b.fRadii[0].asScalars(), 8);
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
195363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    friend bool operator!=(const SkRRect& a, const SkRRect& b) {
197363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return a.fRect != b.fRect ||
198096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger               !SkScalarsEqual(a.fRadii[0].asScalars(),
199096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                               b.fRadii[0].asScalars(), 8);
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
202363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
203d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  Call inset on the bounds, and adjust the radii to reflect what happens
204d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  in stroking: If the corner is sharp (no curvature), leave it alone,
205d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  otherwise we grow/shrink the radii by the amount of the inset. If a
206d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  given radius becomes negative, it is pinned to 0.
207d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *
208d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  It is valid for dst == this.
209d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     */
210363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
211d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
212363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void inset(SkScalar dx, SkScalar dy) {
213363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->inset(dx, dy, this);
214363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
215d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
216d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    /**
217d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  Call outset on the bounds, and adjust the radii to reflect what happens
218d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  in stroking: If the corner is sharp (no curvature), leave it alone,
219d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  otherwise we grow/shrink the radii by the amount of the inset. If a
220d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  given radius becomes negative, it is pinned to 0.
221d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *
222d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     *  It is valid for dst == this.
223d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     */
224363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
225363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->inset(-dx, -dy, dst);
226363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
227363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void outset(SkScalar dx, SkScalar dy) {
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->inset(-dx, -dy, this);
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Returns true if 'rect' is wholy inside the RR, and both
2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  are not empty.
2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    bool contains(const SkRect& rect) const;
2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
237363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkDEBUGCODE(void validate() const;)
238363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
239363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    enum {
240363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kSizeInMemory = 12 * sizeof(SkScalar)
241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
244363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  Write the rrect into the specified buffer. This is guaranteed to always
245363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  write kSizeInMemory bytes, and that value is guaranteed to always be
246363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     *  a multiple of 4. Return kSizeInMemory.
247363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
248910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    size_t writeToMemory(void* buffer) const;
249363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
250363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
251910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * Reads the rrect from the specified buffer
252910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *
253910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * If the specified buffer is large enough, this will read kSizeInMemory bytes,
254910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * and that value is guaranteed to always be a multiple of 4.
255910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *
256910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * @param buffer Memory to read from
257910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * @param length Amount of memory available in the buffer
258910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     * @return number of bytes read (must be a multiple of 4) or
259910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *         0 if there was not enough memory available
260910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     */
261910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    size_t readFromMemory(const void* buffer, size_t length);
262910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
263910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    /**
264910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *  Transform by the specified matrix, and put the result in dst.
265910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *
266910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *  @param matrix SkMatrix specifying the transform. Must only contain
267910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *      scale and/or translate, or this call will fail.
268910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *  @param dst SkRRect to store the result. It is an error to use this,
269910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *      which would make this function no longer const.
270910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger     *  @return true on success, false on failure. If false, dst is unmodified.
271363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
272910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    bool transform(const SkMatrix& matrix, SkRRect* dst) const;
273363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
274363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerprivate:
275363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRect fRect;
276363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
277363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkVector fRadii[4];
278363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    mutable Type fType;
279363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // TODO: add padding so we can use memcpy for flattening and not copy
280363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // uninitialized data
281363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
282363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void computeType() const;
2837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    bool checkCornerContainment(SkScalar x, SkScalar y) const;
284363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
285363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // to access fRadii directly
286363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    friend class SkPath;
287363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
288363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
289363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif
290