1 | // LAF Gfx Library |
2 | // Copyright (C) 2019-2022 Igara Studio S.A. |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifndef GFX_REGION_SKIA_H_INCLUDED |
8 | #define GFX_REGION_SKIA_H_INCLUDED |
9 | #pragma once |
10 | |
11 | #include "gfx/point.h" |
12 | #include "gfx/rect.h" |
13 | |
14 | #include <vector> |
15 | |
16 | #include "include/core/SkRegion.h" |
17 | |
18 | namespace gfx { |
19 | |
20 | template<typename T> class PointT; |
21 | |
22 | class Region; |
23 | |
24 | namespace details { |
25 | |
26 | using Region = SkRegion; |
27 | |
28 | template<typename T> |
29 | class RegionIterator { |
30 | public: |
31 | using iterator_category = std::forward_iterator_tag; |
32 | using value_type = T; |
33 | using difference_type = std::ptrdiff_t; |
34 | using pointer = T*; |
35 | using reference = T&; |
36 | |
37 | RegionIterator() { } |
38 | RegionIterator(const RegionIterator& o) : m_it(o.m_it) { } |
39 | template<typename T2> |
40 | RegionIterator(const RegionIterator<T2>& o) : m_it(o.m_it) { } |
41 | RegionIterator& operator=(const RegionIterator& o) { m_it = o.m_it; return *this; } |
42 | RegionIterator& operator++() { m_it.next(); return *this; } |
43 | bool operator==(const RegionIterator& o) const { |
44 | return (m_it.done() == o.m_it.done()); |
45 | } |
46 | bool operator!=(const RegionIterator& o) const { |
47 | return (m_it.done() != o.m_it.done()); |
48 | } |
49 | reference operator*() { |
50 | const SkIRect& rc = m_it.rect(); |
51 | m_rect.x = rc.x(); |
52 | m_rect.y = rc.y(); |
53 | m_rect.w = rc.width(); |
54 | m_rect.h = rc.height(); |
55 | return m_rect; |
56 | } |
57 | private: |
58 | SkRegion::Iterator m_it; |
59 | mutable Rect m_rect; |
60 | template<typename> friend class RegionIterator; |
61 | friend class ::gfx::Region; |
62 | }; |
63 | |
64 | } // namespace details |
65 | |
66 | class Region { |
67 | public: |
68 | enum Overlap { Out, In, Part }; |
69 | |
70 | using iterator = details::RegionIterator<Rect>; |
71 | using const_iterator = details::RegionIterator<const Rect>; |
72 | |
73 | Region(); |
74 | Region(const Region& copy); |
75 | explicit Region(const Rect& rect); |
76 | Region& operator=(const Rect& rect); |
77 | Region& operator=(const Region& copy); |
78 | |
79 | iterator begin(); |
80 | iterator end(); |
81 | const_iterator begin() const; |
82 | const_iterator end() const; |
83 | |
84 | bool isEmpty() const { return m_region.isEmpty(); } |
85 | bool isRect() const { return m_region.isRect(); } |
86 | bool isComplex() const { return m_region.isComplex(); } |
87 | |
88 | std::size_t size() const { |
89 | return m_region.computeRegionComplexity(); |
90 | } |
91 | |
92 | Rect bounds() const; |
93 | |
94 | void clear() { |
95 | m_region.setEmpty(); |
96 | } |
97 | |
98 | void offset(int dx, int dy) { |
99 | m_region.translate(dx, dy); |
100 | } |
101 | |
102 | void offset(const PointT<int>& delta) { |
103 | m_region.translate(delta.x, delta.y); |
104 | } |
105 | |
106 | Region& createIntersection(const Region& a, const Region& b) { |
107 | m_region.op(a.m_region, b.m_region, SkRegion::kIntersect_Op); |
108 | return *this; |
109 | } |
110 | |
111 | Region& createUnion(const Region& a, const Region& b) { |
112 | m_region.op(a.m_region, b.m_region, SkRegion::kUnion_Op); |
113 | return *this; |
114 | } |
115 | |
116 | Region& createSubtraction(const Region& a, const Region& b) { |
117 | m_region.op(a.m_region, b.m_region, SkRegion::kDifference_Op); |
118 | return *this; |
119 | } |
120 | |
121 | bool contains(const PointT<int>& pt) const { |
122 | return m_region.contains(pt.x, pt.y); |
123 | } |
124 | Overlap contains(const Rect& rect) const; |
125 | |
126 | Region& operator+=(const Region& b) { return createUnion(*this, b); } |
127 | Region& operator|=(const Region& b) { return createUnion(*this, b); } |
128 | Region& operator&=(const Region& b) { return createIntersection(*this, b); } |
129 | Region& operator-=(const Region& b) { return createSubtraction(*this, b); } |
130 | |
131 | private: |
132 | mutable details::Region m_region; |
133 | }; |
134 | |
135 | } // namespace gfx |
136 | |
137 | #endif |
138 | |