1#![allow(unsafe_code)]
5#![warn(missing_docs)]
6extern crate alloc;
12use crate::Coord;
13use crate::SharedString;
14use crate::api::PlatformError;
15use crate::lengths::LogicalLength;
16use alloc::boxed::Box;
17
18pub use euclid;
19pub type Rect = euclid::default::Rect<Coord>;
21pub type IntRect = euclid::default::Rect<i32>;
23pub type Point = euclid::default::Point2D<Coord>;
25pub type Size = euclid::default::Size2D<Coord>;
27pub type IntSize = euclid::default::Size2D<u32>;
29pub type Transform = euclid::default::Transform2D<Coord>;
31
32pub(crate) mod color;
33pub use color::*;
34
35#[cfg(feature = "shared-fontique")]
36use i_slint_common::sharedfontique::{self, fontique};
37#[cfg(feature = "path")]
38mod path;
39#[cfg(feature = "path")]
40pub use path::*;
41
42mod brush;
43pub use brush::*;
44
45pub(crate) mod image;
46pub use self::image::*;
47
48pub(crate) mod bitmapfont;
49pub use self::bitmapfont::*;
50
51pub mod rendering_metrics_collector;
52
53#[cfg(feature = "box-shadow-cache")]
54pub mod boxshadowcache;
55
56pub mod border_radius;
57pub use border_radius::*;
58
59#[cfg(feature = "wgpu-27")]
60pub mod wgpu_27;
61#[cfg(feature = "wgpu-28")]
62pub mod wgpu_28;
63
64pub struct CachedGraphicsData<T> {
69 pub data: T,
71 pub dependency_tracker: Option<core::pin::Pin<Box<crate::properties::PropertyTracker>>>,
74}
75
76impl<T> CachedGraphicsData<T> {
77 pub fn new(update_fn: impl FnOnce() -> T) -> Self {
80 let dependency_tracker = Box::pin(crate::properties::PropertyTracker::default());
81 let data = dependency_tracker.as_ref().evaluate(update_fn);
82 Self { data, dependency_tracker: Some(dependency_tracker) }
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Default)]
90pub struct FontRequest {
91 pub family: Option<SharedString>,
94 pub weight: Option<i32>,
96 pub pixel_size: Option<LogicalLength>,
98 pub letter_spacing: Option<LogicalLength>,
101 pub italic: bool,
103}
104
105#[cfg(feature = "shared-fontique")]
106impl FontRequest {
107 pub fn query_fontique(
109 &self,
110 collection: &mut fontique::Collection,
111 source_cache: &mut fontique::SourceCache,
112 ) -> Option<fontique::QueryFont> {
113 let mut query = collection.query(source_cache);
114 query.set_families(
115 self.family
116 .as_ref()
117 .map(|family| fontique::QueryFamily::from(family.as_str()))
118 .into_iter()
119 .chain(
120 sharedfontique::FALLBACK_FAMILIES
121 .into_iter()
122 .map(fontique::QueryFamily::Generic),
123 ),
124 );
125
126 query.set_attributes(fontique::Attributes {
127 weight: self
128 .weight
129 .as_ref()
130 .map(|&weight| fontique::FontWeight::new(weight as f32))
131 .unwrap_or_default(),
132 style: if self.italic {
133 fontique::FontStyle::Italic
134 } else {
135 fontique::FontStyle::Normal
136 },
137 ..Default::default()
138 });
139
140 let mut font = None;
141
142 query.matches_with(|queried_font| {
143 font = Some(queried_font.clone());
144 fontique::QueryStatus::Stop
145 });
146
147 font
148 }
149}
150
151#[derive(Debug, Clone, PartialEq)]
154pub enum RequestedOpenGLVersion {
155 OpenGL(Option<(u8, u8)>),
157 OpenGLES(Option<(u8, u8)>),
159}
160
161#[derive(Debug, Clone)]
164#[allow(clippy::large_enum_variant)]
165pub enum RequestedGraphicsAPI {
166 OpenGL(RequestedOpenGLVersion),
168 Metal,
170 Vulkan,
172 Direct3D,
174 #[cfg(feature = "unstable-wgpu-27")]
175 WGPU27(wgpu_27::api::WGPUConfiguration),
177 #[cfg(feature = "unstable-wgpu-28")]
178 WGPU28(wgpu_28::api::WGPUConfiguration),
180}
181
182impl TryFrom<&RequestedGraphicsAPI> for RequestedOpenGLVersion {
183 type Error = PlatformError;
184
185 fn try_from(requested_graphics_api: &RequestedGraphicsAPI) -> Result<Self, Self::Error> {
186 match requested_graphics_api {
187 RequestedGraphicsAPI::OpenGL(requested_open_glversion) => {
188 Ok(requested_open_glversion.clone())
189 }
190 RequestedGraphicsAPI::Metal => {
191 Err("Metal rendering is not supported with an OpenGL renderer".into())
192 }
193 RequestedGraphicsAPI::Vulkan => {
194 Err("Vulkan rendering is not supported with an OpenGL renderer".into())
195 }
196 RequestedGraphicsAPI::Direct3D => {
197 Err("Direct3D rendering is not supported with an OpenGL renderer".into())
198 }
199 #[cfg(feature = "unstable-wgpu-27")]
200 RequestedGraphicsAPI::WGPU27(..) => {
201 Err("WGPU 27.x rendering is not supported with an OpenGL renderer".into())
202 }
203 #[cfg(feature = "unstable-wgpu-28")]
204 RequestedGraphicsAPI::WGPU28(..) => {
205 Err("WGPU 28.x rendering is not supported with an OpenGL renderer".into())
206 }
207 }
208 }
209}
210
211impl From<RequestedOpenGLVersion> for RequestedGraphicsAPI {
212 fn from(version: RequestedOpenGLVersion) -> Self {
213 Self::OpenGL(version)
214 }
215}
216
217#[cfg(feature = "unstable-wgpu-27")]
220pub fn create_graphics_api_wgpu_27(
221 instance: wgpu_27::wgpu::Instance,
222 device: wgpu_27::wgpu::Device,
223 queue: wgpu_27::wgpu::Queue,
224) -> crate::api::GraphicsAPI<'static> {
225 crate::api::GraphicsAPI::WGPU27 { instance, device, queue }
226}
227
228#[cfg(feature = "unstable-wgpu-28")]
231pub fn create_graphics_api_wgpu_28(
232 instance: wgpu_28::wgpu::Instance,
233 device: wgpu_28::wgpu::Device,
234 queue: wgpu_28::wgpu::Queue,
235) -> crate::api::GraphicsAPI<'static> {
236 crate::api::GraphicsAPI::WGPU28 { instance, device, queue }
237}
238
239#[cfg(feature = "ffi")]
241pub mod ffi {
242 #![allow(unsafe_code)]
243
244 #[cfg(cbindgen)]
246 #[repr(C)]
247 struct Rect {
248 x: f32,
249 y: f32,
250 width: f32,
251 height: f32,
252 }
253
254 #[cfg(cbindgen)]
256 #[repr(C)]
257 struct IntRect {
258 x: i32,
259 y: i32,
260 width: i32,
261 height: i32,
262 }
263
264 #[cfg(cbindgen)]
266 #[repr(C)]
267 struct Point {
268 x: f32,
269 y: f32,
270 }
271
272 #[cfg(cbindgen)]
274 #[repr(C)]
275 struct Box2D<T, U> {
276 min: euclid::Point2D<T>,
277 max: euclid::Point2D<T>,
278 _unit: std::marker::PhantomData<U>,
279 }
280
281 #[cfg(feature = "std")]
282 pub use super::path::ffi::*;
283
284 pub fn physical_size_from_api(
288 size: crate::api::PhysicalSize,
289 ) -> crate::graphics::euclid::default::Size2D<u32> {
290 size.to_euclid()
291 }
292
293 pub fn physical_position_from_api(
297 position: crate::api::PhysicalPosition,
298 ) -> crate::graphics::euclid::default::Point2D<i32> {
299 position.to_euclid()
300 }
301
302 pub fn physical_position_to_api(
305 position: crate::graphics::euclid::default::Point2D<i32>,
306 ) -> crate::api::PhysicalPosition {
307 crate::api::PhysicalPosition::from_euclid(position)
308 }
309}