1
//! Layout crate for the Azul GUI framework.
2
//!
3
//! Provides the layout solver (`solver3`), text shaping (`text3`), font
4
//! management (`font`), hit testing, page fragmentation, and widget support.
5
//! Integrates with `azul-core` for DOM types and `azul-css` for style
6
//! properties.
7

            
8
#![doc(
9
    html_logo_url = "https://raw.githubusercontent.com/maps4print/azul/master/assets/images/azul_logo_full_min.svg.png",
10
    html_favicon_url = "https://raw.githubusercontent.com/maps4print/azul/master/assets/images/favicon.ico"
11
)]
12
// Lint policy: deny correctness/safety issues, warn on style
13
#![deny(unused_must_use)]
14
#![warn(clippy::all)]
15
#![allow(
16
    clippy::non_canonical_partial_ord_impl,
17
    clippy::legacy_numeric_constants,
18
    clippy::should_implement_trait,
19
    clippy::result_unit_err,
20
    clippy::ptr_as_ptr,
21
    clippy::too_many_arguments,
22
    clippy::type_complexity,
23
    unused_imports,
24
    unused_variables,
25
    unused_mut,
26
    dead_code,
27
    unused_parens,
28
    unused_doc_comments,                   // doc comments before macro invocations
29
    unused_assignments,                    // layout solver incremental updates
30
    unused_labels,
31
    dropping_references,                   // intentional scope markers in layout solver
32
    private_interfaces,                    // internal solver types exposed for testing
33
    function_casts_as_integer,             // widget callback pointer identity
34
    improper_ctypes_definitions,           // node_graph extern fn returns ()
35
    mismatched_lifetime_syntaxes,
36
    unreachable_patterns,                  // exhaustive match in generated property code
37
    unexpected_cfgs,
38
    deprecated,                            // image crate tiff encoder
39
)]
40

            
41
#[macro_use]
42
extern crate alloc;
43
extern crate core;
44

            
45
/// Font traits available regardless of text layout feature.
46
pub mod font_traits;
47
/// Optional probe instrumentation. With the `probe` feature off this
48
/// is a tiny module of no-op stubs and pays zero cost.
49
pub mod probe;
50
/// Image decoding and encoding (wraps the `image` crate).
51
#[cfg(feature = "image_decoding")]
52
pub mod image;
53
/// Scroll, hover, clipboard, cursor, and focus managers.
54
#[cfg(feature = "text_layout")]
55
pub mod managers;
56
/// CSS layout solver: block, inline, flex, grid, and table formatting.
57
#[cfg(feature = "text_layout")]
58
pub mod solver3;
59

            
60
/// C-compatible string formatting via `strfmt`.
61
#[cfg(feature = "strfmt")]
62
pub mod fmt;
63
#[cfg(feature = "strfmt")]
64
pub use fmt::{FmtArg, FmtArgVec, FmtArgVecDestructor, FmtValue, fmt_string};
65

            
66
/// Built-in widgets: button, text input, tabs, tree view, node graph, etc.
67
#[cfg(feature = "widgets")]
68
pub mod widgets;
69

            
70
/// Desktop platform helpers (file dialogs, notifications).
71
#[cfg(feature = "extra")]
72
pub mod desktop;
73
/// Color parsing, XML DOM construction, and misc utilities.
74
#[cfg(feature = "extra")]
75
pub mod extra;
76

            
77
/// ICU internationalization: date/time formatting, plurals, list formatting.
78
#[cfg(any(
79
    feature = "icu",
80
    all(target_os = "macos", feature = "icu_macos"),
81
    all(target_os = "windows", feature = "icu_windows"),
82
))]
83
pub mod icu;
84
#[cfg(any(
85
    feature = "icu",
86
    all(target_os = "macos", feature = "icu_macos"),
87
    all(target_os = "windows", feature = "icu_windows"),
88
))]
89
pub use icu::{
90
    DateTimeFieldSet, FormatLength, IcuDate, IcuDateTime, IcuError,
91
    IcuLocalizer, IcuLocalizerHandle, IcuResult, IcuStringVec, IcuTime,
92
    LayoutCallbackInfoIcuExt, ListType, PluralCategory,
93
};
94

            
95
/// Project Fluent localization: message bundles, argument formatting, ZIP I/O.
96
#[cfg(feature = "fluent")]
97
pub mod fluent;
98
#[cfg(feature = "fluent")]
99
pub use fluent::{
100
    check_fluent_syntax, check_fluent_syntax_bytes, create_fluent_zip,
101
    create_fluent_zip_from_strings, export_to_zip, FluentError,
102
    FluentLanguageInfo, FluentLanguageInfoVec,
103
    FluentLocalizerHandle, FluentResult, FluentSyntaxCheckResult,
104
    FluentSyntaxError, FluentZipLoadResult, LayoutCallbackInfoFluentExt,
105
};
106

            
107
/// URL parsing (RFC 3986 compliant). Pure-Rust, always present (no TLS deps).
108
pub mod url;
109
pub use url::{Url, UrlParseError, ResultUrlUrlParseError};
110

            
111
/// File system operations (C-compatible wrappers for `std::fs`).
112
pub mod file;
113
pub use file::{
114
    dir_create, dir_create_all, dir_list, dir_delete, dir_delete_all,
115
    file_copy, path_exists, file_metadata, file_read, file_delete, file_rename, file_write,
116
    path_is_dir, path_is_file, path_join, temp_dir,
117
    DirEntry, DirEntryVec, DirEntryVecDestructor, DirEntryVecDestructorType,
118
    FileError, FileErrorKind, FileMetadata, FilePath, OptionFilePath,
119
};
120

            
121
/// HTTP client: GET/POST requests with pure-Rust TLS.
122
/// API surface always present (stub when off); ureq/rustls only pulled in with `http`.
123
pub mod http;
124
pub use http::{
125
    download_bytes, download_bytes_with_config, http_get,
126
    http_get_with_config, is_url_reachable, HttpError, HttpHeader,
127
    HttpRequestConfig, HttpResponse, HttpResponseTooLargeError, HttpResult,
128
    HttpStatusError,
129
};
130

            
131
/// JSON parsing and serialization for the C API.
132
#[cfg(feature = "json")]
133
pub mod json;
134
#[cfg(feature = "json")]
135
pub use json::{
136
    json_parse, json_parse_bytes, json_stringify, json_stringify_pretty,
137
    Json, JsonInternal, JsonKeyValue, JsonKeyValueVec, JsonKeyValueVecDestructor, JsonKeyValueVecDestructorType,
138
    JsonParseError, JsonType, JsonVec,
139
    ResultJsonJsonParseError, OptionJson, OptionJsonVec, OptionJsonKeyValueVec,
140
};
141

            
142
/// ZIP file creation, extraction, and listing.
143
#[cfg(feature = "zip_support")]
144
pub mod zip;
145
#[cfg(feature = "zip_support")]
146
pub use zip::{
147
    zip_create, zip_create_from_files, zip_extract_all, zip_list_contents,
148
    ZipFile, ZipFileEntry, ZipFileEntryVec, ZipPathEntry, ZipPathEntryVec,
149
    ZipReadConfig, ZipWriteConfig, ZipReadError, ZipWriteError,
150
};
151

            
152
/// Icon provider: resolves icons from Material Icons font, images, or ZIP packs.
153
pub mod icon;
154
pub use icon::{
155
    // Resolver
156
    default_icon_resolver,
157
    // Data types for RefAny
158
    ImageIconData, FontIconData,
159
    // Helpers
160
    create_default_icon_provider,
161
    register_material_icons,
162
    register_embedded_material_icons,
163
};
164
// Re-export core icon types
165
pub use azul_core::icon::{
166
    IconProviderHandle, IconResolverCallbackType,
167
    resolve_icons_in_styled_dom, OptionIconProviderHandle,
168
};
169

            
170
/// Callback handling for layout events (invocation, result processing).
171
#[cfg(feature = "text_layout")]
172
pub mod callbacks;
173
/// CPU-based software rendering (no GPU required).
174
#[cfg(feature = "cpurender")]
175
pub mod cpurender;
176
/// Glyph path and cell cache for CPU text rendering.
177
#[cfg(feature = "cpurender")]
178
pub mod glyph_cache;
179
/// Default keyboard actions (copy, paste, select-all, undo, etc.).
180
#[cfg(feature = "text_layout")]
181
pub mod default_actions;
182
/// Event determination: maps raw input to DOM node callbacks.
183
#[cfg(feature = "text_layout")]
184
pub mod event_determination;
185
/// Font parsing, metrics extraction, and subsetting.
186
#[cfg(feature = "text_layout")]
187
pub mod font;
188

            
189
/// Headless backend for CPU-only rendering without a display server.
190
/// Used with `AZUL_HEADLESS=1` for E2E testing, CI, and screenshot capture.
191
#[cfg(feature = "text_layout")]
192
pub mod headless;
193
// Re-export allsorts types needed by printpdf
194
#[cfg(feature = "text_layout")]
195
pub use allsorts::subset::CmapTarget;
196
#[cfg(feature = "text_layout")]
197
pub use font::parsed::{
198
    FontParseWarning, FontParseWarningSeverity, FontType, OwnedGlyph, ParsedFont, PdfFontMetrics,
199
    SubsetFont,
200
};
201
// Re-export hyphenation for external crates (like printpdf)
202
#[cfg(feature = "text_layout_hyphenation")]
203
pub use hyphenation;
204
/// CSS fragmentation engine for paged media (page/column breaks).
205
pub mod fragmentation;
206
/// Hit-testing: maps screen coordinates to DOM nodes.
207
#[cfg(feature = "text_layout")]
208
pub mod hit_test;
209
/// Paged media layout engine (infinite canvas with physical spacers).
210
pub mod paged;
211
/// Text shaping, line breaking (Knuth-Plass), and inline formatting.
212
#[cfg(feature = "text_layout")]
213
pub mod text3;
214
/// Thread callback wrappers for the C API.
215
#[cfg(feature = "text_layout")]
216
pub mod thread;
217
/// Timer callback wrappers for the C API.
218
#[cfg(feature = "text_layout")]
219
pub mod timer;
220
/// Scroll physics timer for momentum-based smooth scrolling.
221
#[cfg(feature = "text_layout")]
222
pub mod scroll_timer;
223
/// Window layout management: relayout, event processing, state sync.
224
#[cfg(feature = "text_layout")]
225
pub mod window;
226
/// Window state types (keyboard, mouse, DPI, focus).
227
#[cfg(feature = "text_layout")]
228
pub mod window_state;
229
/// XML and XHTML parsing for declarative UI definitions.
230
#[cfg(feature = "xml")]
231
pub mod xml;
232

            
233
// Export the main layout function and window management
234
pub use fragmentation::{
235
    BoxBreakBehavior, BreakDecision, FragmentationDefaults, FragmentationLayoutContext,
236
    KeepTogetherPriority, PageCounter, PageFragment, PageMargins, PageNumberStyle, PageSlot,
237
    PageSlotContent, PageSlotPosition, PageTemplate,
238
};
239
#[cfg(feature = "text_layout")]
240
pub use hit_test::{CursorTypeHitTest, FullHitTest};
241
pub use paged::FragmentationState;
242
#[cfg(feature = "text_layout")]
243
pub use solver3::cache::LayoutCache as Solver3LayoutCache;
244
#[cfg(feature = "text_layout")]
245
pub use solver3::display_list::DisplayList as DisplayList3;
246
#[cfg(feature = "text_layout")]
247
pub use solver3::layout_document;
248
#[cfg(feature = "text_layout")]
249
pub use solver3::paged_layout::layout_document_paged;
250
#[cfg(feature = "text_layout")]
251
pub use solver3::{LayoutContext, LayoutError, Result as LayoutResult3};
252
#[cfg(feature = "text_layout")]
253
pub use text3::cache::{FontContext, FontManager, TextShapingCache};
254
/// Backwards-compat alias for the old `TextLayoutCache` name.
255
/// Will be dropped at the next API revision; new code should use
256
/// [`TextShapingCache`] directly.
257
#[cfg(feature = "text_layout")]
258
pub use text3::cache::TextShapingCache as TextLayoutCache;
259
#[cfg(feature = "font_async_registry")]
260
pub use rust_fontconfig::registry::FcFontRegistry;
261
#[cfg(feature = "text_layout")]
262
pub use window::{CursorBlinkTimerAction, LayoutWindow, ScrollbarDragState, TooltipTimerAction};
263
#[cfg(feature = "text_layout")]
264
pub use managers::text_input::{PendingTextEdit, OptionPendingTextEdit};
265

            
266
#[cfg(feature = "text_layout")]
267
/// Parses raw font bytes into a [`FontRef`](azul_css::props::basic::FontRef)
268
/// suitable for use in the layout system.
269
pub fn parse_font_fn(
270
    source: azul_core::resources::LoadedFontSource,
271
) -> Option<azul_css::props::basic::FontRef> {
272
    use crate::font::parsed::ParsedFont;
273

            
274
    ParsedFont::from_bytes(
275
        source.data.as_ref(),
276
        source.index as usize,
277
        &mut Vec::new(), // Ignore warnings for now
278
    )
279
    .map(parsed_font_to_font_ref)
280
}
281

            
282
#[cfg(feature = "text_layout")]
283
/// Wraps a [`ParsedFont`] in a [`FontRef`](azul_css::props::basic::FontRef),
284
/// transferring ownership to the returned handle.
285
21175
pub fn parsed_font_to_font_ref(
286
21175
    parsed_font: crate::font::parsed::ParsedFont,
287
21175
) -> azul_css::props::basic::FontRef {
288
    use core::ffi::c_void;
289

            
290
21175
    extern "C" fn parsed_font_destructor(ptr: *mut c_void) {
291
21175
        unsafe {
292
21175
            let _ = Box::from_raw(ptr as *mut crate::font::parsed::ParsedFont);
293
21175
        }
294
21175
    }
295

            
296
21175
    let boxed = Box::new(parsed_font);
297
21175
    let raw_ptr = Box::into_raw(boxed) as *const c_void;
298
21175
    azul_css::props::basic::FontRef::new(raw_ptr, parsed_font_destructor)
299
21175
}
300

            
301
#[cfg(feature = "text_layout")]
302
/// Recovers a reference to the [`ParsedFont`] stored inside a [`FontRef`](azul_css::props::basic::FontRef).
303
///
304
/// # Safety contract
305
/// The `font_ref` must have been created by [`parsed_font_to_font_ref`],
306
/// so that `font_ref.parsed` points to a valid `ParsedFont`.
307
105
pub fn font_ref_to_parsed_font(
308
105
    font_ref: &azul_css::props::basic::FontRef,
309
105
) -> &crate::font::parsed::ParsedFont {
310
    // SAFETY: `font_ref.parsed` was created by `parsed_font_to_font_ref`
311
    // via `Box::into_raw`, so it points to a valid, aligned `ParsedFont`.
312
105
    unsafe { &*(font_ref.parsed as *const crate::font::parsed::ParsedFont) }
313
105
}