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