SkRect.cpp revision 0bb18bb264b26afca45452910437c09445e23a3c
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do nothing if the params are empty
1491a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (left >= right || top >= bottom) {
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1691a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we are empty, just assign
1991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft >= fRight || fTop >= fBottom) {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(left, top, right, bottom);
2191a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    } else {
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < fLeft) fLeft = left;
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (top < fTop) fTop = top;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (right > fRight) fRight = right;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bottom > fBottom) fBottom = bottom;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkIRect::sort() {
3091a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft > fRight) {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<int32_t>(fLeft, fRight);
3291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
3391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fTop > fBottom) {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<int32_t>(fTop, fBottom);
3591a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4091a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkRect::sort() {
4191a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft > fRight) {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<SkScalar>(fLeft, fRight);
4391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
4491a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fTop > fBottom) {
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<SkScalar>(fTop, fBottom);
4691a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkRect::toQuad(SkPoint quad[4]) const {
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(quad);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[0].set(fLeft, fTop);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[1].set(fRight, fTop);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[2].set(fRight, fBottom);
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[3].set(fLeft, fBottom);
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com#ifdef SK_SCALAR_IS_FLOAT
59fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    #define SkFLOATCODE(code)   code
60fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com#else
61fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    #define SkFLOATCODE(code)
62fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com#endif
63fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
64921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com// For float compares (at least on x86, by removing the else from the min/max
65921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com// computation, we get MAXSS and MINSS instructions, and no branches.
66921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com// Fixed point has no such opportunity (afaik), so we leave the else in that case
67921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com#ifdef SK_SCALAR_IS_FLOAT
68921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com    #define MINMAX_ELSE
69921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com#else
70921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com    #define MINMAX_ELSE else
71921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com#endif
72921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com
730bb18bb264b26afca45452910437c09445e23a3creed@google.combool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((pts && count > 0) || count == 0);
750bb18bb264b26afca45452910437c09445e23a3creed@google.com
760bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite = true;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count <= 0) {
794516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com        sk_bzero(this, sizeof(SkRect));
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SCALAR_SLOW_COMPARES
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int32_t    l, t, r, b;
83077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        l = r = SkScalarAs2sCompliment(pts[0].fX);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        t = b = SkScalarAs2sCompliment(pts[0].fY);
86077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int i = 1; i < count; i++) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int32_t x = SkScalarAs2sCompliment(pts[i].fX);
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int32_t y = SkScalarAs2sCompliment(pts[i].fY);
90077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (x < l) l = x; else if (x > r) r = x;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (y < t) t = y; else if (y > b) b = y;
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(Sk2sComplimentAsScalar(l),
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                  Sk2sComplimentAsScalar(t),
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                  Sk2sComplimentAsScalar(r),
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                  Sk2sComplimentAsScalar(b));
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar    l, t, r, b;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        l = r = pts[0].fX;
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        t = b = pts[0].fY;
10330d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com
10430d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        // If all of the points are finite, accum should stay 0. If we encounter
10530d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        // a NaN or infinity, then accum should become NaN.
10630d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        SkFLOATCODE(float accum = 0;)
107921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com        SkFLOATCODE(accum *= l; accum *= t;)
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int i = 1; i < count; i++) {
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkScalar x = pts[i].fX;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkScalar y = pts[i].fY;
11230d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com
11330d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com            SkFLOATCODE(accum *= x; accum *= y;)
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
115921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com            if (x < l) l = x; MINMAX_ELSE if (x > r) r = x;
116921374d4cc7ee2bf07be0d778ce4ce7414909534reed@google.com            if (y < t) t = y; MINMAX_ELSE if (y > b) b = y;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
118fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
119fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com#ifdef SK_SCALAR_IS_FLOAT
12030d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        SkASSERT(!accum || !SkScalarIsFinite(accum));
12130d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        if (accum) {
122fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com            l = t = r = b = 0;
1230bb18bb264b26afca45452910437c09445e23a3creed@google.com            isFinite = false;
124fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        }
125fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com#endif
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(l, t, r, b);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1290bb18bb264b26afca45452910437c09445e23a3creed@google.com
1300bb18bb264b26afca45452910437c09445e23a3creed@google.com    return isFinite;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.combool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right,
13491a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com                       SkScalar bottom) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (left < right && top < bottom && !this->isEmpty() && // check for empties
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft < right && left < fRight && fTop < bottom && top < fBottom)
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fLeft < left) fLeft = left;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fTop < top) fTop = top;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fRight > right) fRight = right;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fBottom > bottom) fBottom = bottom;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14791a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.combool SkRect::intersect(const SkRect& r) {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(&r);
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
152f0f617a502ae9298056654811542c62769a906c8reed@google.combool SkRect::intersect(const SkRect& a, const SkRect& b) {
153f0f617a502ae9298056654811542c62769a906c8reed@google.com    SkASSERT(&a && &b);
154f0f617a502ae9298056654811542c62769a906c8reed@google.com
155f0f617a502ae9298056654811542c62769a906c8reed@google.com    if (!a.isEmpty() && !b.isEmpty() &&
156f0f617a502ae9298056654811542c62769a906c8reed@google.com        a.fLeft < b.fRight && b.fLeft < a.fRight &&
157f0f617a502ae9298056654811542c62769a906c8reed@google.com        a.fTop < b.fBottom && b.fTop < a.fBottom) {
158f0f617a502ae9298056654811542c62769a906c8reed@google.com        fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
159f0f617a502ae9298056654811542c62769a906c8reed@google.com        fTop    = SkMaxScalar(a.fTop,    b.fTop);
160f0f617a502ae9298056654811542c62769a906c8reed@google.com        fRight  = SkMinScalar(a.fRight,  b.fRight);
161f0f617a502ae9298056654811542c62769a906c8reed@google.com        fBottom = SkMinScalar(a.fBottom, b.fBottom);
162f0f617a502ae9298056654811542c62769a906c8reed@google.com        return true;
163f0f617a502ae9298056654811542c62769a906c8reed@google.com    }
164f0f617a502ae9298056654811542c62769a906c8reed@google.com    return false;
165f0f617a502ae9298056654811542c62769a906c8reed@google.com}
166f0f617a502ae9298056654811542c62769a906c8reed@google.com
16791a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkRect::join(SkScalar left, SkScalar top, SkScalar right,
16891a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com                  SkScalar bottom) {
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do nothing if the params are empty
17091a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (left >= right || top >= bottom) {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
17291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
173077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we are empty, just assign
17591a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft >= fRight || fTop >= fBottom) {
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(left, top, right, bottom);
17791a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    } else {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < fLeft) fLeft = left;
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (top < fTop) fTop = top;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (right > fRight) fRight = right;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bottom > fBottom) fBottom = bottom;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
185