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/core/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