Skip to main content

i_slint_core/
renderer.rs

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::{ItemRc, 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 ones from Slint.
20pub trait Renderer: RendererSealed {}
21impl<T: RendererSealed> Renderer for T {}
22
23/// Implementation details behind [`Renderer`], but since this
24/// trait is not exported in the public API, it is not possible for the
25/// users to re-implement these functions.
26pub trait RendererSealed {
27    /// Returns the size of the given text in logical pixels.
28    /// When set, `max_width` means that one need to wrap the text, so it does not go further than that,
29    /// using the wrapping type passed by `text_wrap`.
30    fn text_size(
31        &self,
32        text_item: Pin<&dyn crate::item_rendering::RenderString>,
33        item_rc: &crate::item_tree::ItemRc,
34        max_width: Option<LogicalLength>,
35        text_wrap: TextWrap,
36    ) -> LogicalSize;
37
38    /// Returns the size of the individual character in logical pixels.
39    fn char_size(
40        &self,
41        text_item: Pin<&dyn crate::item_rendering::HasFont>,
42        item_rc: &crate::item_tree::ItemRc,
43        ch: char,
44    ) -> LogicalSize;
45
46    /// Returns the metrics of the given font.
47    fn font_metrics(&self, font_request: crate::graphics::FontRequest)
48    -> crate::items::FontMetrics;
49
50    /// Returns the (UTF-8) byte offset in the text property that refers to the character that contributed to
51    /// the glyph cluster that's visually nearest to the given coordinate. This is used for hit-testing,
52    /// for example when receiving a mouse click into a text field. Then this function returns the "cursor"
53    /// position.
54    fn text_input_byte_offset_for_position(
55        &self,
56        text_input: Pin<&crate::items::TextInput>,
57        item_rc: &ItemRc,
58        pos: LogicalPoint,
59    ) -> usize;
60
61    /// That's the opposite of [`Self::text_input_byte_offset_for_position`]
62    /// It takes a (UTF-8) byte offset in the text property, and returns a Rectangle
63    /// left to the char. It is one logical pixel wide and ends at the baseline.
64    fn text_input_cursor_rect_for_byte_offset(
65        &self,
66        text_input: Pin<&crate::items::TextInput>,
67        item_rc: &ItemRc,
68        byte_offset: usize,
69    ) -> LogicalRect;
70
71    /// Clear the caches for the items that are being removed
72    fn free_graphics_resources(
73        &self,
74        _component: ItemTreeRef,
75        _items: &mut dyn Iterator<Item = Pin<crate::items::ItemRef<'_>>>,
76    ) -> Result<(), crate::platform::PlatformError> {
77        Ok(())
78    }
79
80    /// Mark a given region as dirty regardless whether the items actually are dirty.
81    ///
82    /// Example: when a PopupWindow disappears, the region under the popup needs to be redrawn
83    fn mark_dirty_region(&self, _region: crate::partial_renderer::DirtyRegion) {}
84
85    #[cfg(feature = "std")] // FIXME: just because of the Error
86    /// This function can be used to register a custom TrueType font with Slint,
87    /// for use with the `font-family` property. The provided slice must be a valid TrueType
88    /// font.
89    fn register_font_from_memory(
90        &self,
91        _data: &'static [u8],
92    ) -> Result<(), Box<dyn std::error::Error>> {
93        Err("This renderer does not support registering custom fonts.".into())
94    }
95
96    #[cfg(feature = "std")]
97    /// This function can be used to register a custom TrueType font with Slint,
98    /// for use with the `font-family` property. The provided path must refer to a valid TrueType
99    /// font.
100    fn register_font_from_path(
101        &self,
102        _path: &std::path::Path,
103    ) -> Result<(), Box<dyn std::error::Error>> {
104        Err("This renderer does not support registering custom fonts.".into())
105    }
106
107    fn register_bitmap_font(&self, _font_data: &'static crate::graphics::BitmapFont) {
108        crate::debug_log!(
109            "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"
110        );
111    }
112
113    /// This function is called through the public API to register a callback that the backend needs to invoke during
114    /// different phases of rendering.
115    fn set_rendering_notifier(
116        &self,
117        _callback: Box<dyn crate::api::RenderingNotifier>,
118    ) -> Result<(), crate::api::SetRenderingNotifierError> {
119        Err(crate::api::SetRenderingNotifierError::Unsupported)
120    }
121
122    fn set_window_adapter(&self, _window_adapter: &Rc<dyn WindowAdapter>);
123
124    fn window_adapter(&self) -> Option<Rc<dyn WindowAdapter>>;
125
126    fn scale_factor(&self) -> Option<ScaleFactor> {
127        self.window_adapter()
128            .map(|window_adapter| ScaleFactor::new(window_adapter.window().scale_factor()))
129    }
130
131    fn default_font_size(&self) -> LogicalLength;
132
133    fn resize(&self, _size: crate::api::PhysicalSize) -> Result<(), PlatformError> {
134        Ok(())
135    }
136
137    /// Re-implement this function to support Window::take_snapshot(), i.e. return
138    /// the contents of the window in an image buffer.
139    fn take_snapshot(&self) -> Result<SharedPixelBuffer<Rgba8Pixel>, PlatformError> {
140        Err("WindowAdapter::take_snapshot is not implemented by the platform".into())
141    }
142
143    /// Whether the renderer supports transformations such as rotations and scaling or not.
144    fn supports_transformations(&self) -> bool;
145}