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#include "SkRRect.h" 920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com#include "SkMatrix.h" 105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { 145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.isEmpty()) { 155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setEmpty(); 165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (xRad <= 0 || yRad <= 0) { 205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // all corners are square in this case 215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setRect(rect); 225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) { 265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad), 275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), yRad + yRad)); 285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(scale < SK_Scalar1); 295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com xRad = SkScalarMul(xRad, scale); 305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com yRad = SkScalarMul(yRad, scale); 315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRect = rect; 345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].set(xRad, yRad); 365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kSimple_Type; 385985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height())) { 395985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kOval_Type; 405b33211c5edafde82af781beaa1dbc295000a62frobertphillips@google.com // TODO: assert that all the x&y radii are already W/2 & H/2 415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 445985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 455985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 46f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.orgvoid SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad, 47f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkScalar rightRad, SkScalar bottomRad) { 48f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (rect.isEmpty()) { 49f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org this->setEmpty(); 50f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org return; 51f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 52f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 53f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org leftRad = SkMaxScalar(leftRad, 0); 54f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org topRad = SkMaxScalar(topRad, 0); 55f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org rightRad = SkMaxScalar(rightRad, 0); 56f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org bottomRad = SkMaxScalar(bottomRad, 0); 57f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 58f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkScalar scale = SK_Scalar1; 59f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (leftRad + rightRad > rect.width()) { 60f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org scale = SkScalarDiv(rect.width(), leftRad + rightRad); 61f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 62f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (topRad + bottomRad > rect.height()) { 63f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org scale = SkMinScalar(scale, SkScalarDiv(rect.width(), leftRad + rightRad)); 64f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 65f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 66f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (scale < SK_Scalar1) { 67f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org leftRad = SkScalarMul(leftRad, scale); 68f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org topRad = SkScalarMul(topRad, scale); 69f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org rightRad = SkScalarMul(rightRad, scale); 70f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org bottomRad = SkScalarMul(bottomRad, scale); 71f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 72f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 73f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (leftRad == rightRad && topRad == bottomRad) { 74f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (leftRad >= SkScalarHalf(rect.width()) && topRad >= SkScalarHalf(rect.height())) { 75f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kOval_Type; 76f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } else if (0 == leftRad || 0 == topRad) { 77f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org // If the left and (by equality check above) right radii are zero then it is a rect. 78f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org // Same goes for top/bottom. 79f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kRect_Type; 80f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org leftRad = 0; 81f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org topRad = 0; 82f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org rightRad = 0; 83f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org bottomRad = 0; 84f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } else { 85f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kSimple_Type; 86f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 87f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } else { 88f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kNinePatch_Type; 89f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 90f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 91f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fRect = rect; 92f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fRadii[kUpperLeft_Corner].set(leftRad, topRad); 93f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fRadii[kUpperRight_Corner].set(rightRad, topRad); 94f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fRadii[kLowerRight_Corner].set(rightRad, bottomRad); 95f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fRadii[kLowerLeft_Corner].set(leftRad, bottomRad); 96f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 97f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkDEBUGCODE(this->validate();) 98f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org} 99f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 100f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 1015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { 1025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.isEmpty()) { 1035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setEmpty(); 1045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 1055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRect = rect; 1085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com memcpy(fRadii, radii, sizeof(fRadii)); 1095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = true; 1115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Clamp negative radii to zero 1135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 1145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) { 1155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // In this case we are being a little fast & loose. Since one of 1165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // the radii is 0 the corner is square. However, the other radii 1175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // could still be non-zero and play in the global scale factor 1185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // computation. 1195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fX = 0; 1205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fY = 0; 1215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 1225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 1235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allCornersSquare) { 1275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setRect(rect); 1285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 1295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Proportionally scale down all radii to fit. Find the minimum ratio 132c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // of a side and the radii on that side (for all four sides) and use 1335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // that to scale down _all_ the radii. This algorithm is from the 1345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping 1355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Curves: 136c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // "Let f = min(Li/Si), where i is one of { top, right, bottom, left }, 1375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Si is the sum of the two corresponding radii of the corners on side i, 138c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // and Ltop = Lbottom = the width of the box, 139c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // and Lleft = Lright = the height of the box. 1405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // If f < 1, then all corner radii are reduced by multiplying them by f." 1415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalar scale = SK_Scalar1; 1425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[0].fX + fRadii[1].fX > rect.width()) { 1445985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 1455985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].fX)); 1465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[1].fY + fRadii[2].fY > rect.height()) { 1485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 1495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].fY)); 1505985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1515985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[2].fX + fRadii[3].fX > rect.width()) { 1525985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 1535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].fX)); 1545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1555985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[3].fY + fRadii[0].fY > rect.height()) { 1565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 1575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].fY)); 1585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (scale < SK_Scalar1) { 1615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 1625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fX = SkScalarMul(fRadii[i].fX, scale); 1635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fY = SkScalarMul(fRadii[i].fY, scale); 1645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // At this point we're either oval, simple, or complex (not empty or rect) 1685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // but we lazily resolve the type to avoid the work if the information 1695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // isn't required. 1705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = (SkRRect::Type) kUnknown_Type; 1715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 1735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 1745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1752cf444f7040614b43af67e368f3aa636ebeaa45askia.committer@gmail.com// This method determines if a point known to be inside the RRect's bounds is 17632c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com// inside all the corners. 17732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.combool SkRRect::checkCornerContainment(SkScalar x, SkScalar y) const { 1785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkPoint canonicalPt; // (x,y) translated to one of the quadrants 1795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com int index; 1805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (kOval_Type == this->type()) { 1825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - fRect.centerX(), y - fRect.centerY()); 1835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperLeft_Corner; // any corner will do in this case 1845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 185c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com if (x < fRect.fLeft + fRadii[kUpperLeft_Corner].fX && 1865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y < fRect.fTop + fRadii[kUpperLeft_Corner].fY) { 1875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // UL corner 1885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperLeft_Corner; 1895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fLeft + fRadii[kUpperLeft_Corner].fX), 1905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fTop + fRadii[kUpperLeft_Corner].fY)); 1915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY < 0); 1925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x < fRect.fLeft + fRadii[kLowerLeft_Corner].fX && 1935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y > fRect.fBottom - fRadii[kLowerLeft_Corner].fY) { 1945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // LL corner 1955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kLowerLeft_Corner; 1965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fLeft + fRadii[kLowerLeft_Corner].fX), 1975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fBottom - fRadii[kLowerLeft_Corner].fY)); 1985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY > 0); 1995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x > fRect.fRight - fRadii[kUpperRight_Corner].fX && 2005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y < fRect.fTop + fRadii[kUpperRight_Corner].fY) { 2015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // UR corner 2025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperRight_Corner; 2035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fRight - fRadii[kUpperRight_Corner].fX), 2045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fTop + fRadii[kUpperRight_Corner].fY)); 2055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY < 0); 2065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x > fRect.fRight - fRadii[kLowerRight_Corner].fX && 2075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y > fRect.fBottom - fRadii[kLowerRight_Corner].fY) { 2085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // LR corner 2095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kLowerRight_Corner; 2105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fRight - fRadii[kLowerRight_Corner].fX), 2115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fBottom - fRadii[kLowerRight_Corner].fY)); 2125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY > 0); 2135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 2145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // not in any of the corners 2155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return true; 2165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // A point is in an ellipse (in standard position) if: 2205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // x^2 y^2 2215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // ----- + ----- <= 1 2225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // a^2 b^2 22332c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // or : 22432c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // b^2*x^2 + a^2*y^2 <= (ab)^2 22532c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com SkScalar dist = SkScalarMul(SkScalarSquare(canonicalPt.fX), SkScalarSquare(fRadii[index].fY)) + 22632c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com SkScalarMul(SkScalarSquare(canonicalPt.fY), SkScalarSquare(fRadii[index].fX)); 22732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com return dist <= SkScalarSquare(SkScalarMul(fRadii[index].fX, fRadii[index].fY)); 22832c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com} 22932c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com 230821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.orgbool SkRRect::allCornersCircular() const { 231821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org return fRadii[0].fX == fRadii[0].fY && 232821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org fRadii[1].fX == fRadii[1].fY && 233821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org fRadii[2].fX == fRadii[2].fY && 234821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org fRadii[3].fX == fRadii[3].fY; 235821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org} 236821397018fdabea6b434ecb96f84fb5449c4025fcommit-bot@chromium.org 23732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.combool SkRRect::contains(const SkRect& rect) const { 23832c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com if (!this->getBounds().contains(rect)) { 23932c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // If 'rect' isn't contained by the RR's bounds then the 24032c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // RR definitely doesn't contain it 24132c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com return false; 24232c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com } 24332c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com 24432c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com if (this->isRect()) { 24532c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // the prior test was sufficient 24632c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com return true; 24732c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com } 24832c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com 24932c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // At this point we know all four corners of 'rect' are inside the 25032c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // bounds of of this RR. Check to make sure all the corners are inside 25132c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com // all the curves 25232c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com return this->checkCornerContainment(rect.fLeft, rect.fTop) && 25332c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com this->checkCornerContainment(rect.fRight, rect.fTop) && 25432c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com this->checkCornerContainment(rect.fRight, rect.fBottom) && 25532c1b66a2c4f26935ba59f3afe3e81600fade78drobertphillips@google.com this->checkCornerContainment(rect.fLeft, rect.fBottom); 2565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 2575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 258f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.orgstatic bool radii_are_nine_patch(const SkVector radii[4]) { 259f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org return radii[SkRRect::kUpperLeft_Corner].fX == radii[SkRRect::kLowerLeft_Corner].fX && 260f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org radii[SkRRect::kUpperLeft_Corner].fY == radii[SkRRect::kUpperRight_Corner].fY && 261f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org radii[SkRRect::kUpperRight_Corner].fX == radii[SkRRect::kLowerRight_Corner].fX && 262f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org radii[SkRRect::kLowerLeft_Corner].fY == radii[SkRRect::kLowerRight_Corner].fY; 263f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org} 264f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org 2655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// There is a simplified version of this method in setRectXY 2665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::computeType() const { 2675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 2685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRect.isEmpty()) { 2705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kEmpty_Type; 2715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 2725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiEqual = true; // are all x radii equal and all y radii? 2755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = 0 == fRadii[0].fX || 0 == fRadii[0].fY; 2765985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 1; i < 4; ++i) { 2785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { 2795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // if either radius is zero the corner is square so both have to 2805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // be non-zero to have a rounded corner 2815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 2825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { 2845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiEqual = false; 2855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allCornersSquare) { 2895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kRect_Type; 2905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 2915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allRadiiEqual) { 2945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[0].fX >= SkScalarHalf(fRect.width()) && 2955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[0].fY >= SkScalarHalf(fRect.height())) { 2965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kOval_Type; 2975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 2985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kSimple_Type; 2995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 3005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 3015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 3025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 303f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org if (radii_are_nine_patch(fRadii)) { 304f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kNinePatch_Type; 305f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } else { 306f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org fType = kComplex_Type; 307f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org } 3085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 3095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 31020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.comstatic bool matrix_only_scale_and_translate(const SkMatrix& matrix) { 31120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com const SkMatrix::TypeMask m = (SkMatrix::TypeMask) (SkMatrix::kAffine_Mask 31220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com | SkMatrix::kPerspective_Mask); 31320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return (matrix.getType() & m) == 0; 31420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com} 31520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 31620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.combool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const { 31720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (NULL == dst) { 31820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return false; 31920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 32020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 32120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Assert that the caller is not trying to do this in place, which 32220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // would violate const-ness. Do not return false though, so that 32320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // if they know what they're doing and want to violate it they can. 32420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkASSERT(dst != this); 32520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 32620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (matrix.isIdentity()) { 32720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com *dst = *this; 32820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return true; 32920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 33020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 33120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // If transform supported 90 degree rotations (which it could), we could 33220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // use SkMatrix::rectStaysRect() to check for a valid transformation. 33320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (!matrix_only_scale_and_translate(matrix)) { 33420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return false; 33520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 33620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 33720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkRect newRect; 33820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (!matrix.mapRect(&newRect, fRect)) { 33920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return false; 34020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 34120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 34220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // At this point, this is guaranteed to succeed, so we can modify dst. 34320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com dst->fRect = newRect; 34420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 34520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Now scale each corner 34620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkScalar xScale = matrix.getScaleX(); 34720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com const bool flipX = xScale < 0; 34820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (flipX) { 34920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com xScale = -xScale; 35020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 35120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkScalar yScale = matrix.getScaleY(); 35220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com const bool flipY = yScale < 0; 35320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (flipY) { 35420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com yScale = -yScale; 35520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 35620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 35720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Scale the radii without respecting the flip. 35820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com for (int i = 0; i < 4; ++i) { 35920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com dst->fRadii[i].fX = SkScalarMul(fRadii[i].fX, xScale); 36020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com dst->fRadii[i].fY = SkScalarMul(fRadii[i].fY, yScale); 36120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 36220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 36320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Now swap as necessary. 36420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (flipX) { 36520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com if (flipY) { 36620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Swap with opposite corners 36720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kUpperLeft_Corner], dst->fRadii[kLowerRight_Corner]); 36820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kLowerLeft_Corner]); 36920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } else { 37020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Only swap in x 37120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kUpperLeft_Corner]); 37220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kLowerRight_Corner], dst->fRadii[kLowerLeft_Corner]); 37320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 37420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } else if (flipY) { 37520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Only swap in y 37620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kUpperLeft_Corner], dst->fRadii[kLowerLeft_Corner]); 37720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkTSwap(dst->fRadii[kUpperRight_Corner], dst->fRadii[kLowerRight_Corner]); 37820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com } 37920e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 38020e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // Since the only transforms that were allowed are scale and translate, the type 38120e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com // remains unchanged. 38220e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com dst->fType = fType; 38320e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 38420e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com SkDEBUGCODE(dst->validate();) 38520e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 38620e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com return true; 38720e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com} 38820e3cd2c9fbc049eae8bcedc591c2cc8d4bed656scroggo@google.com 3894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com/////////////////////////////////////////////////////////////////////////////// 39037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 391bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.orgvoid SkRRect::inset(SkScalar dx, SkScalar dy, SkRRect* dst) const { 39237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkRect r = fRect; 3931a60dab449ee8ab3b4c4330a18fae57b5980363eskia.committer@gmail.com 39437071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org r.inset(dx, dy); 39537071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org if (r.isEmpty()) { 39637071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org dst->setEmpty(); 39737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org return; 39837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 39937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 40037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkVector radii[4]; 401bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org memcpy(radii, fRadii, sizeof(radii)); 40237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org for (int i = 0; i < 4; ++i) { 403bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org if (radii[i].fX) { 404bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org radii[i].fX -= dx; 405bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org } 406bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org if (radii[i].fY) { 407bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org radii[i].fY -= dy; 408bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org } 40937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 41037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org dst->setRectRadii(r, radii); 41137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org} 412bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org 41337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 41437071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 4154faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRRect::writeToMemory(void* buffer) const { 4164ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkASSERT(kSizeInMemory == sizeof(SkRect) + sizeof(fRadii)); 4174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 4184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy(buffer, &fRect, sizeof(SkRect)); 4194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy((char*)buffer + sizeof(SkRect), fRadii, sizeof(fRadii)); 4204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return kSizeInMemory; 4214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 4224ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 4234faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRRect::readFromMemory(const void* buffer, size_t length) { 4244faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org if (length < kSizeInMemory) { 4254faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org return 0; 4264faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org } 4274faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org 4284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkScalar storage[12]; 4294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkASSERT(sizeof(storage) == kSizeInMemory); 4304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 4314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // we make a local copy, to ensure alignment before we cast 4324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy(storage, buffer, kSizeInMemory); 4334ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 4344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->setRectRadii(*(const SkRect*)&storage[0], 4354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com (const SkVector*)&storage[4]); 4364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return kSizeInMemory; 4374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 4384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 439b6b02526438d6839481fb40ccf610d28f7652397bsalomon#ifdef SK_DEVELOPER 440b6b02526438d6839481fb40ccf610d28f7652397bsalomonvoid SkRRect::dump() const { 441b6b02526438d6839481fb40ccf610d28f7652397bsalomon SkDebugf("Rect: "); 442b6b02526438d6839481fb40ccf610d28f7652397bsalomon fRect.dump(); 443b6b02526438d6839481fb40ccf610d28f7652397bsalomon SkDebugf(" Corners: { TL: (%f, %f), TR: (%f, %f), BR: (%f, %f), BL: (%f, %f) }", 444b6b02526438d6839481fb40ccf610d28f7652397bsalomon fRadii[kUpperLeft_Corner].fX, fRadii[kUpperLeft_Corner].fY, 445b6b02526438d6839481fb40ccf610d28f7652397bsalomon fRadii[kUpperRight_Corner].fX, fRadii[kUpperRight_Corner].fY, 446b6b02526438d6839481fb40ccf610d28f7652397bsalomon fRadii[kLowerRight_Corner].fX, fRadii[kLowerRight_Corner].fY, 447b6b02526438d6839481fb40ccf610d28f7652397bsalomon fRadii[kLowerLeft_Corner].fX, fRadii[kLowerLeft_Corner].fY); 448b6b02526438d6839481fb40ccf610d28f7652397bsalomon} 449b6b02526438d6839481fb40ccf610d28f7652397bsalomon#endif 450b6b02526438d6839481fb40ccf610d28f7652397bsalomon 4514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com/////////////////////////////////////////////////////////////////////////////// 4524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 4535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#ifdef SK_DEBUG 4545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::validate() const { 4555985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY); 4565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY); 4575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiSame = true; 4585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 4595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 1; i < 4; ++i) { 4605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX || 0 != fRadii[i].fY) { 4615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiZero = false; 4625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 4635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 4645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { 4655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiSame = false; 4665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 4675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 4685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { 4695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 4705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 4715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 472f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org bool patchesOfNine = radii_are_nine_patch(fRadii); 4735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 4745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com switch (fType) { 4755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kEmpty_Type: 4765985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(fRect.isEmpty()); 4775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); 4785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 4795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kRect_Type: 4805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 4815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); 4825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 4835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kOval_Type: 4845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 4855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); 4865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 4875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 4885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.width()))); 4895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.height()))); 4905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 4915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 4925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kSimple_Type: 4935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 4945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); 4955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 496f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org case kNinePatch_Type: 497f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkASSERT(!fRect.isEmpty()); 498f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); 499f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkASSERT(patchesOfNine); 500f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org break; 5015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kComplex_Type: 5025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 5035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); 504f338d7c860bf0bca82cac793069522311a3dbb1acommit-bot@chromium.org SkASSERT(!patchesOfNine); 5055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 5065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kUnknown_Type: 5075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // no limits on this 5085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 5095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 5105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 5115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#endif // SK_DEBUG 5125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 5135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 514