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
580bb18bb264b26afca45452910437c09445e23a3creed@google.combool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((pts && count > 0) || count == 0);
60fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
610bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite = true;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count <= 0) {
644516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com        sk_bzero(this, sizeof(SkRect));
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar    l, t, r, b;
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        l = r = pts[0].fX;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        t = b = pts[0].fY;
7030d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com
7130d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        // If all of the points are finite, accum should stay 0. If we encounter
7230d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        // a NaN or infinity, then accum should become NaN.
738f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        float accum = 0;
748f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        accum *= l; accum *= t;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int i = 1; i < count; i++) {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkScalar x = pts[i].fX;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkScalar y = pts[i].fY;
7930d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com
808f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            accum *= x; accum *= y;
818f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com
828f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            // we use if instead of if/else, so we can generate min/max
838f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            // float instructions (at least on SSE)
848f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            if (x < l) l = x;
858f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            if (x > r) r = x;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            if (y < t) t = y;
888f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com            if (y > b) b = y;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
90fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
9130d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        SkASSERT(!accum || !SkScalarIsFinite(accum));
9230d90ebe7c05b7067f5c67bd8278371c2a355b02reed@google.com        if (accum) {
93fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com            l = t = r = b = 0;
940bb18bb264b26afca45452910437c09445e23a3creed@google.com            isFinite = false;
95fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        }
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(l, t, r, b);
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
990bb18bb264b26afca45452910437c09445e23a3creed@google.com    return isFinite;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.combool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right,
10391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com                       SkScalar bottom) {
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (left < right && top < bottom && !this->isEmpty() && // check for empties
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft < right && left < fRight && fTop < bottom && top < fBottom)
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fLeft < left) fLeft = left;
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fTop < top) fTop = top;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fRight > right) fRight = right;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fBottom > bottom) fBottom = bottom;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11691a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.combool SkRect::intersect(const SkRect& r) {
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
120ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.orgbool SkRect::intersect2(const SkRect& r) {
121ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    SkScalar L = SkMaxScalar(fLeft, r.fLeft);
122ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    SkScalar R = SkMinScalar(fRight, r.fRight);
123ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    if (L >= R) {
124ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org        return false;
125ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    }
126ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    SkScalar T = SkMaxScalar(fTop, r.fTop);
127ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    SkScalar B = SkMinScalar(fBottom, r.fBottom);
128ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    if (T >= B) {
129ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org        return false;
130ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    }
131ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    this->set(L, T, R, B);
132ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org    return true;
133ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org}
134ae8f9528fd0052e06653272abb44a1f49a3b726bmike@reedtribe.org
135f0f617a502ae9298056654811542c62769a906c8reed@google.combool SkRect::intersect(const SkRect& a, const SkRect& b) {
136f0f617a502ae9298056654811542c62769a906c8reed@google.com
137f0f617a502ae9298056654811542c62769a906c8reed@google.com    if (!a.isEmpty() && !b.isEmpty() &&
138f0f617a502ae9298056654811542c62769a906c8reed@google.com        a.fLeft < b.fRight && b.fLeft < a.fRight &&
139f0f617a502ae9298056654811542c62769a906c8reed@google.com        a.fTop < b.fBottom && b.fTop < a.fBottom) {
140f0f617a502ae9298056654811542c62769a906c8reed@google.com        fLeft   = SkMaxScalar(a.fLeft,   b.fLeft);
141f0f617a502ae9298056654811542c62769a906c8reed@google.com        fTop    = SkMaxScalar(a.fTop,    b.fTop);
142f0f617a502ae9298056654811542c62769a906c8reed@google.com        fRight  = SkMinScalar(a.fRight,  b.fRight);
143f0f617a502ae9298056654811542c62769a906c8reed@google.com        fBottom = SkMinScalar(a.fBottom, b.fBottom);
144f0f617a502ae9298056654811542c62769a906c8reed@google.com        return true;
145f0f617a502ae9298056654811542c62769a906c8reed@google.com    }
146f0f617a502ae9298056654811542c62769a906c8reed@google.com    return false;
147f0f617a502ae9298056654811542c62769a906c8reed@google.com}
148f0f617a502ae9298056654811542c62769a906c8reed@google.com
14991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkRect::join(SkScalar left, SkScalar top, SkScalar right,
15091a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com                  SkScalar bottom) {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do nothing if the params are empty
15291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (left >= right || top >= bottom) {
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
15491a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
155077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we are empty, just assign
15791a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft >= fRight || fTop >= fBottom) {
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(left, top, right, bottom);
15991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    } else {
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < fLeft) fLeft = left;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (top < fTop) fTop = top;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (right > fRight) fRight = right;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bottom > fBottom) fBottom = bottom;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
166