roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
roo_display.cpp
Go to the documentation of this file.
1#include "roo_display.h"
2
3#include <cmath>
4
6
7namespace roo_display {
8
10 TouchResult result = getRawTouch(points, max_points);
11 if (result.touch_points > 0) {
12 Orientation orientation = display_device_.orientation();
13 for (int i = 0; i < result.touch_points && i < max_points; ++i) {
14 TouchPoint& p = points[i];
15 touch_calibration_.Calibrate(p);
16 if (orientation.isRightToLeft()) {
17 p.x = 4095 - p.x;
18 p.vx = -p.vx;
19 }
20 if (orientation.isBottomToTop()) {
21 p.y = 4095 - p.y;
22 p.vy = -p.vy;
23 }
24 if (orientation.isXYswapped()) {
25 std::swap(p.x, p.y);
26 std::swap(p.vx, p.vy);
27 }
28 p.x = ((int32_t)p.x * (display_device_.effective_width() - 1)) / 4095;
29 p.y = ((int32_t)p.y * (display_device_.effective_height() - 1)) / 4095;
30 p.vx = ((int32_t)p.vx * (display_device_.effective_width() - 1)) / 4095;
31 p.vy = ((int32_t)p.vy * (display_device_.effective_height() - 1)) / 4095;
32 }
33 }
34 return result;
35}
36
37bool Display::getTouch(int16_t& x, int16_t& y) {
38 TouchPoint point;
39 TouchResult result = touch_.getTouch(&point, 1);
40 if (result.touch_points == 0) {
41 return false;
42 }
43 x = point.x;
44 y = point.y;
45 return true;
46}
47
48class DummyTouch : public TouchDevice {
49 public:
50 void initTouch() override {}
51
52 TouchResult getTouch(TouchPoint* points, int max_points) override {
53 return TouchResult(roo_time::Uptime::Now(), 0);
54 }
55};
56
58
59Display::Display(DisplayDevice& display_device, TouchDevice* touch_device,
60 TouchCalibration touch_calibration)
61 : display_device_(display_device),
62 output_(&display_device_),
63 touch_(display_device,
64 touch_device == nullptr ? dummy_touch : *touch_device,
65 touch_calibration),
66 nest_level_(0),
67 orientation_(display_device.orientation()),
68 extents_(Box::MaximumBox()),
69 bgcolor_(Color(0)),
70 background_(nullptr) {
71 resetExtents();
72}
73
74void Display::setOrientation(Orientation orientation) {
75 if (orientation_ == orientation) return;
76 orientation_ = orientation;
77 nest();
78 display_device_.setOrientation(orientation);
79 unnest();
80 // Update, since the width and height might have gotten swapped.
81 resetExtents();
82}
83
84void Display::init(Color bgcolor) {
85 init();
86 setBackgroundColor(bgcolor);
87 clear();
88}
89
90void Display::clear() {
91 DrawingContext dc(*this);
92 dc.clear();
93}
94
95void DrawingContext::fill(Color color) {
96 BlendingMode bm = blendingMode();
97 FillMode fm = fillMode();
98 setBlendingMode(BlendingMode::kSource);
99 setFillMode(FillMode::kExtents);
100 draw(Fill(color));
101 setBlendingMode(bm);
102 setFillMode(fm);
103}
104
105void DrawingContext::clear() {
106 BlendingMode bm = blendingMode();
107 FillMode fm = fillMode();
108 setBlendingMode(BlendingMode::kSource);
109 setFillMode(FillMode::kExtents);
110 draw(Clear());
111 setBlendingMode(bm);
112 setFillMode(fm);
113}
114
115void Display::enableTurbo() {
116 if (turbo_ != nullptr) return;
117 turbo_frame_buffer_ =
118 std::make_unique<BackgroundFillOptimizer::FrameBuffer>(width(), height());
119 turbo_ = std::make_unique<BackgroundFillOptimizer>(display_device_,
120 *turbo_frame_buffer_);
121 output_ = turbo_.get();
122}
123
124void Display::disableTurbo() {
125 output_ = &display_device_;
126 turbo_.reset();
127 turbo_frame_buffer_.reset();
128}
129
130namespace {
131
132class Pixels : public Drawable {
133 public:
134 Pixels(const std::function<void(ClippingBufferedPixelWriter&)>& fn,
136 : fn_(fn), extents_(extents), blending_mode_(blending_mode) {}
137
138 Box extents() const override { return extents_; }
139
140 private:
141 void drawTo(const Surface& s) const override {
142 if (s.dx() == 0 && s.dy() == 0) {
143 ClippingBufferedPixelWriter writer(s.out(), extents_, blending_mode_);
144 fn_(writer);
145 } else {
146 TransformedDisplayOutput out(s.out(),
147 Transformation().translate(s.dx(), s.dy()));
148 ClippingBufferedPixelWriter writer(out, extents_, blending_mode_);
149 fn_(writer);
150 }
151 }
152
153 const std::function<void(ClippingBufferedPixelWriter&)>& fn_;
154 Box extents_;
155 BlendingMode blending_mode_;
156};
157
158} // namespace
159
160DrawingContext::~DrawingContext() { unnest_(); }
161
162void DrawingContext::setWriteOnce() {
163 if (write_once_) return;
164 write_once_ = true;
165 front_to_back_writer_.reset(
166 new FrontToBackWriter(output(), bounds().translate(dx_, dy_)));
167}
168
169void DrawingContext::drawPixels(
170 const std::function<void(ClippingBufferedPixelWriter&)>& fn,
172 draw(Pixels(fn, transformation_.smallestEnclosingRect(clip_box_),
174}
175
176void DrawingContext::drawInternal(const Drawable& object, int16_t dx,
177 int16_t dy, Color bgcolor) {
178 DisplayOutput& out = front_to_back_writer_.get() != nullptr
179 ? *front_to_back_writer_
180 : output();
181 Surface s(out, dx + dx_, dy + dy_, clip_box_.translate(dx_, dy_), write_once_,
182 bgcolor, fill_mode_, blending_mode_);
183 if (clip_mask_ == nullptr) {
184 drawInternalWithBackground(s, object);
185 } else {
186 ClipMaskFilter filter(out, clip_mask_, dx_, dy_);
187 s.set_out(&filter);
188 drawInternalWithBackground(s, object);
189 }
190}
191
192void DrawingContext::drawInternalWithBackground(Surface& s,
193 const Drawable& object) {
194 if (background_ == nullptr) {
195 drawInternalTransformed(s, object);
196 } else {
197 BackgroundFilter filter(s.out(), background_, dx_, dy_, s.bgcolor());
198 s.set_out(&filter);
199 s.set_bgcolor(color::Transparent);
200 drawInternalTransformed(s, object);
201 }
202}
203
204void DrawingContext::drawInternalTransformed(Surface& s,
205 const Drawable& object) {
206 if (!transformed_) {
207 if (s.clipToExtents(object.extents()) == Box::ClipResult::kEmpty) return;
208 s.drawObject(object);
209 } else if (!transformation_.is_rescaled() && !transformation_.xy_swap()) {
210 // Translation only.
211 s.set_dx(s.dx() + transformation_.x_offset());
212 s.set_dy(s.dy() + transformation_.y_offset());
213 if (s.clipToExtents(object.extents()) == Box::ClipResult::kEmpty) return;
214 s.drawObject(object);
215 } else {
216 auto transformed = TransformedDrawable(transformation_, &object);
217 if (s.clipToExtents(transformed.extents()) == Box::ClipResult::kEmpty) {
218 return;
219 }
220 s.drawObject(transformed);
221 }
222}
223
224namespace {
225
226class ErasedDrawable : public Drawable {
227 public:
228 ErasedDrawable(const Drawable* delegate) : delegate_(delegate) {}
229
230 Box extents() const override { return delegate_->extents(); }
231 Box anchorExtents() const override { return delegate_->anchorExtents(); }
232
233 private:
234 void drawTo(const Surface& s) const override {
235 Surface news = s;
236 ColorFilter<Erasure> filter(s.out(), s.bgcolor());
237 news.set_out(&filter);
238 news.set_blending_mode(BlendingMode::kSource);
239 news.drawObject(*delegate_);
240 }
241
242 const Drawable* delegate_;
243};
244
245} // namespace
246
247void DrawingContext::erase(const Drawable& object) {
248 draw(ErasedDrawable(&object));
249}
250
251void DrawingContext::erase(const Drawable& object, int16_t dx, int16_t dy) {
252 draw(ErasedDrawable(&object), dx, dy);
253}
254
255void DrawingContext::erase(const Drawable& object, Alignment alignment) {
256 draw(ErasedDrawable(&object), alignment);
257}
258
259void Fill::readColors(const int16_t* x, const int16_t* y, uint32_t count,
260 Color* result) const {
261 FillColor(result, count, color_);
262}
263
264bool Fill::readColorRect(int16_t xMin, int16_t yMin, int16_t xMax, int16_t yMax,
265 Color* result) const {
266 *result = color_;
267 return true;
268}
269
270void Fill::drawTo(const Surface& s) const {
271 Color color = AlphaBlend(s.bgcolor(), color_);
272 if (color == color::Transparent && s.fill_mode() == FillMode::kVisible) {
273 return;
274 }
275 s.out().fillRect(s.blending_mode(), s.clip_box(), color);
276}
277
278void Clear::readColors(const int16_t* x, const int16_t* y, uint32_t count,
279 Color* result) const {
280 FillColor(result, count, color::Transparent);
281}
282
283bool Clear::readColorRect(int16_t xMin, int16_t yMin, int16_t xMax,
284 int16_t yMax, Color* result) const {
285 *result = color::Transparent;
286 return true;
287}
288
289void Clear::drawTo(const Surface& s) const {
290 if (s.fill_mode() == FillMode::kVisible &&
291 s.bgcolor() == color::Transparent) {
292 return;
293 }
294 s.out().fillRect(s.blending_mode(), s.clip_box(), s.bgcolor());
295}
296
297} // namespace roo_display
BufferedRectWriter & writer
Combines horizontal and vertical alignment.
Definition alignment.h:172
Axis-aligned integer rectangle.
Definition box.h:12
Infinite transparent area.
Buffered pixel writer with a clipping box.
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
Base class for display device drivers.
Definition device.h:223
int16_t effective_height() const
Return the display height in the current orientation.
Definition device.h:270
Orientation orientation() const
Return the current orientation of the display.
Definition device.h:250
int16_t effective_width() const
Return the display width in the current orientation.
Definition device.h:265
The abstraction for drawing to a display.
Definition device.h:15
void fillRect(BlendingMode blending_mode, const Box &rect, Color color)
Fill a single rectangle. Invalidates the address window.
Definition device.h:135
Display(DisplayDevice &display_device)
Constructs a display without touch support.
Definition roo_display.h:67
TouchResult getTouch(TouchPoint *points, int max_points)
Returns calibrated touch points in display coordinates.
Interface for objects that can be drawn to an output device.
Definition drawable.h:229
virtual Box extents() const =0
Return the bounding box encompassing all pixels that need to be drawn.
Primary top-level interface for drawing to screens, off-screen buffers, or other devices.
void clear()
Clears the display, respecting the clip box, and background settings.
void initTouch() override
Initialize the touch controller.
TouchResult getTouch(TouchPoint *points, int max_points) override
Read the current touch state.
Infinite single-color area.
Writer that ensures front-most pixels are written first.
Represents the orientation of a display device.
Definition orientation.h:25
bool isRightToLeft() const
Return whether horizontal direction is right-to-left.
bool isBottomToTop() const
Return whether vertical direction is bottom-to-top.
bool isXYswapped() const
Return whether x maps to the vertical direction.
Definition orientation.h:90
Low-level handle used to draw to an underlying device.
Definition drawable.h:60
Color bgcolor() const
Return the background color used for blending.
Definition drawable.h:140
const Box & clip_box() const
Return the clip box in device coordinates (independent of offsets).
Definition drawable.h:134
BlendingMode blending_mode() const
Return the default blending mode for drawing.
Definition drawable.h:162
FillMode fill_mode() const
Return the fill mode the drawable should observe. FillMode::kVisible If FillMode::kExtents,...
Definition drawable.h:151
DisplayOutput & out() const
Return the device output.
Definition drawable.h:119
Touch calibration parameters (bounds + orientation).
Definition calibration.h:10
void Calibrate(TouchPoint &point)
Apply calibration and orientation to the given touch point.
Touch controller interface.
Definition device.h:428
TouchResult getTouch(TouchPoint *points, int max_points)
Returns calibrated touch points in display coordinates.
TouchResult getRawTouch(TouchPoint *points, int max_points)
Returns raw touch points in absolute 0-4095 coordinates.
Definition roo_display.h:41
Defines 140 opaque HTML named colors.
BlendingMode
Porter-Duff style blending modes.
Definition blending.h:17
static DummyTouch dummy_touch
Color AlphaBlend(Color bgc, Color fgc)
Definition blending.h:598
BlendingFilter< BlendOp< BlendingMode::kSourceOver > > BackgroundFilter
Filtering device that blends with a rasterizable background.
Definition background.h:9
void FillColor(Color *buf, uint32_t count, Color color)
Fill an array with a single color.
Definition color.h:109
FillMode
Specifies whether a Drawable should fill its entire extents box, including fully transparent pixels.
Definition drawable.h:15
Public API surface for roo_display display, touch, and drawing utilities.
DisplayOutput * out
Definition smooth.cpp:886
Color bgcolor
Definition smooth.cpp:889
BlendingMode blending_mode
Definition smooth.cpp:888
A single touch point returned by a touch controller.
Definition device.h:390
int16_t x
X-coordinate of the touch.
Definition device.h:398
int16_t y
Y-coordinate of the touch.
Definition device.h:401
int32_t vy
Y-axis velocity at the touch point, in pixels/sec.
Definition device.h:411
int32_t vx
X-axis velocity at the touch point, in pixels/sec.
Definition device.h:408
Metadata for a touch sampling result.
Definition device.h:415