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; 161e3b79e0c6480ea7e372ec4e5a2c5e11a03a845dBrian Salomonclass SkRBuffer; 171e3b79e0c6480ea7e372ec4e5a2c5e11a03a845dBrian Salomonclass SkWBuffer; 184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// Path forward: 205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// core work 215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add contains(SkRect&) - for clip stack 225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add contains(SkRRect&) - for clip stack 235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add heart rect computation (max rect inside RR) 245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add 9patch rect computation 255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add growToInclude(SkPath&) 265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// analysis 275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// use growToInclude to fit skp round rects & generate stats (RRs vs. real paths) 285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// check on # of rectorus's the RRs could handle 295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// rendering work 3014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org// update SkPath.addRRect() to only use quads 315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// add GM and bench 325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// further out 335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// detect and triangulate RRectorii rather than falling back to SW in Ganesh 34c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com// 355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/** \class SkRRect 375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 38c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com The SkRRect class represents a rounded rect with a potentially different 39c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com radii for each corner. It does not have a constructor so must be 40c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com initialized with one of the initialization functions (e.g., setEmpty, 415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com setRectRadii, etc.) 425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 43c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com This class is intended to roughly match CSS' border-*-*-radius capabilities. 445985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com This means: 45c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com If either of a corner's radii are 0 the corner will be square. 465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com Negative radii are not allowed (they are clamped to zero). 475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com If the corner curves overlap they will be proportionally reduced to fit. 485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com*/ 495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comclass SK_API SkRRect { 505985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.compublic: 510a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon /** Default initialized to a rrect at the origin with zero width and height. */ 520a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon SkRRect() = default; 530a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon 547f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon SkRRect(const SkRRect&) = default; 557f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon SkRRect& operator=(const SkRRect&) = default; 567f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon 57c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Enum to capture the various possible subtypes of RR. Accessed 595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * by type(). The subtypes become progressively less restrictive. 605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com enum Type { 620a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon // !< The RR has zero width and/or zero height. All radii are zero. 635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kEmpty_Type, 645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< The RR is actually a (non-empty) rect (i.e., at least one radius 665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< at each corner is zero) 67c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com kRect_Type, 685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 69c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal 705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< and >= width/2 and all the y radii are equal and >= height/2 71c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com kOval_Type, 725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 73c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com //!< The RR is non-empty and all the x radii are equal & all y radii 74c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com //!< are equal but it is not an oval (i.e., there are lines between 755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< the curves) nor a rect (i.e., both radii are non-zero) 76c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com kSimple_Type, 775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 78f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< The RR is non-empty and the two left x radii are equal, the two top 79f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< y radii are equal, and the same for the right and bottom but it is 80f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< neither an rect, oval, nor a simple RR. It is called "nine patch" 81f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< because the centers of the corner ellipses form an axis aligned 82f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< rect with edges that divide the RR into an 9 rectangular patches: 83f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org //!< an interior patch, four edge patches, and four corner patches. 84f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org kNinePatch_Type, 85f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< A fully general (non-empty) RR. Some of the x and/or y radii are 875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< different from the others and there must be one corner where 885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com //!< both radii are non-zero. 895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kComplex_Type, 90ba9741d46718c44d6e95e990c476d865c1cf4e55Adrienne Walker 91ba9741d46718c44d6e95e990c476d865c1cf4e55Adrienne Walker kLastType = kComplex_Type, 925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com }; 935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 94c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Returns the RR's sub type. 965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com Type getType() const { 9849da334086c4a2c0bc4cb99e97965600dcb72f73Robert Phillips SkASSERT(this->isValid()); 99727b8c1d1c0ba0634a97bff601e7af96bfd7daf8reed return static_cast<Type>(fType); 1005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com Type type() const { return this->getType(); } 1034ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 1044ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com inline bool isEmpty() const { return kEmpty_Type == this->getType(); } 1054ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com inline bool isRect() const { return kRect_Type == this->getType(); } 1064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com inline bool isOval() const { return kOval_Type == this->getType(); } 1074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com inline bool isSimple() const { return kSimple_Type == this->getType(); } 108f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); } 1094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com inline bool isComplex() const { return kComplex_Type == this->getType(); } 1104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 11137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkScalar width() const { return fRect.width(); } 11237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkScalar height() const { return fRect.height(); } 11337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 114c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 115242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed * kSimple means that all corners have the same x,y radii. This returns the top/left 116242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed * corner's radii as representative of all corners. If the RRect is kComplex, then 117242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed * this still returns that corner's radii, but it is not indicative of the other corners. 118242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed */ 119242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed SkVector getSimpleRadii() const { 120242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed return fRadii[0]; 121242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed } 122242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed 123242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed /** 1240a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * Same as default initialized - zero width and height at the origin. 1255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 1260a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon void setEmpty() { *this = SkRRect(); } 1275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 128c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 1295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Set this RR to match the supplied rect. All radii will be 0. 1305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 1315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com void setRect(const SkRect& rect) { 1320a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon if (!this->initializeRect(rect)) { 1335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 1345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com memset(fRadii, 0, sizeof(fRadii)); 1375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kRect_Type; 1385985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 13949da334086c4a2c0bc4cb99e97965600dcb72f73Robert Phillips SkASSERT(this->isValid()); 1405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1420a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon /** Makes an empty rrect at the origin with zero width and height. */ 1430a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon static SkRRect MakeEmpty() { return SkRRect(); } 144ee295645bd91fcbe1714847c5fe5341759037cc5bsalomon 145021f631dc66da06dbe4aed21df2f27daecce9db7reed static SkRRect MakeRect(const SkRect& r) { 146021f631dc66da06dbe4aed21df2f27daecce9db7reed SkRRect rr; 147021f631dc66da06dbe4aed21df2f27daecce9db7reed rr.setRect(r); 148021f631dc66da06dbe4aed21df2f27daecce9db7reed return rr; 149021f631dc66da06dbe4aed21df2f27daecce9db7reed } 150ee295645bd91fcbe1714847c5fe5341759037cc5bsalomon 15130c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips static SkRRect MakeOval(const SkRect& oval) { 15230c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips SkRRect rr; 15330c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips rr.setOval(oval); 15430c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips return rr; 15530c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips } 15630c4cae7d3a26252e7e45adf6e5722b34adf6848robertphillips 1574a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { 1584a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon SkRRect rr; 1594a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon rr.setRectXY(rect, xRad, yRad); 1604a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon return rr; 1614a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon } 1624a4f14ba3f93cc6bb9146be0f029a9badb1b95d9bsalomon 163c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 1645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Set this RR to match the supplied oval. All x radii will equal half the 1655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * width and all y radii will equal half the height. 1665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 1675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com void setOval(const SkRect& oval) { 1680a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon if (!this->initializeRect(oval)) { 1695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 1705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 17205302f8f24cf0254e1fa713fbfc766387505e511robertphillips SkScalar xRad = SkScalarHalf(fRect.width()); 17305302f8f24cf0254e1fa713fbfc766387505e511robertphillips SkScalar yRad = SkScalarHalf(fRect.height()); 1745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 1765985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].set(xRad, yRad); 1775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kOval_Type; 1795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 18049da334086c4a2c0bc4cb99e97965600dcb72f73Robert Phillips SkASSERT(this->isValid()); 1815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 183c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 1845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Initialize the RR with the same radii for all four corners. 1855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 1865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad); 1875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 188c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com /** 189f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org * Initialize the rr with one radius per-side. 190f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org */ 191f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad, 192f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkScalar rightRad, SkScalar bottomRad); 193f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 194f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org /** 1955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com * Initialize the RR with potentially different radii for all four corners. 1965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com */ 1975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com void setRectRadii(const SkRect& rect, const SkVector radii[4]); 1985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 199c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // The radii are stored in UL, UR, LR, LL order. 2005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com enum Corner { 2015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kUpperLeft_Corner, 2025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kUpperRight_Corner, 2035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kLowerRight_Corner, 2045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com kLowerLeft_Corner 2055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com }; 2065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com const SkRect& rect() const { return fRect; } 208242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed SkVector radii(Corner corner) const { return fRadii[corner]; } 2094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com const SkRect& getBounds() const { return fRect; } 2104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com friend bool operator==(const SkRRect& a, const SkRRect& b) { 212df429f3beac1c191289ba1e3bd918bf84df57bf5Cary Clark return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8); 2135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com friend bool operator!=(const SkRRect& a, const SkRRect& b) { 216df429f3beac1c191289ba1e3bd918bf84df57bf5Cary Clark return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8); 2175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com /** 220bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * Call inset on the bounds, and adjust the radii to reflect what happens 221bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * in stroking: If the corner is sharp (no curvature), leave it alone, 222bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * otherwise we grow/shrink the radii by the amount of the inset. If a 223bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * given radius becomes negative, it is pinned to 0. 224bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * 2250a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * If the inset amount is larger than the width/height then the rrect collapses to 2260a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * a degenerate line or point. 2270a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * 2280a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * If the inset is sufficiently negative to cause the bounds to become infinite then 2290a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * the result is a default initialized rrect. 2300a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * 231bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * It is valid for dst == this. 232bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org */ 23337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const; 234bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org 23537071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org void inset(SkScalar dx, SkScalar dy) { 23637071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org this->inset(dx, dy, this); 23737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 238bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org 239bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org /** 240bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * Call outset on the bounds, and adjust the radii to reflect what happens 241bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * in stroking: If the corner is sharp (no curvature), leave it alone, 242bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * otherwise we grow/shrink the radii by the amount of the inset. If a 243bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * given radius becomes negative, it is pinned to 0. 244bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * 245bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org * It is valid for dst == this. 246bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org */ 24737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const { 24837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org this->inset(-dx, -dy, dst); 24937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 25037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org void outset(SkScalar dx, SkScalar dy) { 25137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org this->inset(-dx, -dy, this); 25237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 253f1f66c0c8623805fdb88f09c0d87cbdd1745e12bskia.committer@gmail.com 254fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org /** 255fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org * Translate the rrect by (dx, dy). 256fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org */ 257fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org void offset(SkScalar dx, SkScalar dy) { 258fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org fRect.offset(dx, dy); 259fbde87f53d659ae2bd616751e466c887b0f3bee5commit-bot@chromium.org } 26037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 2617f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const { 2627f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType); 2637f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon } 2647f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon 26532c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com /** 26632c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com * Returns true if 'rect' is wholy inside the RR, and both 26732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com * are not empty. 26832c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com */ 26932c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com bool contains(const SkRect& rect) const; 27032c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com 27149da334086c4a2c0bc4cb99e97965600dcb72f73Robert Phillips bool isValid() const; 2725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com enum { 2744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com kSizeInMemory = 12 * sizeof(SkScalar) 2754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com }; 276306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com 2774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com /** 2784ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com * Write the rrect into the specified buffer. This is guaranteed to always 2794ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com * write kSizeInMemory bytes, and that value is guaranteed to always be 2804ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com * a multiple of 4. Return kSizeInMemory. 2814ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com */ 2824faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t writeToMemory(void* buffer) const; 2831e3b79e0c6480ea7e372ec4e5a2c5e11a03a845dBrian Salomon void writeToBuffer(SkWBuffer*) const; 2844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2854ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com /** 2864faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * Reads the rrect from the specified buffer 2874faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * 2884faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * If the specified buffer is large enough, this will read kSizeInMemory bytes, 2894faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * and that value is guaranteed to always be a multiple of 4. 2904faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * 2914faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @param buffer Memory to read from 2924faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @param length Amount of memory available in the buffer 2934faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @return number of bytes read (must be a multiple of 4) or 2944faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * 0 if there was not enough memory available 2954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com */ 2964faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t readFromMemory(const void* buffer, size_t length); 2971e3b79e0c6480ea7e372ec4e5a2c5e11a03a845dBrian Salomon bool readFromBuffer(SkRBuffer*); 2984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 29920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com /** 30020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * Transform by the specified matrix, and put the result in dst. 30120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * 30220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * @param matrix SkMatrix specifying the transform. Must only contain 30320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * scale and/or translate, or this call will fail. 30420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * @param dst SkRRect to store the result. It is an error to use this, 30520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com * which would make this function no longer const. 30620d479c088ad6dc06e16b13a3e6b2dfefa845430Mike Klein * @return true on success, false on failure. 30720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com */ 30820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com bool transform(const SkMatrix& matrix, SkRRect* dst) const; 30920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 310e05fed0d6339c63c8cceff74af0b8d120c07e54creed void dump(bool asHex) const; 311e05fed0d6339c63c8cceff74af0b8d120c07e54creed void dump() const { this->dump(false); } 312e05fed0d6339c63c8cceff74af0b8d120c07e54creed void dumpHex() const { this->dump(true); } 313b6b02526438d6839481fb40ccf610d28f7652397bsalomon 3145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comprivate: 315242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]); 316242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed 3177f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type) 3187f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon : fRect(rect) 3197f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon , fRadii{radii[0], radii[1], radii[2], radii[3]} 3207f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon , fType(type) {} 3217f0d9f39206d0bf67e0a14e9cf3351243c9b5a1bbsalomon 3220a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon /** 3230a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully 3240a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon * initialized and false is returned. Otherwise, just fRect is initialized and true is returned. 3250a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon */ 3260a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon bool initializeRect(const SkRect&); 3275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 3288aacf2085673f6302a43d590d4d2890789b87192mtklein void computeType(); 32932c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com bool checkCornerContainment(SkScalar x, SkScalar y) const; 3305a70bc7f3cd32aaccc137c7d650cea613baa2443caryclark void scaleRadii(); 3314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 3320a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon SkRect fRect = SkRect::MakeEmpty(); 3330a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[] 3340a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}}; 3350a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes) 3360a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon int32_t fType = kEmpty_Type; 3370a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon // TODO: add padding so we can use memcpy for flattening and not copy uninitialized data 3380a241ce808511ceb1c72d6f2473b01b455ac5101Brian Salomon 3394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // to access fRadii directly 3404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com friend class SkPath; 341242135a402592e4fb40c5aba44cf8d483e68d292Mike Reed friend class SkRRectPriv; 3425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com}; 3435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 344852030103e47fabc3c766122140920fa19e17775robertphillips@google.com#endif 345