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    SkASSERT(&r);
118    return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
119}
120
121bool SkRect::intersect2(const SkRect& r) {
122    SkASSERT(&r);
123    SkScalar L = SkMaxScalar(fLeft, r.fLeft);
124    SkScalar R = SkMinScalar(fRight, r.fRight);
125    if (L >= R) {
126        return false;
127    }
128    SkScalar T = SkMaxScalar(fTop, r.fTop);
129    SkScalar B = SkMinScalar(fBottom, r.fBottom);
130    if (T >= B) {
131        return false;
132    }
133    this->set(L, T, R, B);
134    return true;
135}
136
137bool SkRect::intersect(const SkRect& a, const SkRect& b) {
138    SkASSERT(&a && &b);
139
140    if (!a.isEmpty() && !b.isEmpty() &&
141        a.fLeft < b.fRight && b.fLeft < a.fRight &&
142        a.fTop < b.fBottom && b.fTop < a.fBottom) {
143        fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
144        fTop    = SkMaxScalar(a.fTop,    b.fTop);
145        fRight  = SkMinScalar(a.fRight,  b.fRight);
146        fBottom = SkMinScalar(a.fBottom, b.fBottom);
147        return true;
148    }
149    return false;
150}
151
152void SkRect::join(SkScalar left, SkScalar top, SkScalar right,
153                  SkScalar bottom) {
154    // do nothing if the params are empty
155    if (left >= right || top >= bottom) {
156        return;
157    }
158
159    // if we are empty, just assign
160    if (fLeft >= fRight || fTop >= fBottom) {
161        this->set(left, top, right, bottom);
162    } else {
163        if (left < fLeft) fLeft = left;
164        if (top < fTop) fTop = top;
165        if (right > fRight) fRight = right;
166        if (bottom > fBottom) fBottom = bottom;
167    }
168}
169