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