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