xref: /third_party/skia/src/core/SkRectPriv.h (revision cb93a386)
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
14class SkRectPriv {
15public:
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.
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
25    static SkIRect MakeILargestInverted() {
26        return { SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32 };
27    }
28
29    static SkRect MakeLargeS32() {
30        SkRect r;
31        r.set(MakeILarge());
32        return r;
33    }
34
35    static SkRect MakeLargest() {
36        return { SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax };
37    }
38
39    static constexpr SkRect MakeLargestInverted() {
40        return { SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin };
41    }
42
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
52    static bool FitsInFixed(const SkRect& r) {
53        return SkFitsInFixed(r.fLeft) && SkFitsInFixed(r.fTop) &&
54               SkFitsInFixed(r.fRight) && SkFitsInFixed(r.fBottom);
55    }
56
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.
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.
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.
79    static SkRect Subtract(const SkRect& a, const SkRect& b) {
80        SkRect diff;
81        Subtract(a, b, &diff);
82        return diff;
83    }
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