Пример #1
0
void SkRRect::scaleRadii() {

    // Proportionally scale down all radii to fit. Find the minimum ratio
    // of a side and the radii on that side (for all four sides) and use
    // that to scale down _all_ the radii. This algorithm is from the
    // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping
    // Curves:
    // "Let f = min(Li/Si), where i is one of { top, right, bottom, left },
    //   Si is the sum of the two corresponding radii of the corners on side i,
    //   and Ltop = Lbottom = the width of the box,
    //   and Lleft = Lright = the height of the box.
    // If f < 1, then all corner radii are reduced by multiplying them by f."
    double scale = 1.0;

    // The sides of the rectangle may be larger than a float.
    double width = (double)fRect.fRight - (double)fRect.fLeft;
    double height = (double)fRect.fBottom - (double)fRect.fTop;
    scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, width,  scale);
    scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, height, scale);
    scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, width,  scale);
    scale = compute_min_scale(fRadii[3].fY, fRadii[0].fY, height, scale);

    if (scale < 1.0) {
        SkScaleToSides::AdjustRadii(width,  scale, &fRadii[0].fX, &fRadii[1].fX);
        SkScaleToSides::AdjustRadii(height, scale, &fRadii[1].fY, &fRadii[2].fY);
        SkScaleToSides::AdjustRadii(width,  scale, &fRadii[2].fX, &fRadii[3].fX);
        SkScaleToSides::AdjustRadii(height, scale, &fRadii[3].fY, &fRadii[0].fY);
    }

    // At this point we're either oval, simple, or complex (not empty or rect).
    this->computeType();

    SkDEBUGCODE(this->validate();)
}
Пример #2
0
void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) {
    fRect = rect;
    fRect.sort();

    if (fRect.isEmpty() || !fRect.isFinite()) {
        this->setEmpty();
        return;
    }

    if (!SkScalarsAreFinite(&radii[0].fX, 8)) {
        this->setRect(rect);    // devolve into a simple rect
        return;
    }

    memcpy(fRadii, radii, sizeof(fRadii));

    bool allCornersSquare = true;

    // Clamp negative radii to zero
    for (int i = 0; i < 4; ++i) {
        if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) {
            // In this case we are being a little fast & loose. Since one of
            // the radii is 0 the corner is square. However, the other radii
            // could still be non-zero and play in the global scale factor
            // computation.
            fRadii[i].fX = 0;
            fRadii[i].fY = 0;
        } else {
            allCornersSquare = false;
        }
    }

    if (allCornersSquare) {
        this->setRect(rect);
        return;
    }

    // Proportionally scale down all radii to fit. Find the minimum ratio
    // of a side and the radii on that side (for all four sides) and use
    // that to scale down _all_ the radii. This algorithm is from the
    // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping
    // Curves:
    // "Let f = min(Li/Si), where i is one of { top, right, bottom, left },
    //   Si is the sum of the two corresponding radii of the corners on side i,
    //   and Ltop = Lbottom = the width of the box,
    //   and Lleft = Lright = the height of the box.
    // If f < 1, then all corner radii are reduced by multiplying them by f."
    double scale = 1.0;

    scale = compute_min_scale(fRadii[0].fX, fRadii[1].fX, fRect.width(),  scale);
    scale = compute_min_scale(fRadii[1].fY, fRadii[2].fY, fRect.height(), scale);
    scale = compute_min_scale(fRadii[2].fX, fRadii[3].fX, fRect.width(),  scale);
    scale = compute_min_scale(fRadii[3].fY, fRadii[0].fY, fRect.height(), scale);

    if (scale < 1.0) {
        for (int i = 0; i < 4; ++i) {
            fRadii[i].fX *= scale;
            fRadii[i].fY *= scale;
        }
    }

    // skbug.com/3239 -- its possible that we can hit the following inconsistency:
    //     rad == bounds.bottom - bounds.top
    //     bounds.bottom - radius < bounds.top
    //     YIKES
    // We need to detect and "fix" this now, otherwise we can have the following wackiness:
    //     path.addRRect(rrect);
    //     rrect.rect() != path.getBounds()
    for (int i = 0; i < 4; ++i) {
        fRadii[i].fX = clamp_radius_check_predicates(fRadii[i].fX, fRect.fLeft, fRect.fRight);
        fRadii[i].fY = clamp_radius_check_predicates(fRadii[i].fY, fRect.fTop, fRect.fBottom);
    }
    // At this point we're either oval, simple, or complex (not empty or rect).
    this->computeType();

    SkDEBUGCODE(this->validate();)
}