roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
clip_exclude_rects.h
Go to the documentation of this file.
1#pragma once
2
5
6namespace roo_display {
7
8/// Union of rectangles used as an exclusion mask.
9class RectUnion {
10 public:
11 /// Construct a rect union from a range.
12 RectUnion(const Box* begin, const Box* end) : begin_(begin), end_(end) {}
13
14 /// Reset to a new range.
15 void reset(const Box* begin, const Box* end) {
16 begin_ = begin;
17 end_ = end;
18 }
19
20 /// Return whether the union contains a point.
21 inline bool contains(int16_t x, int16_t y) const {
22 for (const Box* box = begin_; box != end_; ++box) {
23 if (box->contains(x, y)) return true;
24 }
25 return false;
26 }
27
28 /// Return whether the union intersects a rectangle.
29 inline bool intersects(const Box& rect) const {
30 for (const Box* box = begin_; box != end_; ++box) {
31 if (box->intersects(rect)) return true;
32 }
33 return false;
34 }
35
36 /// Return the number of rectangles in the union.
37 size_t size() const { return end_ - begin_; }
38
39 /// Return the rectangle at index `idx`.
40 const Box& at(int idx) const { return *(begin_ + idx); }
41
42 private:
43 const Box* begin_;
44 const Box* end_;
45};
46
47/// Filtering device that excludes a union of rectangles.
49 public:
50 /// Create a filter with an exclusion union.
52 : output_(&output),
53 exclusion_(exclusion),
54 address_window_(0, 0, 0, 0),
55 cursor_x_(0),
56 cursor_y_(0) {}
57
58 virtual ~RectUnionFilter() {}
59
60 /// Replace the underlying output.
61 void setOutput(DisplayOutput& output) { output_ = &output; }
62
64 BlendingMode mode) override {
65 address_window_ = Box(x0, y0, x1, y1);
66 blending_mode_ = mode;
67 cursor_x_ = x0;
68 cursor_y_ = y0;
69 }
70
71 void write(Color* color, uint32_t pixel_count) override {
72 // Naive implementation, for now.
73 uint32_t i = 0;
74 BufferedPixelWriter writer(*output_, blending_mode_);
75 while (i < pixel_count) {
76 if (!exclusion_->contains(cursor_x_, cursor_y_)) {
77 writer.writePixel(cursor_x_, cursor_y_, color[i]);
78 }
79 if (++cursor_x_ > address_window_.xMax()) {
80 ++cursor_y_;
81 cursor_x_ = address_window_.xMin();
82 }
83 ++i;
84 }
85 }
86
87 void fill(Color color, uint32_t pixel_count) override {
88 uint32_t i = 0;
89 BufferedPixelFiller filler(*output_, color, blending_mode_);
90 while (i < pixel_count) {
91 if (!exclusion_->contains(cursor_x_, cursor_y_)) {
92 filler.fillPixel(cursor_x_, cursor_y_);
93 }
94 if (++cursor_x_ > address_window_.xMax()) {
95 ++cursor_y_;
96 cursor_x_ = address_window_.xMin();
97 }
98 ++i;
99 }
100 }
101
102 void writeRects(BlendingMode mode, Color* color, int16_t* x0, int16_t* y0,
103 int16_t* x1, int16_t* y1, uint16_t count) override {
104 BufferedRectWriter writer(*output_, mode);
105 while (count-- > 0) {
106 writeRect(*color++, *x0++, *y0++, *x1++, *y1++, 0, &writer);
107 }
108 }
109
110 void fillRects(BlendingMode mode, Color color, int16_t* x0, int16_t* y0,
111 int16_t* x1, int16_t* y1, uint16_t count) override {
112 BufferedRectFiller filler(*output_, color, mode);
113 while (count-- > 0) {
114 fillRect(*x0++, *y0++, *x1++, *y1++, 0, &filler);
115 }
116 }
117
118 void writePixels(BlendingMode mode, Color* color, int16_t* x, int16_t* y,
119 uint16_t pixel_count) override {
120 int16_t* x_out = x;
121 int16_t* y_out = y;
124 for (uint16_t i = 0; i < pixel_count; ++i) {
125 if (!exclusion_->contains(x[i], y[i])) {
126 *x_out++ = x[i];
127 *y_out++ = y[i];
128 *color_out++ = color[i];
130 }
131 }
132 if (new_pixel_count > 0) {
133 output_->writePixels(mode, color, x, y, new_pixel_count);
134 }
135 }
136
137 void fillPixels(BlendingMode mode, Color color, int16_t* x, int16_t* y,
138 uint16_t pixel_count) override {
139 int16_t* x_out = x;
140 int16_t* y_out = y;
142 for (uint16_t i = 0; i < pixel_count; ++i) {
143 if (!exclusion_->contains(x[i], y[i])) {
144 *x_out++ = x[i];
145 *y_out++ = y[i];
147 }
148 }
149 if (new_pixel_count > 0) {
150 output_->fillPixels(mode, color, x, y, new_pixel_count);
151 }
152 }
153
154 const ColorFormat& getColorFormat() const override {
155 return output_->getColorFormat();
156 }
157
164
165 private:
166 void writeRect(Color color, int16_t x0, int16_t y0, int16_t x1, int16_t y1,
168 Box rect(x0, y0, x1, y1);
169 while (mask_idx < (int)exclusion_->size() &&
170 !exclusion_->at(mask_idx).intersects(rect)) {
171 ++mask_idx;
172 }
173 if (mask_idx == (int)exclusion_->size()) {
174 writer->writeRect(x0, y0, x1, y1, color);
175 return;
176 }
177 Box intruder = Box::Intersect(exclusion_->at(mask_idx), rect);
178 if (intruder.yMin() > y0) {
179 writeRect(color, x0, y0, x1, intruder.yMin() - 1, mask_idx + 1, writer);
180 y0 = intruder.yMin();
181 }
182 if (intruder.xMin() > x0) {
183 writeRect(color, x0, y0, intruder.xMin() - 1, intruder.yMax(),
184 mask_idx + 1, writer);
185 }
186 if (intruder.xMax() < x1) {
187 writeRect(color, intruder.xMax() + 1, y0, x1, intruder.yMax(),
188 mask_idx + 1, writer);
189 }
190 if (intruder.yMax() < y1) {
191 writeRect(color, x0, intruder.yMax() + 1, x1, y1, mask_idx + 1, writer);
192 }
193 }
194
195 void fillRect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int mask_idx,
196 BufferedRectFiller* filler) {
197 {
198 Box rect(x0, y0, x1, y1);
199 while (mask_idx < (int)exclusion_->size() &&
200 !exclusion_->at(mask_idx).intersects(rect)) {
201 ++mask_idx;
202 }
203 }
204 if (mask_idx == (int)exclusion_->size()) {
205 filler->fillRect(x0, y0, x1, y1);
206 return;
207 }
208 Box intruder =
209 Box::Intersect(exclusion_->at(mask_idx), Box(x0, y0, x1, y1));
210 if (intruder.yMin() > y0) {
211 fillRect(x0, y0, x1, intruder.yMin() - 1, mask_idx + 1, filler);
212 y0 = intruder.yMin();
213 }
214 if (intruder.xMin() > x0) {
215 fillRect(x0, y0, intruder.xMin() - 1, intruder.yMax(), mask_idx + 1,
216 filler);
217 }
218 if (intruder.xMax() < x1) {
219 fillRect(intruder.xMax() + 1, y0, x1, intruder.yMax(), mask_idx + 1,
220 filler);
221 }
222 if (intruder.yMax() < y1) {
223 fillRect(x0, intruder.yMax() + 1, x1, y1, mask_idx + 1, filler);
224 }
225 }
226
227 DisplayOutput* output_;
228 const RectUnion* exclusion_;
229 Box address_window_;
230 BlendingMode blending_mode_;
231 int16_t cursor_x_;
232 int16_t cursor_y_;
233};
234
235} // namespace roo_display
BufferedRectWriter & writer
Axis-aligned integer rectangle.
Definition box.h:12
int16_t xMin() const
Minimum x (inclusive).
Definition box.h:65
int16_t xMax() const
Maximum x (inclusive).
Definition box.h:71
bool intersects(const Box &other) const
Return whether this box intersects the other box.
Definition box.h:97
static Box Intersect(const Box &a, const Box &b)
Return the intersection of two boxes (may be empty).
Definition box.h:25
Buffered filler for arbitrary pixels using a single color.
Buffered writer for arbitrary pixels with per-pixel colors.
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
The abstraction for drawing to a display.
Definition device.h:15
virtual const ColorFormat & getColorFormat() const =0
Return the native color format used by this device for direct drawing.
virtual void drawDirectRect(const roo::byte *data, size_t row_width_bytes, int16_t src_x0, int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0, int16_t dst_y0)
Draw a rectangle represented in the device's native color format.
Definition device.cpp:33
virtual void fillPixels(BlendingMode blending_mode, Color color, int16_t *x, int16_t *y, uint16_t pixel_count)=0
Draw the specified pixels using the same color. Invalidates the address window.
virtual void writePixels(BlendingMode blending_mode, Color *color, int16_t *x, int16_t *y, uint16_t pixel_count)=0
Draw the specified pixels (per-pixel colors). Invalidates the address window.
Filtering device that excludes a union of rectangles.
const ColorFormat & getColorFormat() const override
Return the native color format used by this device for direct drawing.
void fill(Color color, uint32_t pixel_count) override
Write pixel_count copies of the same color into the current address window.
void setAddress(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, BlendingMode mode) override
Set a rectangular window filled by subsequent calls to write().
void fillRects(BlendingMode mode, Color color, int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1, uint16_t count) override
Draw the specified rectangles using the same color. Invalidates the address window.
void setOutput(DisplayOutput &output)
Replace the underlying output.
RectUnionFilter(DisplayOutput &output, const RectUnion *exclusion)
Create a filter with an exclusion union.
void writePixels(BlendingMode mode, Color *color, int16_t *x, int16_t *y, uint16_t pixel_count) override
Draw the specified pixels (per-pixel colors). Invalidates the address window.
void drawDirectRect(const roo::byte *data, size_t row_width_bytes, int16_t src_x0, int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0, int16_t dst_y0) override
Draw a rectangle represented in the device's native color format.
void fillPixels(BlendingMode mode, Color color, int16_t *x, int16_t *y, uint16_t pixel_count) override
Draw the specified pixels using the same color. Invalidates the address window.
void writeRects(BlendingMode mode, Color *color, int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1, uint16_t count) override
Draw the specified rectangles (per-rectangle colors). Invalidates the address window.
void write(Color *color, uint32_t pixel_count) override
Write pixels into the current address window.
Union of rectangles used as an exclusion mask.
bool intersects(const Box &rect) const
Return whether the union intersects a rectangle.
RectUnion(const Box *begin, const Box *end)
Construct a rect union from a range.
void reset(const Box *begin, const Box *end)
Reset to a new range.
size_t size() const
Return the number of rectangles in the union.
const Box & at(int idx) const
Return the rectangle at index idx.
bool contains(int16_t x, int16_t y) const
Return whether the union contains a point.
Defines 140 opaque HTML named colors.
BlendingMode
Porter-Duff style blending modes.
Definition blending.h:17