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
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1191a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom) {
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do nothing if the params are empty
1391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (left >= right || top >= bottom) {
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1591a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we are empty, just assign
1891a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft >= fRight || fTop >= fBottom) {
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(left, top, right, bottom);
2091a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    } else {
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (left < fLeft) fLeft = left;
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (top < fTop) fTop = top;
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (right > fRight) fRight = right;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (bottom > fBottom) fBottom = bottom;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2891a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkIRect::sort() {
2991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft > fRight) {
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<int32_t>(fLeft, fRight);
3191a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
3291a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fTop > fBottom) {
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<int32_t>(fTop, fBottom);
3491a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.comvoid SkRect::toQuad(SkPoint quad[4]) const {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(quad);
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[0].set(fLeft, fTop);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[1].set(fRight, fTop);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[2].set(fRight, fBottom);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    quad[3].set(fLeft, fBottom);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein#include "SkNx.h"
49b25a83bd8802b7c3c5746c319e781f45337fe207reed
50c9adb05b64fa0bfadf9d1a782afcda470da68c9emtkleinstatic inline bool is_finite(const Sk4s& value) {
518fe8fffdfa7464c6f7da773b8660a2043f4998e0mtklein    auto finite = value * Sk4s(0) == Sk4s(0);
52b25a83bd8802b7c3c5746c319e781f45337fe207reed    return finite.allTrue();
53b25a83bd8802b7c3c5746c319e781f45337fe207reed}
54b25a83bd8802b7c3c5746c319e781f45337fe207reed
550bb18bb264b26afca45452910437c09445e23a3creed@google.combool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((pts && count > 0) || count == 0);
57fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
580bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite = true;
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count <= 0) {
614516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com        sk_bzero(this, sizeof(SkRect));
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
63c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein        Sk4s min, max, accum;
64b25a83bd8802b7c3c5746c319e781f45337fe207reed
65b25a83bd8802b7c3c5746c319e781f45337fe207reed        if (count & 1) {
66c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein            min = Sk4s(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
67b25a83bd8802b7c3c5746c319e781f45337fe207reed            pts += 1;
68b25a83bd8802b7c3c5746c319e781f45337fe207reed            count -= 1;
69b25a83bd8802b7c3c5746c319e781f45337fe207reed        } else {
70c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein            min = Sk4s::Load(&pts[0].fX);
71b25a83bd8802b7c3c5746c319e781f45337fe207reed            pts += 2;
72b25a83bd8802b7c3c5746c319e781f45337fe207reed            count -= 2;
73b25a83bd8802b7c3c5746c319e781f45337fe207reed        }
74b25a83bd8802b7c3c5746c319e781f45337fe207reed        accum = max = min;
75c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein        accum *= Sk4s(0);
76b25a83bd8802b7c3c5746c319e781f45337fe207reed
77b25a83bd8802b7c3c5746c319e781f45337fe207reed        count >>= 1;
78b25a83bd8802b7c3c5746c319e781f45337fe207reed        for (int i = 0; i < count; ++i) {
79c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein            Sk4s xy = Sk4s::Load(&pts->fX);
80b25a83bd8802b7c3c5746c319e781f45337fe207reed            accum *= xy;
81c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein            min = Sk4s::Min(min, xy);
82c9adb05b64fa0bfadf9d1a782afcda470da68c9emtklein            max = Sk4s::Max(max, xy);
83b25a83bd8802b7c3c5746c319e781f45337fe207reed            pts += 2;
84b25a83bd8802b7c3c5746c319e781f45337fe207reed        }
85b25a83bd8802b7c3c5746c319e781f45337fe207reed
86b25a83bd8802b7c3c5746c319e781f45337fe207reed        /**
87b25a83bd8802b7c3c5746c319e781f45337fe207reed         *  With some trickery, we may be able to use Min/Max to also propogate non-finites,
88b25a83bd8802b7c3c5746c319e781f45337fe207reed         *  in which case we could eliminate accum entirely, and just check min and max for
89b25a83bd8802b7c3c5746c319e781f45337fe207reed         *  "is_finite".
90b25a83bd8802b7c3c5746c319e781f45337fe207reed         */
91b25a83bd8802b7c3c5746c319e781f45337fe207reed        if (is_finite(accum)) {
92b25a83bd8802b7c3c5746c319e781f45337fe207reed            float minArray[4], maxArray[4];
93b25a83bd8802b7c3c5746c319e781f45337fe207reed            min.store(minArray);
94b25a83bd8802b7c3c5746c319e781f45337fe207reed            max.store(maxArray);
95b25a83bd8802b7c3c5746c319e781f45337fe207reed            this->set(SkTMin(minArray[0], minArray[2]), SkTMin(minArray[1], minArray[3]),
96b25a83bd8802b7c3c5746c319e781f45337fe207reed                      SkTMax(maxArray[0], maxArray[2]), SkTMax(maxArray[1], maxArray[3]));
97b25a83bd8802b7c3c5746c319e781f45337fe207reed        } else {
98b25a83bd8802b7c3c5746c319e781f45337fe207reed            // we hit a non-finite value, so zero everything and return false
99b25a83bd8802b7c3c5746c319e781f45337fe207reed            this->setEmpty();
100b25a83bd8802b7c3c5746c319e781f45337fe207reed            isFinite = false;
101b25a83bd8802b7c3c5746c319e781f45337fe207reed        }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1030bb18bb264b26afca45452910437c09445e23a3creed@google.com    return isFinite;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1061119c870651ccd34c0acb8fb2cdfad2c07d3116creed#define CHECK_INTERSECT(al, at, ar, ab, bl, bt, br, bb) \
1071119c870651ccd34c0acb8fb2cdfad2c07d3116creed    SkScalar L = SkMaxScalar(al, bl);                   \
1081119c870651ccd34c0acb8fb2cdfad2c07d3116creed    SkScalar R = SkMinScalar(ar, br);                   \
1091119c870651ccd34c0acb8fb2cdfad2c07d3116creed    SkScalar T = SkMaxScalar(at, bt);                   \
1101119c870651ccd34c0acb8fb2cdfad2c07d3116creed    SkScalar B = SkMinScalar(ab, bb);                   \
1111119c870651ccd34c0acb8fb2cdfad2c07d3116creed    do { if (L >= R || T >= B) return false; } while (0)
1121119c870651ccd34c0acb8fb2cdfad2c07d3116creed
1131119c870651ccd34c0acb8fb2cdfad2c07d3116creedbool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
1141119c870651ccd34c0acb8fb2cdfad2c07d3116creed    CHECK_INTERSECT(left, top, right, bottom, fLeft, fTop, fRight, fBottom);
1151119c870651ccd34c0acb8fb2cdfad2c07d3116creed    this->setLTRB(L, T, R, B);
1161119c870651ccd34c0acb8fb2cdfad2c07d3116creed    return true;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11991a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.combool SkRect::intersect(const SkRect& r) {
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
123f0f617a502ae9298056654811542c62769a906c8reed@google.combool SkRect::intersect(const SkRect& a, const SkRect& b) {
1241119c870651ccd34c0acb8fb2cdfad2c07d3116creed    CHECK_INTERSECT(a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom);
1251119c870651ccd34c0acb8fb2cdfad2c07d3116creed    this->setLTRB(L, T, R, B);
1261119c870651ccd34c0acb8fb2cdfad2c07d3116creed    return true;
127f0f617a502ae9298056654811542c62769a906c8reed@google.com}
128f0f617a502ae9298056654811542c62769a906c8reed@google.com
129d9c42f71c391baa23c5ed5934444077e96a68638reedvoid SkRect::join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // do nothing if the params are empty
13191a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (left >= right || top >= bottom) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
13391a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    }
134077910e20cda41d7981084fbd047a108894bc8dfreed@google.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we are empty, just assign
13691a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    if (fLeft >= fRight || fTop >= fBottom) {
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->set(left, top, right, bottom);
13891a2ae988e46b8db3f1cc691d09d77f8c5d84d2creed@google.com    } else {
139d9c42f71c391baa23c5ed5934444077e96a68638reed        fLeft   = SkMinScalar(fLeft, left);
140d9c42f71c391baa23c5ed5934444077e96a68638reed        fTop    = SkMinScalar(fTop, top);
141d9c42f71c391baa23c5ed5934444077e96a68638reed        fRight  = SkMaxScalar(fRight, right);
142d9c42f71c391baa23c5ed5934444077e96a68638reed        fBottom = SkMaxScalar(fBottom, bottom);
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1451119c870651ccd34c0acb8fb2cdfad2c07d3116creed
146e05fed0d6339c63c8cceff74af0b8d120c07e54creed////////////////////////////////////////////////////////////////////////////////////////////////
147e05fed0d6339c63c8cceff74af0b8d120c07e54creed
148e05fed0d6339c63c8cceff74af0b8d120c07e54creed#include "SkString.h"
149e05fed0d6339c63c8cceff74af0b8d120c07e54creed#include "SkStringUtils.h"
150e05fed0d6339c63c8cceff74af0b8d120c07e54creed
151e05fed0d6339c63c8cceff74af0b8d120c07e54creedstatic const char* set_scalar(SkString* storage, SkScalar value, SkScalarAsStringType asType) {
152e05fed0d6339c63c8cceff74af0b8d120c07e54creed    storage->reset();
153e05fed0d6339c63c8cceff74af0b8d120c07e54creed    SkAppendScalar(storage, value, asType);
154e05fed0d6339c63c8cceff74af0b8d120c07e54creed    return storage->c_str();
155e05fed0d6339c63c8cceff74af0b8d120c07e54creed}
156e05fed0d6339c63c8cceff74af0b8d120c07e54creed
157e05fed0d6339c63c8cceff74af0b8d120c07e54creedvoid SkRect::dump(bool asHex) const {
158e05fed0d6339c63c8cceff74af0b8d120c07e54creed    SkScalarAsStringType asType = asHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType;
159e05fed0d6339c63c8cceff74af0b8d120c07e54creed
160e05fed0d6339c63c8cceff74af0b8d120c07e54creed    SkString line;
161e05fed0d6339c63c8cceff74af0b8d120c07e54creed    if (asHex) {
162e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkString tmp;
163e05fed0d6339c63c8cceff74af0b8d120c07e54creed        line.printf( "SkRect::MakeLTRB(%s, /* %f */\n", set_scalar(&tmp, fLeft, asType), fLeft);
164e05fed0d6339c63c8cceff74af0b8d120c07e54creed        line.appendf("                 %s, /* %f */\n", set_scalar(&tmp, fTop, asType), fTop);
165e05fed0d6339c63c8cceff74af0b8d120c07e54creed        line.appendf("                 %s, /* %f */\n", set_scalar(&tmp, fRight, asType), fRight);
166e05fed0d6339c63c8cceff74af0b8d120c07e54creed        line.appendf("                 %s  /* %f */);", set_scalar(&tmp, fBottom, asType), fBottom);
167e05fed0d6339c63c8cceff74af0b8d120c07e54creed    } else {
168e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkString strL, strT, strR, strB;
169e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkAppendScalarDec(&strL, fLeft);
170e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkAppendScalarDec(&strT, fTop);
171e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkAppendScalarDec(&strR, fRight);
172e05fed0d6339c63c8cceff74af0b8d120c07e54creed        SkAppendScalarDec(&strB, fBottom);
173e05fed0d6339c63c8cceff74af0b8d120c07e54creed        line.printf("SkRect::MakeLTRB(%s, %s, %s, %s);",
174e05fed0d6339c63c8cceff74af0b8d120c07e54creed                    strL.c_str(), strT.c_str(), strR.c_str(), strB.c_str());
175e05fed0d6339c63c8cceff74af0b8d120c07e54creed    }
176e05fed0d6339c63c8cceff74af0b8d120c07e54creed    SkDebugf("%s\n", line.c_str());
177e05fed0d6339c63c8cceff74af0b8d120c07e54creed}
178