15985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/*
25985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Copyright 2012 Google Inc.
35985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com *
45985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
55985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * found in the LICENSE file.
65985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */
75985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
85985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#ifndef SkRRect_DEFINED
95985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#define SkRRect_DEFINED
105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#include "SkRect.h"
125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#include "SkPoint.h"
135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comclass SkPath;
1520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.comclass SkMatrix;
164ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// Path forward:
185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//   core work
195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add validate method (all radii positive, all radii sums < rect size, etc.)
205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add contains(SkRect&)  - for clip stack
215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add contains(SkRRect&) - for clip stack
225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add heart rect computation (max rect inside RR)
235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add 9patch rect computation
245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add growToInclude(SkPath&)
255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//   analysis
265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      check on # of rectorus's the RRs could handle
285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//   rendering work
2914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org//      update SkPath.addRRect() to only use quads
305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      add GM and bench
315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//   further out
325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com//      detect and triangulate RRectorii rather than falling back to SW in Ganesh
33c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com//
345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/** \class SkRRect
365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
37c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    The SkRRect class represents a rounded rect with a potentially different
38c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    radii for each corner. It does not have a constructor so must be
39c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    initialized with one of the initialization functions (e.g., setEmpty,
405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    setRectRadii, etc.)
415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
42c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    This class is intended to roughly match CSS' border-*-*-radius capabilities.
435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    This means:
44c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        If either of a corner's radii are 0 the corner will be square.
455985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        Negative radii are not allowed (they are clamped to zero).
465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        If the corner curves overlap they will be proportionally reduced to fit.
475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com*/
485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comclass SK_API SkRRect {
495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.compublic:
50c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
515985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Enum to capture the various possible subtypes of RR. Accessed
525985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * by type(). The subtypes become progressively less restrictive.
535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    enum Type {
550da23a5184cf8ee658c4f1ac45b798ddf7e73002tomhudson@google.com        // !< Internal indicator that the sub type must be computed.
560da23a5184cf8ee658c4f1ac45b798ddf7e73002tomhudson@google.com        kUnknown_Type = -1,
570da23a5184cf8ee658c4f1ac45b798ddf7e73002tomhudson@google.com
585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        // !< The RR is empty
595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kEmpty_Type,
605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< The RR is actually a (non-empty) rect (i.e., at least one radius
625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< at each corner is zero)
63c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        kRect_Type,
645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
65c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< and >= width/2 and all the y radii are equal and >= height/2
67c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        kOval_Type,
685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
69c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        //!< The RR is non-empty and all the x radii are equal & all y radii
70c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        //!< are equal but it is not an oval (i.e., there are lines between
715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< the curves) nor a rect (i.e., both radii are non-zero)
72c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com        kSimple_Type,
735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
74f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< The RR is non-empty and the two left x radii are equal, the two top
75f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< y radii are equal, and the same for the right and bottom but it is
76f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< neither an rect, oval, nor a simple RR. It is called "nine patch"
77f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< because the centers of the corner ellipses form an axis aligned
78f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< rect with edges that divide the RR into an 9 rectangular patches:
79f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        //!< an interior patch, four edge patches, and four corner patches.
80f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org        kNinePatch_Type,
81f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org
825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< A fully general (non-empty) RR. Some of the x and/or y radii are
835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< different from the others and there must be one corner where
845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        //!< both radii are non-zero.
855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kComplex_Type,
865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    };
875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
88c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Returns the RR's sub type.
905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    Type getType() const {
925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkDEBUGCODE(this->validate();)
935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        if (kUnknown_Type == fType) {
955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            this->computeType();
965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        }
975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkASSERT(kUnknown_Type != fType);
985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        return fType;
995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
1005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    Type type() const { return this->getType(); }
1024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1034ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
1044ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    inline bool isRect() const { return kRect_Type == this->getType(); }
1054ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    inline bool isOval() const { return kOval_Type == this->getType(); }
1064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    inline bool isSimple() const { return kSimple_Type == this->getType(); }
107c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    inline bool isSimpleCircular() const {
108c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org        return this->isSimple() && fRadii[0].fX == fRadii[0].fY;
109c2f7824436d05da6e8514d06a54773538aace028commit-bot@chromium.org    }
110f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org    inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
1114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    inline bool isComplex() const { return kComplex_Type == this->getType(); }
1124ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
113821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org    bool allCornersCircular() const;
114821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org
11537071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    SkScalar width() const { return fRect.width(); }
11637071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    SkScalar height() const { return fRect.height(); }
11737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org
118c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
1195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
1205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
121c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    void setEmpty() {
1225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fRect.setEmpty();
1235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        memset(fRadii, 0, sizeof(fRadii));
1245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fType = kEmpty_Type;
1255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkDEBUGCODE(this->validate();)
1275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
1285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
129c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
1305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Set this RR to match the supplied rect. All radii will be 0.
1315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
1325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    void setRect(const SkRect& rect) {
1335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        if (rect.isEmpty()) {
1345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            this->setEmpty();
1355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            return;
1365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        }
1375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1385985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fRect = rect;
1395985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        memset(fRadii, 0, sizeof(fRadii));
1405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fType = kRect_Type;
1415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkDEBUGCODE(this->validate();)
1435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
1445985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
145c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
1465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Set this RR to match the supplied oval. All x radii will equal half the
1475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * width and all y radii will equal half the height.
1485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
1495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    void setOval(const SkRect& oval) {
1505985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        if (oval.isEmpty()) {
1515985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            this->setEmpty();
1525985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            return;
1535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        }
1545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1555985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkScalar xRad = SkScalarHalf(oval.width());
1565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkScalar yRad = SkScalarHalf(oval.height());
1575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fRect = oval;
1595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        for (int i = 0; i < 4; ++i) {
1605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com            fRadii[i].set(xRad, yRad);
1615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        }
1625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        fType = kOval_Type;
1635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        SkDEBUGCODE(this->validate();)
1655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
1665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
167c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
1685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Initialize the RR with the same radii for all four corners.
1695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
1705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
1715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
172c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    /**
173f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org     * Initialize the rr with one radius per-side.
174f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org     */
175f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org    void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
176f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org                      SkScalar rightRad, SkScalar bottomRad);
177f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org
178f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org    /**
1795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     * Initialize the RR with potentially different radii for all four corners.
1805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com     */
1815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    void setRectRadii(const SkRect& rect, const SkVector radii[4]);
1825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
183c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    // The radii are stored in UL, UR, LR, LL order.
1845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    enum Corner {
1855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kUpperLeft_Corner,
1865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kUpperRight_Corner,
1875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kLowerRight_Corner,
1885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        kLowerLeft_Corner
1895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    };
1905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
1915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    const SkRect& rect() const { return fRect; }
1925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    const SkVector& radii(Corner corner) const { return fRadii[corner]; }
1934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    const SkRect& getBounds() const { return fRect; }
1944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    /**
1964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     *  When a rrect is simple, all of its radii are equal. This returns one
1974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     *  of those radii. This call requires the rrect to be non-complex.
1984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     */
1994ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    const SkVector& getSimpleRadii() const {
2004ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkASSERT(!this->isComplex());
2014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        return fRadii[0];
2024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
2045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    friend bool operator==(const SkRRect& a, const SkRRect& b) {
2055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        return a.fRect == b.fRect &&
2064bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com               SkScalarsEqual(a.fRadii[0].asScalars(),
2074bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com                              b.fRadii[0].asScalars(), 8);
2085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
2095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
2105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    friend bool operator!=(const SkRRect& a, const SkRRect& b) {
2115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com        return a.fRect != b.fRect ||
2124bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com               !SkScalarsEqual(a.fRadii[0].asScalars(),
2134bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com                               b.fRadii[0].asScalars(), 8);
2145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    }
2155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
2165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    /**
217bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  Call inset on the bounds, and adjust the radii to reflect what happens
218bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  in stroking: If the corner is sharp (no curvature), leave it alone,
219bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  otherwise we grow/shrink the radii by the amount of the inset. If a
220bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  given radius becomes negative, it is pinned to 0.
221bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *
222bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  It is valid for dst == this.
223bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     */
22437071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
225bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org
22637071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    void inset(SkScalar dx, SkScalar dy) {
22737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org        this->inset(dx, dy, this);
22837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    }
229bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org
230bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org    /**
231bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  Call outset on the bounds, and adjust the radii to reflect what happens
232bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  in stroking: If the corner is sharp (no curvature), leave it alone,
233bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  otherwise we grow/shrink the radii by the amount of the inset. If a
234bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  given radius becomes negative, it is pinned to 0.
235bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *
236bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     *  It is valid for dst == this.
237bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org     */
23837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
23937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org        this->inset(-dx, -dy, dst);
24037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    }
24137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    void outset(SkScalar dx, SkScalar dy) {
24237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org        this->inset(-dx, -dy, this);
24337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org    }
244f1f66c0c8623805fdb88f09c0d87cbdd1745e12bskia.committer@gmail.com
245fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org    /**
246fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org     * Translate the rrect by (dx, dy).
247fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org     */
248fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org    void offset(SkScalar dx, SkScalar dy) {
249fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org        fRect.offset(dx, dy);
250fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org    }
25137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org
25232c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com    /**
25332c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com     *  Returns true if 'rect' is wholy inside the RR, and both
25432c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com     *  are not empty.
25532c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com     */
25632c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com    bool contains(const SkRect& rect) const;
25732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com
2585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    SkDEBUGCODE(void validate() const;)
2595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
2604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    enum {
2614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        kSizeInMemory = 12 * sizeof(SkScalar)
2624ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    };
263306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
2644ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    /**
2654ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     *  Write the rrect into the specified buffer. This is guaranteed to always
2664ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     *  write kSizeInMemory bytes, and that value is guaranteed to always be
2674ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     *  a multiple of 4. Return kSizeInMemory.
2684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     */
2694faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t writeToMemory(void* buffer) const;
2704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    /**
2724faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * Reads the rrect from the specified buffer
2734faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *
2744faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * If the specified buffer is large enough, this will read kSizeInMemory bytes,
2754faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * and that value is guaranteed to always be a multiple of 4.
2764faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *
2774faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param buffer Memory to read from
2784faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @param length Amount of memory available in the buffer
2794faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     * @return number of bytes read (must be a multiple of 4) or
2804faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org     *         0 if there was not enough memory available
2814ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com     */
2824faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t readFromMemory(const void* buffer, size_t length);
2834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
28420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com    /**
28520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *  Transform by the specified matrix, and put the result in dst.
28620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *
28720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *  @param matrix SkMatrix specifying the transform. Must only contain
28820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *      scale and/or translate, or this call will fail.
28920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *  @param dst SkRRect to store the result. It is an error to use this,
29020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *      which would make this function no longer const.
29120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     *  @return true on success, false on failure. If false, dst is unmodified.
29220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com     */
29320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com    bool transform(const SkMatrix& matrix, SkRRect* dst) const;
29420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com
295b6b02526438d6839481fb40ccf610d28f7652397bsalomon#ifdef SK_DEVELOPER
296b6b02526438d6839481fb40ccf610d28f7652397bsalomon    /**
297b6b02526438d6839481fb40ccf610d28f7652397bsalomon     * Prints the rrect using SkDebugf. This is intended for Skia development debugging. Don't
298b6b02526438d6839481fb40ccf610d28f7652397bsalomon     * rely on the existence of this function or the formatting of its output.
299b6b02526438d6839481fb40ccf610d28f7652397bsalomon     */
300b6b02526438d6839481fb40ccf610d28f7652397bsalomon    void dump() const;
301b6b02526438d6839481fb40ccf610d28f7652397bsalomon#endif
302b6b02526438d6839481fb40ccf610d28f7652397bsalomon
3035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comprivate:
3045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    SkRect fRect;
3055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
306c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com    SkVector fRadii[4];
3075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    mutable Type fType;
3085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    // TODO: add padding so we can use memcpy for flattening and not copy
3095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    // uninitialized data
3105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
3115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com    void computeType() const;
31232c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com    bool checkCornerContainment(SkScalar x, SkScalar y) const;
3134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
3144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    // to access fRadii directly
3154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    friend class SkPath;
3165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com};
3175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com
318852030103e47fabc3c766122140920fa19e17775robertphillips@google.com#endif
319