SkRRect.cpp revision 5b33211c5edafde82af781beaa1dbc295000a62f
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" 95985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) { 135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.isEmpty()) { 145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setEmpty(); 155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (xRad <= 0 || yRad <= 0) { 195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // all corners are square in this case 205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setRect(rect); 215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) { 255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad), 265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), yRad + yRad)); 275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(scale < SK_Scalar1); 285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com xRad = SkScalarMul(xRad, scale); 295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com yRad = SkScalarMul(yRad, scale); 305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRect = rect; 335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].set(xRad, yRad); 355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kSimple_Type; 375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height())) { 385985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kOval_Type; 395b33211c5edafde82af781beaa1dbc295000a62frobertphillips@google.com // TODO: assert that all the x&y radii are already W/2 & H/2 405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 445985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 455985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { 465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (rect.isEmpty()) { 475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setEmpty(); 485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 505985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 515985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRect = rect; 525985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com memcpy(fRadii, radii, sizeof(fRadii)); 535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = true; 555985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Clamp negative radii to zero 575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) { 595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // In this case we are being a little fast & loose. Since one of 605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // the radii is 0 the corner is square. However, the other radii 615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // could still be non-zero and play in the global scale factor 625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // computation. 635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fX = 0; 645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fY = 0; 655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allCornersSquare) { 715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com this->setRect(rect); 725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Proportionally scale down all radii to fit. Find the minimum ratio 76c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // of a side and the radii on that side (for all four sides) and use 775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // that to scale down _all_ the radii. This algorithm is from the 785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping 795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Curves: 80c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // "Let f = min(Li/Si), where i is one of { top, right, bottom, left }, 815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // Si is the sum of the two corresponding radii of the corners on side i, 82c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // and Ltop = Lbottom = the width of the box, 83c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com // and Lleft = Lright = the height of the box. 845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // If f < 1, then all corner radii are reduced by multiplying them by f." 855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalar scale = SK_Scalar1; 865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[0].fX + fRadii[1].fX > rect.width()) { 885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].fX)); 905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[1].fY + fRadii[2].fY > rect.height()) { 925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].fY)); 945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[2].fX + fRadii[3].fX > rect.width()) { 965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].fX)); 985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[3].fY + fRadii[0].fY > rect.height()) { 1005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com scale = SkMinScalar(scale, 1015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].fY)); 1025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (scale < SK_Scalar1) { 1055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 1065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fX = SkScalarMul(fRadii[i].fX, scale); 1075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[i].fY = SkScalarMul(fRadii[i].fY, scale); 1085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // At this point we're either oval, simple, or complex (not empty or rect) 1125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // but we lazily resolve the type to avoid the work if the information 1135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // isn't required. 1145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = (SkRRect::Type) kUnknown_Type; 1155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 1175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 1185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.combool SkRRect::contains(SkScalar x, SkScalar y) const { 1205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 1215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (kEmpty_Type == this->type()) { 1235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return false; 1245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (!fRect.contains(x, y)) { 1275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return false; 1285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (kRect_Type == this->type()) { 1315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // the 'fRect' test above was sufficient 1325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return true; 1335985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1345985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1355985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // We know the point is inside the RR's bounds. The only way it can 1365985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // be out is if it outside one of the corners 1375985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkPoint canonicalPt; // (x,y) translated to one of the quadrants 1385985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com int index; 1395985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1405985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (kOval_Type == this->type()) { 1415985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - fRect.centerX(), y - fRect.centerY()); 1425985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperLeft_Corner; // any corner will do in this case 1435985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 144c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com if (x < fRect.fLeft + fRadii[kUpperLeft_Corner].fX && 1455985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y < fRect.fTop + fRadii[kUpperLeft_Corner].fY) { 1465985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // UL corner 1475985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperLeft_Corner; 1485985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fLeft + fRadii[kUpperLeft_Corner].fX), 1495985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fTop + fRadii[kUpperLeft_Corner].fY)); 1505985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY < 0); 1515985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x < fRect.fLeft + fRadii[kLowerLeft_Corner].fX && 1525985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y > fRect.fBottom - fRadii[kLowerLeft_Corner].fY) { 1535985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // LL corner 1545985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kLowerLeft_Corner; 1555985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fLeft + fRadii[kLowerLeft_Corner].fX), 1565985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fBottom - fRadii[kLowerLeft_Corner].fY)); 1575985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY > 0); 1585985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x > fRect.fRight - fRadii[kUpperRight_Corner].fX && 1595985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y < fRect.fTop + fRadii[kUpperRight_Corner].fY) { 1605985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // UR corner 1615985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kUpperRight_Corner; 1625985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fRight - fRadii[kUpperRight_Corner].fX), 1635985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fTop + fRadii[kUpperRight_Corner].fY)); 1645985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY < 0); 1655985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else if (x > fRect.fRight - fRadii[kLowerRight_Corner].fX && 1665985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y > fRect.fBottom - fRadii[kLowerRight_Corner].fY) { 1675985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // LR corner 1685985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com index = kLowerRight_Corner; 1695985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com canonicalPt.set(x - (fRect.fRight - fRadii[kLowerRight_Corner].fX), 1705985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com y - (fRect.fBottom - fRadii[kLowerRight_Corner].fY)); 1715985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY > 0); 1725985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 1735985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // not in any of the corners 1745985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return true; 1755985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1765985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // A point is in an ellipse (in standard position) if: 1795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // x^2 y^2 1805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // ----- + ----- <= 1 1815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // a^2 b^2 1825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalar dist = SkScalarDiv(SkScalarSquare(canonicalPt.fX), SkScalarSquare(fRadii[index].fX)) + 1835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkScalarDiv(SkScalarSquare(canonicalPt.fY), SkScalarSquare(fRadii[index].fY)); 1845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return dist <= SK_Scalar1; 1855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 1865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com// There is a simplified version of this method in setRectXY 1885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::computeType() const { 1895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkDEBUGCODE(this->validate();) 1905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRect.isEmpty()) { 1925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kEmpty_Type; 1935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 1945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 1955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiEqual = true; // are all x radii equal and all y radii? 1975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = 0 == fRadii[0].fX || 0 == fRadii[0].fY; 1985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 1995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 1; i < 4; ++i) { 2005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { 2015985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // if either radius is zero the corner is square so both have to 2025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // be non-zero to have a rounded corner 2035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 2045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { 2065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiEqual = false; 2075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allCornersSquare) { 2115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kRect_Type; 2125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 2135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (allRadiiEqual) { 2165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[0].fX >= SkScalarHalf(fRect.width()) && 2175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fRadii[0].fY >= SkScalarHalf(fRect.height())) { 2185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kOval_Type; 2195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } else { 2205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kSimple_Type; 2215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com return; 2235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com fType = kComplex_Type; 2265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 2275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com/////////////////////////////////////////////////////////////////////////////// 22937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 230bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.orgvoid SkRRect::inset(SkScalar dx, SkScalar dy, SkRRect* dst) const { 23137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkRect r = fRect; 2321a60dab449ee8ab3b4c4330a18fae57b5980363eskia.committer@gmail.com 23337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org r.inset(dx, dy); 23437071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org if (r.isEmpty()) { 23537071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org dst->setEmpty(); 23637071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org return; 23737071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 23837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 23937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org SkVector radii[4]; 240bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org memcpy(radii, fRadii, sizeof(radii)); 24137071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org for (int i = 0; i < 4; ++i) { 242bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org if (radii[i].fX) { 243bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org radii[i].fX -= dx; 244bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org } 245bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org if (radii[i].fY) { 246bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org radii[i].fY -= dy; 247bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org } 24837071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org } 24937071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org dst->setRectRadii(r, radii); 25037071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org} 251bcbef579d02e255b9a29b5db2d6804f4bfc76d1cmike@reedtribe.org 25237071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 25337071640f6bdcb1bfb193f85b9ca615b29679425mike@reedtribe.org 2544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comuint32_t SkRRect::writeToMemory(void* buffer) const { 2554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkASSERT(kSizeInMemory == sizeof(SkRect) + sizeof(fRadii)); 2564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2574ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy(buffer, &fRect, sizeof(SkRect)); 2584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy((char*)buffer + sizeof(SkRect), fRadii, sizeof(fRadii)); 2594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return kSizeInMemory; 2604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 2614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2624ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comuint32_t SkRRect::readFromMemory(const void* buffer) { 2634ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkScalar storage[12]; 2644ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com SkASSERT(sizeof(storage) == kSizeInMemory); 2654ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2664ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com // we make a local copy, to ensure alignment before we cast 2674ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com memcpy(storage, buffer, kSizeInMemory); 2684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2694ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com this->setRectRadii(*(const SkRect*)&storage[0], 2704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com (const SkVector*)&storage[4]); 2714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com return kSizeInMemory; 2724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com} 2734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com/////////////////////////////////////////////////////////////////////////////// 2754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com 2765985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#ifdef SK_DEBUG 2775985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.comvoid SkRRect::validate() const { 2785985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY); 2795985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY); 2805985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com bool allRadiiSame = true; 2815985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2825985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 1; i < 4; ++i) { 2835985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX || 0 != fRadii[i].fY) { 2845985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiZero = false; 2855985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2865985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2875985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { 2885985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allRadiiSame = false; 2895985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2905985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2915985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { 2925985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com allCornersSquare = false; 2935985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2945985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 2955985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 2965985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com switch (fType) { 2975985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kEmpty_Type: 2985985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(fRect.isEmpty()); 2995985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); 3005985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 301c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop && 3025985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 0 == fRect.fRight && 0 == fRect.fBottom); 3035985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3045985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kRect_Type: 3055985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 3065985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); 3075985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3085985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kOval_Type: 3095985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 3105985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); 3115985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 3125985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com for (int i = 0; i < 4; ++i) { 3135985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.width()))); 3145985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.height()))); 3155985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 3165985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3175985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kSimple_Type: 3185985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 3195985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); 3205985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3215985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kComplex_Type: 3225985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!fRect.isEmpty()); 3235985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); 3245985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3255985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com case kUnknown_Type: 3265985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com // no limits on this 3275985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com break; 3285985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com } 3295985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com} 3305985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com#endif // SK_DEBUG 3315985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com 3325985e7c4d13b04d6b819bfff3df44f1dd3eb35b8robertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 333