1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use alloc::boxed::Box;
5use alloc::rc::Rc;
6use core::pin::Pin;
7
8use crate::api::PlatformError;
9use crate::graphics::{Rgba8Pixel, SharedPixelBuffer};
10use crate::item_tree::ItemTreeRef;
11use crate::items::TextWrap;
12use crate::lengths::{LogicalLength, LogicalPoint, LogicalRect, LogicalSize, ScaleFactor};
13use crate::window::WindowAdapter;
14
15/// This trait represents a Renderer that can render a slint scene.
16///
17/// This trait is [sealed](https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed),
18/// meaning that you are not expected to implement this trait
19/// yourself, but you should use the provided one from Slint such as
20/// [`SoftwareRenderer`](crate::software_renderer::SoftwareRenderer)
21pub trait Renderer: RendererSealed {}
22impl<T: RendererSealed> Renderer for T {}
23
24/// Implementation details behind [`Renderer`], but since this
25/// trait is not exported in the public API, it is not possible for the
26/// users to re-implement these functions.
27pub trait RendererSealed {
28 /// Returns the size of the given text in logical pixels.
29 /// When set, `max_width` means that one need to wrap the text, so it does not go further than that,
30 /// using the wrapping type passed by `text_wrap`.
31 fn text_size(
32 &self,
33 font_request: crate::graphics::FontRequest,
34 text: &str,
35 max_width: Option<LogicalLength>,
36 scale_factor: ScaleFactor,
37 text_wrap: TextWrap,
38 ) -> LogicalSize;
39
40 /// Returns the metrics of the given font.
41 fn font_metrics(
42 &self,
43 font_request: crate::graphics::FontRequest,
44 scale_factor: ScaleFactor,
45 ) -> crate::items::FontMetrics;
46
47 /// Returns the (UTF-8) byte offset in the text property that refers to the character that contributed to
48 /// the glyph cluster that's visually nearest to the given coordinate. This is used for hit-testing,
49 /// for example when receiving a mouse click into a text field. Then this function returns the "cursor"
50 /// position.
51 fn text_input_byte_offset_for_position(
52 &self,
53 text_input: Pin<&crate::items::TextInput>,
54 pos: LogicalPoint,
55 font_request: crate::graphics::FontRequest,
56 scale_factor: ScaleFactor,
57 ) -> usize;
58
59 /// That's the opposite of [`Self::text_input_byte_offset_for_position`]
60 /// It takes a (UTF-8) byte offset in the text property, and returns a Rectangle
61 /// left to the char. It is one logical pixel wide and ends at the baseline.
62 fn text_input_cursor_rect_for_byte_offset(
63 &self,
64 text_input: Pin<&crate::items::TextInput>,
65 byte_offset: usize,
66 font_request: crate::graphics::FontRequest,
67 scale_factor: ScaleFactor,
68 ) -> LogicalRect;
69
70 /// Clear the caches for the items that are being removed
71 fn free_graphics_resources(
72 &self,
73 _component: ItemTreeRef,
74 _items: &mut dyn Iterator<Item = Pin<crate::items::ItemRef<'_>>>,
75 ) -> Result<(), crate::platform::PlatformError> {
76 Ok(())
77 }
78
79 /// Mark a given region as dirty regardless whether the items actually are dirty.
80 ///
81 /// Example: when a PopupWindow disappears, the region under the popup needs to be redrawn
82 fn mark_dirty_region(&self, _region: crate::item_rendering::DirtyRegion) {}
83
84 #[cfg(feature = "std")] // FIXME: just because of the Error
85 /// This function can be used to register a custom TrueType font with Slint,
86 /// for use with the `font-family` property. The provided slice must be a valid TrueType
87 /// font.
88 fn register_font_from_memory(
89 &self,
90 _data: &'static [u8],
91 ) -> Result<(), Box<dyn std::error::Error>> {
92 Err("This renderer does not support registering custom fonts.".into())
93 }
94
95 #[cfg(feature = "std")]
96 /// This function can be used to register a custom TrueType font with Slint,
97 /// for use with the `font-family` property. The provided path must refer to a valid TrueType
98 /// font.
99 fn register_font_from_path(
100 &self,
101 _path: &std::path::Path,
102 ) -> Result<(), Box<dyn std::error::Error>> {
103 Err("This renderer does not support registering custom fonts.".into())
104 }
105
106 fn register_bitmap_font(&self, _font_data: &'static crate::graphics::BitmapFont) {
107 crate::debug_log!("Internal error: The current renderer cannot load fonts build with the `EmbedForSoftwareRenderer` option. Please use the software Renderer, or disable that option when building your slint files");
108 }
109
110 /// This function is called through the public API to register a callback that the backend needs to invoke during
111 /// different phases of rendering.
112 fn set_rendering_notifier(
113 &self,
114 _callback: Box<dyn crate::api::RenderingNotifier>,
115 ) -> Result<(), crate::api::SetRenderingNotifierError> {
116 Err(crate::api::SetRenderingNotifierError::Unsupported)
117 }
118
119 fn default_font_size(&self) -> LogicalLength;
120
121 fn set_window_adapter(&self, _window_adapter: &Rc<dyn WindowAdapter>);
122
123 fn resize(&self, _size: crate::api::PhysicalSize) -> Result<(), PlatformError> {
124 Ok(())
125 }
126
127 /// Re-implement this function to support Window::take_snapshot(), i.e. return
128 /// the contents of the window in an image buffer.
129 fn take_snapshot(&self) -> Result<SharedPixelBuffer<Rgba8Pixel>, PlatformError> {
130 Err("WindowAdapter::take_snapshot is not implemented by the platform".into())
131 }
132}
133