ul_next/
config.rs

1//! The configuration of the [`Renderer`](crate::renderer::Renderer) struct.
2
3use std::sync::Arc;
4
5use crate::Library;
6
7/// The winding order for front-facing triangles. (Only used when the GPU renderer is used)
8pub enum FaceWinding {
9    /// Clockwise Winding (Direct3D, etc.)
10    Clockwise = ul_sys::ULFaceWinding_kFaceWinding_Clockwise as isize,
11    /// Counter-Clockwise Winding (OpenGL, etc.)
12    CounterClockwise = ul_sys::ULFaceWinding_kFaceWinding_CounterClockwise as isize,
13}
14
15/// The font hinting algorithm.
16pub enum FontHinting {
17    /// Lighter hinting algorithm-- glyphs are slightly fuzzier but better resemble their original
18    /// shape. This is achieved by snapping glyphs to the pixel grid only vertically which better
19    /// preserves inter-glyph spacing.
20    Smooth = ul_sys::ULFontHinting_kFontHinting_Smooth as isize,
21    /// Default hinting algorithm-- offers a good balance between sharpness and shape at smaller font
22    /// sizes.
23    Normal = ul_sys::ULFontHinting_kFontHinting_Normal as isize,
24    /// Strongest hinting algorithm-- outputs only black/white glyphs. The result is usually
25    /// unpleasant if the underlying TTF does not contain hints for this type of rendering.
26    Monochrome = ul_sys::ULFontHinting_kFontHinting_Monochrome as isize,
27}
28
29/// Configuration settings for Ultralight renderer
30///
31/// This is intended to be implemented by users when creating the Renderer in
32/// [`Renderer::create`](crate::renderer::Renderer::create).
33pub struct Config {
34    lib: Arc<Library>,
35    internal: ul_sys::ULConfig,
36}
37
38impl Config {
39    /// Starts the building process for the [`Config`] struct. returns a builder
40    /// which can be used to configure the settings.
41    pub fn start() -> ConfigBuilder {
42        ConfigBuilder::default()
43    }
44
45    /// Returns the underlying [`ul_sys::ULConfig`] struct, to be used locally for
46    /// calling the underlying C API.
47    pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULConfig {
48        self.internal
49    }
50
51    /// Returns the library associated with this config.
52    pub(crate) fn lib(&self) -> &Arc<Library> {
53        &self.lib
54    }
55}
56
57impl Drop for Config {
58    fn drop(&mut self) {
59        unsafe {
60            self.lib.ultralight().ulDestroyConfig(self.internal);
61        }
62    }
63}
64
65/// Builder for the [`Config`] struct.
66#[derive(Default)]
67pub struct ConfigBuilder {
68    cache_path: Option<String>,
69    resource_path_prefix: Option<String>,
70    face_winding: Option<FaceWinding>,
71    font_hinting: Option<FontHinting>,
72    font_gamma: Option<f64>,
73    user_stylesheet: Option<String>,
74    force_repaint: Option<bool>,
75    animation_timer_delay: Option<f64>,
76    scroll_timer_delay: Option<f64>,
77    recycle_delay: Option<f64>,
78    memory_cache_size: Option<u32>,
79    page_cache_size: Option<u32>,
80    override_ram_size: Option<u32>,
81    min_large_heap_size: Option<u32>,
82    min_small_heap_size: Option<u32>,
83    num_renderer_threads: Option<u32>,
84    max_update_time: Option<f64>,
85    bitmap_alignment: Option<u32>,
86}
87
88impl ConfigBuilder {
89    /// A writable OS file path to store persistent Session data in.
90    ///
91    /// This data may include cookies, cached network resources, indexed DB, etc.
92    ///
93    /// Files are only written to disk when using a persistent Session (see
94    /// [`Renderer::create_session`](crate::renderer::Renderer::create_session)).
95    pub fn cache_path(mut self, path: &str) -> Self {
96        self.cache_path = Some(path.to_string());
97        self
98    }
99
100    /// The relative path to the resources folder (loaded via the FileSystem API).
101    /// The library loads certain resources (SSL certs, ICU data, etc.)
102    /// from the FileSystem API during runtime (eg, `file:///resources/cacert.pem`).
103    ///
104    /// You can customize the relative file path to the resources folder by modifying this setting.
105    ///
106    /// (Default = “resources/”)
107    pub fn resource_path_prefix(mut self, path: &str) -> Self {
108        self.resource_path_prefix = Some(path.to_string());
109        self
110    }
111
112    /// The winding order for front-facing triangles. (See [`FaceWinding`])
113    ///
114    /// Note: This is only used when the GPU renderer is enabled.
115    pub fn face_winding(mut self, winding: FaceWinding) -> Self {
116        self.face_winding = Some(winding);
117        self
118    }
119
120    /// The hinting algorithm to use when rendering fonts. (See [`FontHinting`])
121    pub fn font_hinting(mut self, hinting: FontHinting) -> Self {
122        self.font_hinting = Some(hinting);
123        self
124    }
125
126    /// The gamma to use when compositing font glyphs, change this value to
127    /// adjust contrast (Adobe and Apple prefer 1.8, others may prefer 2.2).
128    pub fn font_gamma(mut self, gamma: f64) -> Self {
129        self.font_gamma = Some(gamma);
130        self
131    }
132
133    /// Default user stylesheet. You should set this to your own custom CSS
134    /// string to define default styles for various DOM elements, scrollbars,
135    /// and platform input widgets.
136    pub fn user_stylesheet(mut self, path: &str) -> Self {
137        self.user_stylesheet = Some(path.to_string());
138        self
139    }
140
141    /// Whether or not we should continuously repaint any Views or compositor
142    /// layers, regardless if they are dirty or not. This is mainly used to
143    /// diagnose painting/shader issues.
144    ///
145    /// (Default = false)
146    pub fn force_repaint(mut self, force: bool) -> Self {
147        self.force_repaint = Some(force);
148        self
149    }
150
151    /// When a CSS animation is active, the amount of time (in seconds) to wait
152    /// before triggering another repaint.
153    ///
154    /// (Default = 1.0 / 60.0)
155    pub fn animation_timer_delay(mut self, delay: f64) -> Self {
156        self.animation_timer_delay = Some(delay);
157        self
158    }
159
160    /// When a smooth scroll animation is active, the amount of time (in seconds)
161    /// to wait before triggering another repaint.
162    ///
163    /// (Default = 1.0 / 60.0)
164    pub fn scroll_timer_delay(mut self, delay: f64) -> Self {
165        self.scroll_timer_delay = Some(delay);
166        self
167    }
168
169    /// The amount of time (in seconds) to wait before running the recycler
170    /// (will attempt to return excess memory back to the system).
171    pub fn recycle_delay(mut self, delay: f64) -> Self {
172        self.recycle_delay = Some(delay);
173        self
174    }
175
176    /// The size of WebCore's memory cache in bytes.
177    ///
178    /// You should increase this if you anticipate handling pages with large
179    /// resources, Safari typically uses 128+ MiB for its cache.
180    ///
181    /// `size` is in bytes.
182    ///
183    /// (Default = 64 * 1024 * 1024)
184    pub fn memory_cache_size(mut self, size: u32) -> Self {
185        self.memory_cache_size = Some(size);
186        self
187    }
188
189    /// Number of pages to keep in the cache. Defaults to 0 (none).
190    ///
191    /// Safari typically caches about 5 pages and maintains an on-disk cache
192    /// to support typical web-browsing activities. If you increase this,
193    /// you should probably increase the memory cache size as well.
194    pub fn page_cache_size(mut self, size: u32) -> Self {
195        self.page_cache_size = Some(size);
196        self
197    }
198
199    /// The system's physical RAM size in bytes.
200    ///
201    /// JavaScriptCore tries to detect the system's physical RAM size to set
202    /// reasonable allocation limits. Set this to anything other than 0 to
203    /// override the detected value. `size` is in bytes.
204    ///
205    /// This can be used to force JavaScriptCore to be more conservative
206    /// with its allocation strategy (at the cost of some performance).
207    pub fn override_ram_size(mut self, size: u32) -> Self {
208        self.override_ram_size = Some(size);
209        self
210    }
211
212    /// The minimum size of large VM heaps in JavaScriptCore. Set this to a lower value to make these
213    /// heaps start with a smaller initial value.
214    ///
215    /// `size` is in bytes.
216    ///
217    /// (Default = 32 * 1024 * 1024)
218    pub fn min_large_heap_size(mut self, size: u32) -> Self {
219        self.min_large_heap_size = Some(size);
220        self
221    }
222
223    /// The minimum size of small VM heaps in JavaScriptCore. Set this to a lower value to make these
224    /// heaps start with a smaller initial value.
225    ///
226    /// `size` is in bytes.
227    ///
228    /// (Default = 1 * 1024 * 1024)
229    pub fn min_small_heap_size(mut self, size: u32) -> Self {
230        self.min_small_heap_size = Some(size);
231        self
232    }
233
234    /// The number of threads to use in the Renderer (for parallel painting on the CPU, etc.).
235    ///
236    /// You can set this to a certain number to limit the number of threads to spawn.
237    ///
238    /// If this value is 0 (the default), the number of threads will be determined at runtime
239    /// using the following formula:
240    ///
241    /// `max(PhysicalProcessorCount() - 1, 1)`
242    pub fn num_renderer_threads(mut self, threads: u32) -> Self {
243        self.num_renderer_threads = Some(threads);
244        self
245    }
246
247    /// The max amount of time (in seconds) to allow repeating timers to run during each call to
248    /// [`Renderer::update`](crate::renderer::Renderer::update).
249    /// The library will attempt to throttle timers and/or reschedule work if this
250    /// time budget is exceeded.
251    ///
252    /// (Default = 1.0 / 200.0)
253    pub fn max_update_time(mut self, time: f64) -> Self {
254        self.max_update_time = Some(time);
255        self
256    }
257
258    /// **Note that this is currently is useless in this library**
259    /// **as we can't get the bitmap from [`Surface`](crate::surface::Surface)**
260    /// **when using CPU rendering**.
261    ///
262    /// The alignment (in bytes) of the BitmapSurface when using the CPU renderer.
263    ///
264    /// The underlying bitmap associated with each BitmapSurface will have
265    /// `row_bytes` padded to reach this `alignment`.
266    ///
267    /// Aligning the bitmap helps improve performance when using the CPU renderer/
268    /// Determining the proper value to use depends on the CPU architecture and
269    /// max SIMD instruction set used.
270    ///
271    /// We generally target the 128-bit SSE2 instruction set across most
272    /// PC platforms so '16' is a default and safe value to use.
273    ///
274    /// You can set this to '0' to perform no padding
275    /// (row_bytes will always be `width * 4`) at a slight cost to performance.
276    pub fn bitmap_alignment(mut self, alignment: u32) -> Self {
277        self.bitmap_alignment = Some(alignment);
278        self
279    }
280
281    /// Builds the [`Config`] struct using the settings configured in this builder.
282    ///
283    /// Returns [`None`] if failed to create [`Config`].
284    pub fn build(self, lib: Arc<Library>) -> Option<Config> {
285        let internal = unsafe { lib.ultralight().ulCreateConfig() };
286
287        if internal.is_null() {
288            return None;
289        }
290
291        set_config_str!(
292            internal,
293            self.cache_path,
294            lib.ultralight().ulConfigSetCachePath
295        );
296        set_config_str!(
297            internal,
298            self.resource_path_prefix,
299            lib.ultralight().ulConfigSetResourcePathPrefix
300        );
301        set_config!(
302            internal,
303            self.face_winding.map(|x| x as u32),
304            lib.ultralight().ulConfigSetFaceWinding
305        );
306        set_config!(
307            internal,
308            self.font_hinting.map(|x| x as u32),
309            lib.ultralight().ulConfigSetFontHinting
310        );
311        set_config!(
312            internal,
313            self.font_gamma,
314            lib.ultralight().ulConfigSetFontGamma
315        );
316        set_config_str!(
317            internal,
318            self.user_stylesheet,
319            lib.ultralight().ulConfigSetUserStylesheet
320        );
321        set_config!(
322            internal,
323            self.force_repaint,
324            lib.ultralight().ulConfigSetForceRepaint
325        );
326        set_config!(
327            internal,
328            self.animation_timer_delay,
329            lib.ultralight().ulConfigSetAnimationTimerDelay
330        );
331        set_config!(
332            internal,
333            self.scroll_timer_delay,
334            lib.ultralight().ulConfigSetScrollTimerDelay
335        );
336        set_config!(
337            internal,
338            self.recycle_delay,
339            lib.ultralight().ulConfigSetRecycleDelay
340        );
341        set_config!(
342            internal,
343            self.memory_cache_size,
344            lib.ultralight().ulConfigSetMemoryCacheSize
345        );
346        set_config!(
347            internal,
348            self.page_cache_size,
349            lib.ultralight().ulConfigSetPageCacheSize
350        );
351        set_config!(
352            internal,
353            self.override_ram_size,
354            lib.ultralight().ulConfigSetOverrideRAMSize
355        );
356        set_config!(
357            internal,
358            self.min_large_heap_size,
359            lib.ultralight().ulConfigSetMinLargeHeapSize
360        );
361        set_config!(
362            internal,
363            self.min_small_heap_size,
364            lib.ultralight().ulConfigSetMinSmallHeapSize
365        );
366        set_config!(
367            internal,
368            self.num_renderer_threads,
369            lib.ultralight().ulConfigSetNumRendererThreads
370        );
371        set_config!(
372            internal,
373            self.max_update_time,
374            lib.ultralight().ulConfigSetMaxUpdateTime
375        );
376        set_config!(
377            internal,
378            self.bitmap_alignment,
379            lib.ultralight().ulConfigSetBitmapAlignment
380        );
381
382        Some(Config { lib, internal })
383    }
384}