1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkRectPriv_DEFINED 9 #define SkRectPriv_DEFINED 10 11 #include "include/core/SkRect.h" 12 #include "src/base/SkMathPriv.h" 13 14 class SkRectPriv { 15 public: 16 // Returns an irect that is very large, and can be safely round-trip with SkRect and still 17 // be considered non-empty (i.e. width/height > 0) even if we round-out the SkRect. MakeILarge()18 static SkIRect MakeILarge() { 19 // SK_MaxS32 >> 1 seemed better, but it did not survive round-trip with SkRect and rounding. 20 // Also, 1 << 29 can be perfectly represented in float, while SK_MaxS32 >> 1 cannot. 21 const int32_t large = 1 << 29; 22 return { -large, -large, large, large }; 23 } 24 MakeILargestInverted()25 static SkIRect MakeILargestInverted() { 26 return { SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32 }; 27 } 28 MakeLargeS32()29 static SkRect MakeLargeS32() { 30 SkRect r; 31 r.set(MakeILarge()); 32 return r; 33 } 34 MakeLargest()35 static SkRect MakeLargest() { 36 return { SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax }; 37 } 38 MakeLargestInverted()39 static constexpr SkRect MakeLargestInverted() { 40 return { SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin }; 41 } 42 GrowToInclude(SkRect * r,const SkPoint & pt)43 static void GrowToInclude(SkRect* r, const SkPoint& pt) { 44 r->fLeft = std::min(pt.fX, r->fLeft); 45 r->fRight = std::max(pt.fX, r->fRight); 46 r->fTop = std::min(pt.fY, r->fTop); 47 r->fBottom = std::max(pt.fY, r->fBottom); 48 } 49 50 // Conservative check if r can be expressed in fixed-point. 51 // Will return false for very large values that might have fit FitsInFixed(const SkRect & r)52 static bool FitsInFixed(const SkRect& r) { 53 return SkFitsInFixed(r.fLeft) && SkFitsInFixed(r.fTop) && 54 SkFitsInFixed(r.fRight) && SkFitsInFixed(r.fBottom); 55 } 56 Is16Bit(const SkIRect & r)57 static bool Is16Bit(const SkIRect& r) { 58 return SkTFitsIn<int16_t>(r.fLeft) && SkTFitsIn<int16_t>(r.fTop) && 59 SkTFitsIn<int16_t>(r.fRight) && SkTFitsIn<int16_t>(r.fBottom); 60 } 61 62 // Returns r.width()/2 but divides first to avoid width() overflowing. HalfWidth(const SkRect & r)63 static SkScalar HalfWidth(const SkRect& r) { 64 return SkScalarHalf(r.fRight) - SkScalarHalf(r.fLeft); 65 } 66 // Returns r.height()/2 but divides first to avoid height() overflowing. HalfHeight(const SkRect & r)67 static SkScalar HalfHeight(const SkRect& r) { 68 return SkScalarHalf(r.fBottom) - SkScalarHalf(r.fTop); 69 } 70 71 // Evaluate A-B. If the difference shape cannot be represented as a rectangle then false is 72 // returned and 'out' is set to the largest rectangle contained in said shape. If true is 73 // returned then A-B is representable as a rectangle, which is stored in 'out'. 74 static bool Subtract(const SkRect& a, const SkRect& b, SkRect* out); 75 static bool Subtract(const SkIRect& a, const SkIRect& b, SkIRect* out); 76 77 // Evaluate A-B, and return the largest rectangle contained in that shape (since the difference 78 // may not be representable as rectangle). The returned rectangle will not intersect B. Subtract(const SkRect & a,const SkRect & b)79 static SkRect Subtract(const SkRect& a, const SkRect& b) { 80 SkRect diff; 81 Subtract(a, b, &diff); 82 return diff; 83 } Subtract(const SkIRect & a,const SkIRect & b)84 static SkIRect Subtract(const SkIRect& a, const SkIRect& b) { 85 SkIRect diff; 86 Subtract(a, b, &diff); 87 return diff; 88 } 89 }; 90 91 92 #endif 93