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
18namespace 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