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 #include "src/base/SkVx.h" 14 15 class SkM44; 16 class SkMatrix; 17 18 class SkRectPriv { 19 public: 20 // Returns an irect that is very large, and can be safely round-trip with SkRect and still 21 // be considered non-empty (i.e. width/height > 0) even if we round-out the SkRect. MakeILarge()22 static SkIRect MakeILarge() { 23 // SK_MaxS32 >> 1 seemed better, but it did not survive round-trip with SkRect and rounding. 24 // Also, 1 << 29 can be perfectly represented in float, while SK_MaxS32 >> 1 cannot. 25 const int32_t large = 1 << 29; 26 return { -large, -large, large, large }; 27 } 28 MakeILargestInverted()29 static SkIRect MakeILargestInverted() { 30 return { SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32 }; 31 } 32 MakeLargeS32()33 static SkRect MakeLargeS32() { 34 SkRect r; 35 r.set(MakeILarge()); 36 return r; 37 } 38 MakeLargest()39 static SkRect MakeLargest() { 40 return { SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax }; 41 } 42 MakeLargestInverted()43 static constexpr SkRect MakeLargestInverted() { 44 return { SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin }; 45 } 46 GrowToInclude(SkRect * r,const SkPoint & pt)47 static void GrowToInclude(SkRect* r, const SkPoint& pt) { 48 r->fLeft = std::min(pt.fX, r->fLeft); 49 r->fRight = std::max(pt.fX, r->fRight); 50 r->fTop = std::min(pt.fY, r->fTop); 51 r->fBottom = std::max(pt.fY, r->fBottom); 52 } 53 54 // Conservative check if r can be expressed in fixed-point. 55 // Will return false for very large values that might have fit FitsInFixed(const SkRect & r)56 static bool FitsInFixed(const SkRect& r) { 57 return SkFitsInFixed(r.fLeft) && SkFitsInFixed(r.fTop) && 58 SkFitsInFixed(r.fRight) && SkFitsInFixed(r.fBottom); 59 } 60 61 // Returns r.width()/2 but divides first to avoid width() overflowing. HalfWidth(const SkRect & r)62 static constexpr float HalfWidth(const SkRect& r) { 63 return sk_float_midpoint(-r.fLeft, r.fRight); 64 } 65 // Returns r.height()/2 but divides first to avoid height() overflowing. HalfHeight(const SkRect & r)66 static constexpr float HalfHeight(const SkRect& r) { 67 return sk_float_midpoint(-r.fTop, r.fBottom); 68 } 69 70 // Evaluate A-B. If the difference shape cannot be represented as a rectangle then false is 71 // returned and 'out' is set to the largest rectangle contained in said shape. If true is 72 // returned then A-B is representable as a rectangle, which is stored in 'out'. 73 static bool Subtract(const SkRect& a, const SkRect& b, SkRect* out); 74 static bool Subtract(const SkIRect& a, const SkIRect& b, SkIRect* out); 75 76 // Evaluate A-B, and return the largest rectangle contained in that shape (since the difference 77 // may not be representable as rectangle). The returned rectangle will not intersect B. Subtract(const SkRect & a,const SkRect & b)78 static SkRect Subtract(const SkRect& a, const SkRect& b) { 79 SkRect diff; 80 Subtract(a, b, &diff); 81 return diff; 82 } Subtract(const SkIRect & a,const SkIRect & b)83 static SkIRect Subtract(const SkIRect& a, const SkIRect& b) { 84 SkIRect diff; 85 Subtract(a, b, &diff); 86 return diff; 87 } 88 89 // Returns true if the quadrilateral formed by transforming the four corners of 'a' contains 'b' 90 // 'tol' is in the same coordinate space as 'b', to treat 'b' as 'tol' units inset. 91 static bool QuadContainsRect(const SkMatrix& m, 92 const SkIRect& a, 93 const SkIRect& b, 94 float tol=0.f); 95 static bool QuadContainsRect(const SkM44& m, const SkRect& a, const SkRect& b, float tol=0.f); 96 // Like QuadContainsRect() but returns the edge test masks ordered T, R, B, L. 97 static skvx::int4 QuadContainsRectMask(const SkM44& m, const SkRect& a, const SkRect& b, 98 float tol=0.f); 99 100 // Assuming 'src' does not intersect 'dst', returns the edge or corner of 'src' that is closest 101 // to 'dst', e.g. the pixels that would be sampled from 'src' when clamp-tiled into 'dst'. 102 // 103 // The returned rectangle will not be empty if 'src' is not empty and 'dst' is not empty. 104 // At least one of its width or height will be equal to 1 (possibly both if a corner is closest) 105 // 106 // Returns src.intersect(dst) if they do actually intersect. 107 static SkIRect ClosestDisjointEdge(const SkIRect& src, const SkIRect& dst); 108 }; 109 110 111 #endif 112