oxide_gui_core/backend.rs
1//! `Backend` — the single trait that every platform must implement.
2//!
3//! A backend owns the framebuffer (or window) and provides three core
4//! operations: draw into the buffer, flush the buffer to the screen, and
5//! return the next pending input event.
6//!
7//! Default implementations of `draw_char` and `draw_text` are provided using
8//! the embedded bitmap font in `font.rs`. A backend can override these for
9//! hardware-accelerated text.
10//!
11//! ## Implementing a new backend
12//!
13//! ```rust,ignore
14//! struct MyBackend { /* framebuffer pointer, width, height */ }
15//!
16//! impl Backend for MyBackend {
17//! fn width(&self) -> u32 { … }
18//! fn height(&self) -> u32 { … }
19//!
20//! fn fill_rect(&mut self, x: u32, y: u32, w: u32, h: u32, color: Color) {
21//! // write pixels into your framebuffer
22//! }
23//!
24//! fn present(&mut self) {
25//! // flush back-buffer to screen (or no-op for direct FB)
26//! }
27//!
28//! fn poll_event(&mut self) -> Option<Event> {
29//! // translate native input into oxide-gui Event
30//! None
31//! }
32//! }
33//! ```
34
35use crate::color::Color;
36use crate::event::Event;
37use crate::font;
38
39pub trait Backend {
40 // ── Required ───────────────────────────────────────────────────────────
41
42 /// Framebuffer width in pixels.
43 fn width(&self) -> u32;
44
45 /// Framebuffer height in pixels.
46 fn height(&self) -> u32;
47
48 /// Fill a rectangle with a solid color.
49 /// Out-of-bounds coordinates should be clipped silently.
50 fn fill_rect(&mut self, x: u32, y: u32, w: u32, h: u32, color: Color);
51
52 /// Flush the back-buffer to the physical display.
53 fn present(&mut self);
54
55 /// Return the next pending input event, or `None` if the queue is empty.
56 fn poll_event(&mut self) -> Option<Event>;
57
58 // ── Provided (override for hardware acceleration) ──────────────────────
59
60 /// Draw a single character at `(x, y)` using the embedded bitmap font.
61 fn draw_char(&mut self, x: u32, y: u32, ch: char, color: Color) {
62 font::render_char(self, x, y, ch, color);
63 }
64
65 /// Draw a string at `(x, y)` advancing by `font::CHAR_W` per glyph.
66 fn draw_text(&mut self, x: u32, y: u32, text: &str, color: Color) {
67 let mut cx = x;
68 for ch in text.chars() {
69 if cx + font::CHAR_W > self.width() { break; }
70 self.draw_char(cx, y, ch, color);
71 cx += font::CHAR_W;
72 }
73 }
74
75 /// Draw a 1-pixel horizontal rule.
76 fn hline(&mut self, x: u32, y: u32, w: u32, color: Color) {
77 self.fill_rect(x, y, w, 1, color);
78 }
79
80 /// Draw a 1-pixel vertical rule.
81 fn vline(&mut self, x: u32, y: u32, h: u32, color: Color) {
82 self.fill_rect(x, y, 1, h, color);
83 }
84
85 /// Draw a hollow rectangle (border only, 1-pixel thick).
86 fn draw_rect(&mut self, x: u32, y: u32, w: u32, h: u32, color: Color) {
87 self.hline(x, y, w, color);
88 self.hline(x, y + h - 1, w, color);
89 self.vline(x, y, h, color);
90 self.vline(x + w - 1, y, h, color);
91 }
92
93 /// Clear the entire framebuffer to `color`.
94 fn clear(&mut self, color: Color) {
95 let (w, h) = (self.width(), self.height());
96 self.fill_rect(0, 0, w, h, color);
97 }
98
99 /// Return `(width, height)` as a tuple.
100 fn size(&self) -> (u32, u32) { (self.width(), self.height()) }
101}