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