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