18template <
typename Blender>
43 address_window_(0, 0, 0, 0),
57 address_window_ =
Box(x0 - dx_, y0 - dy_, x1 - dx_, y1 - dy_);
72 if (cursor_x_ > address_window_.
xMax()) {
74 cursor_x_ = address_window_.
xMin();
82 if (bgcolor_ != color::Transparent) {
99 if (cursor_x_ > address_window_.
xMax()) {
101 cursor_x_ = address_window_.
xMin();
108 if (bgcolor_ != color::Transparent) {
134 while (count-- > 0) {
135 fillRect(mode, *x0++, *y0++, *x1++, *y1++, *
color++);
141 while (count-- > 0) {
142 fillRect(mode, *x0++, *y0++, *x1++, *y1++,
color);
154 if (bgcolor_ != color::Transparent) {
170 if (bgcolor_ != color::Transparent) {
192 if (dx_ == 0 && dy_ == 0) {
197 int16_t xp[pixel_count];
198 int16_t yp[pixel_count];
199 for (uint32_t i = 0; i < pixel_count; ++i) {
207 void fillRect(
BlendingMode mode, int16_t xMin, int16_t yMin, int16_t xMax,
208 int16_t yMax, Color color) {
209 Color out_of_bounds_color =
AlphaBlend(bgcolor_, color);
211 raster_->
extents().translate(dx_, dy_));
212 if (trimmed.empty()) {
213 output_->
fillRect(mode, xMin, yMin, xMax, yMax, out_of_bounds_color);
216 if (yMin < trimmed.yMin()) {
218 output_->
fillRect(mode, xMin, yMin, xMax, trimmed.yMin() - 1,
219 out_of_bounds_color);
221 if (xMin < trimmed.xMin()) {
223 output_->
fillRect(mode, xMin, trimmed.yMin(), trimmed.xMin() - 1,
224 trimmed.yMax(), out_of_bounds_color);
226 fillRectIntersectingRaster(mode, trimmed.xMin(), trimmed.yMin(),
227 trimmed.xMax(), trimmed.yMax(), color);
228 if (xMax > trimmed.xMax()) {
230 output_->
fillRect(mode, trimmed.xMax() + 1, trimmed.yMin(), xMax,
231 trimmed.yMax(), out_of_bounds_color);
233 if (yMax > trimmed.yMax()) {
235 output_->
fillRect(mode, xMin, trimmed.yMax() + 1, xMax, yMax,
236 out_of_bounds_color);
240 void fillRectIntersectingRaster(
BlendingMode mode, int16_t xMin, int16_t yMin,
241 int16_t xMax, int16_t yMax, Color color) {
243 uint32_t pixel_count = (xMax - xMin + 1) * (yMax - yMin + 1);
244 if (pixel_count <= 64) {
245 fillRectInternal(mode, xMin, yMin, xMax, yMax, color);
249 const int16_t xMinOuter = (xMin / 8) * 8;
250 const int16_t yMinOuter = (yMin / 8) * 8;
251 const int16_t xMaxOuter = (xMax / 8) * 8 + 7;
252 const int16_t yMaxOuter = (yMax / 8) * 8 + 7;
253 for (int16_t y = yMinOuter; y < yMaxOuter; y += 8) {
254 for (int16_t x = xMinOuter; x < xMaxOuter; x += 8) {
255 fillRectInternal(mode, std::max(x, xMin), std::max(y, yMin),
256 std::min((int16_t)(x + 7), xMax),
257 std::min((int16_t)(y + 7), yMax), color);
263 void fillRectInternal(
BlendingMode mode, int16_t xMin, int16_t yMin,
264 int16_t xMax, int16_t yMax, Color color) {
265 uint16_t pixel_count = (xMax - xMin + 1) * (yMax - yMin + 1);
266 Color newcolor[pixel_count];
267 bool same = raster_->
readColorRect(xMin - dx_, yMin - dy_, xMax - dx_,
268 yMax - dy_, newcolor);
270 output_->
fillRect(mode, Box(xMin, yMin, xMax, yMax),
271 AlphaBlend(bgcolor_, blender_(newcolor[0], color)));
273 for (uint16_t i = 0; i < pixel_count; ++i) {
274 newcolor[i] = blender_(newcolor[i], color);
276 if (bgcolor_ != color::Transparent) {
277 for (uint16_t i = 0; i < pixel_count; ++i) {
278 newcolor[i] =
AlphaBlend(bgcolor_, newcolor[i]);
281 output_->
setAddress(Box(xMin, yMin, xMax, yMax), mode);
282 output_->
write(newcolor, pixel_count);
286 DisplayOutput* output_;
288 const Rasterizable* raster_;
Filtering device that blends with a rasterizable image.
BlendingFilter(DisplayOutput &output, const Rasterizable *raster, Color bgcolor=color::Transparent)
Create a blending filter with default blender and no offset.
void setOutput(DisplayOutput &output)
Replace the underlying output.
BlendingFilter(DisplayOutput &output, const Rasterizable *raster, int16_t dx, int16_t dy, Color bgcolor=color::Transparent)
Create a blending filter with an offset.
void write(Color *color, uint32_t pixel_count) override
Write pixels into the current address window.
virtual ~BlendingFilter()
BlendingFilter(DisplayOutput &output, Blender blender, const Rasterizable *raster, int16_t dx, int16_t dy, Color bgcolor=color::Transparent)
Create a blending filter with a custom blender and offset.
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 fill(Color color, uint32_t pixel_count) override
Write pixel_count copies of the same color into the current address window.
BlendingFilter(DisplayOutput &output, Blender blender, const Rasterizable *raster, Color bgcolor=color::Transparent)
Create a blending filter with a custom blender.
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 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 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 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.
const ColorFormat & getColorFormat() const override
Return the native color format used by this device for direct drawing.
Axis-aligned integer rectangle.
int16_t xMin() const
Minimum x (inclusive).
int16_t xMax() const
Maximum x (inclusive).
static Box Intersect(const Box &a, const Box &b)
Return the intersection of two boxes (may be empty).
ARGB8888 color stored as a 32-bit unsigned integer.
The abstraction for drawing to a display.
virtual void write(Color *color, uint32_t pixel_count)=0
Write pixels into the current address window.
virtual const ColorFormat & getColorFormat() const =0
Return the native color format used by this device for direct drawing.
void fillRect(BlendingMode blending_mode, const Box &rect, Color color)
Fill a single rectangle. Invalidates the address window.
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.
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.
void setAddress(const Box &bounds, BlendingMode blending_mode)
Convenience overload for setAddress() using a Box.
virtual Box extents() const =0
Return the bounding box encompassing all pixels that need to be drawn.
Drawable that can provide a color for any point within its extents.
void readColorsMaybeOutOfBounds(const int16_t *x, const int16_t *y, uint32_t count, Color *result, Color out_of_bounds_color=color::Transparent) const
Read colors for points that may be out of bounds.
virtual bool readColorRect(int16_t xMin, int16_t yMin, int16_t xMax, int16_t yMax, Color *result) const
Read colors for a rectangle.
Defines 140 opaque HTML named colors.
BlendingMode
Porter-Duff style blending modes.
Color AlphaBlend(Color bgc, Color fgc)