1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkRect.h"
11
12void SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
13    // do nothing if the params are empty
14    if (left >= right || top >= bottom) {
15        return;
16    }
17
18    // if we are empty, just assign
19    if (fLeft >= fRight || fTop >= fBottom) {
20        this->set(left, top, right, bottom);
21    } else {
22        if (left < fLeft) fLeft = left;
23        if (top < fTop) fTop = top;
24        if (right > fRight) fRight = right;
25        if (bottom > fBottom) fBottom = bottom;
26    }
27}
28
29void SkIRect::sort() {
30    if (fLeft > fRight) {
31        SkTSwap<int32_t>(fLeft, fRight);
32    }
33    if (fTop > fBottom) {
34        SkTSwap<int32_t>(fTop, fBottom);
35    }
36}
37
38/////////////////////////////////////////////////////////////////////////////
39
40void SkRect::sort() {
41    if (fLeft > fRight) {
42        SkTSwap<SkScalar>(fLeft, fRight);
43    }
44    if (fTop > fBottom) {
45        SkTSwap<SkScalar>(fTop, fBottom);
46    }
47}
48
49void SkRect::toQuad(SkPoint quad[4]) const {
50    SkASSERT(quad);
51
52    quad[0].set(fLeft, fTop);
53    quad[1].set(fRight, fTop);
54    quad[2].set(fRight, fBottom);
55    quad[3].set(fLeft, fBottom);
56}
57
58bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
59    SkASSERT((pts && count > 0) || count == 0);
60
61    bool isFinite = true;
62
63    if (count <= 0) {
64        sk_bzero(this, sizeof(SkRect));
65    } else {
66        SkScalar    l, t, r, b;
67
68        l = r = pts[0].fX;
69        t = b = pts[0].fY;
70
71        // If all of the points are finite, accum should stay 0. If we encounter
72        // a NaN or infinity, then accum should become NaN.
73        float accum = 0;
74        accum *= l; accum *= t;
75
76        for (int i = 1; i < count; i++) {
77            SkScalar x = pts[i].fX;
78            SkScalar y = pts[i].fY;
79
80            accum *= x; accum *= y;
81
82            // we use if instead of if/else, so we can generate min/max
83            // float instructions (at least on SSE)
84            if (x < l) l = x;
85            if (x > r) r = x;
86
87            if (y < t) t = y;
88            if (y > b) b = y;
89        }
90
91        SkASSERT(!accum || !SkScalarIsFinite(accum));
92        if (accum) {
93            l = t = r = b = 0;
94            isFinite = false;
95        }
96        this->set(l, t, r, b);
97    }
98
99    return isFinite;
100}
101
102bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right,
103                       SkScalar bottom) {
104    if (left < right && top < bottom && !this->isEmpty() && // check for empties
105        fLeft < right && left < fRight && fTop < bottom && top < fBottom)
106    {
107        if (fLeft < left) fLeft = left;
108        if (fTop < top) fTop = top;
109        if (fRight > right) fRight = right;
110        if (fBottom > bottom) fBottom = bottom;
111        return true;
112    }
113    return false;
114}
115
116bool SkRect::intersect(const SkRect& r) {
117    return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
118}
119
120bool SkRect::intersect2(const SkRect& r) {
121    SkScalar L = SkMaxScalar(fLeft, r.fLeft);
122    SkScalar R = SkMinScalar(fRight, r.fRight);
123    if (L >= R) {
124        return false;
125    }
126    SkScalar T = SkMaxScalar(fTop, r.fTop);
127    SkScalar B = SkMinScalar(fBottom, r.fBottom);
128    if (T >= B) {
129        return false;
130    }
131    this->set(L, T, R, B);
132    return true;
133}
134
135bool SkRect::intersect(const SkRect& a, const SkRect& b) {
136
137    if (!a.isEmpty() && !b.isEmpty() &&
138        a.fLeft < b.fRight && b.fLeft < a.fRight &&
139        a.fTop < b.fBottom && b.fTop < a.fBottom) {
140        fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
141        fTop    = SkMaxScalar(a.fTop,    b.fTop);
142        fRight  = SkMinScalar(a.fRight,  b.fRight);
143        fBottom = SkMinScalar(a.fBottom, b.fBottom);
144        return true;
145    }
146    return false;
147}
148
149void SkRect::join(SkScalar left, SkScalar top, SkScalar right,
150                  SkScalar bottom) {
151    // do nothing if the params are empty
152    if (left >= right || top >= bottom) {
153        return;
154    }
155
156    // if we are empty, just assign
157    if (fLeft >= fRight || fTop >= fBottom) {
158        this->set(left, top, right, bottom);
159    } else {
160        if (left < fLeft) fLeft = left;
161        if (top < fTop) fTop = top;
162        if (right > fRight) fRight = right;
163        if (bottom > fBottom) fBottom = bottom;
164    }
165}
166