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