xref: /aosp_15_r20/external/skia/src/core/SkRectPriv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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