slint/internal/core/lib.rs
Tasuku Suzuki 224a06af57
Gallery Example: Add i18n and dynamic font loading for WASM (#9762)
- Bundle translations for WASM/Android only (not for native builds)
- Load Noto Sans CJK fonts dynamically from GitHub at runtime
- Implement register_font_from_memory() with Result<FontHandle, RegisterFontError>
- Make API automatically available with std feature (no explicit feature flag needed)
- Export load_font_from_bytes() for WASM font loading from JavaScript
- Change from wasm_bindgen(start) to explicit main() call for better control

Fonts are loaded before app initialization to ensure proper CJK text
rendering across all major browsers without bundling font files.

Native builds load translations from lang/ directory at runtime.
WASM/Android builds bundle translations at compile time and detect
browser/system language automatically.

API is now available when std feature is enabled, since we always
have fontique with std. No need for experimental-register-font feature.
2025-11-17 14:00:39 +01:00

186 lines
5.1 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
// cSpell: ignore sharedvector textlayout
#![doc = include_str!("README.md")]
#![doc(html_logo_url = "https://slint.dev/logo/slint-logo-square-light.svg")]
#![deny(unsafe_code)]
#![no_std]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[cfg(all(not(feature = "std"), feature = "unsafe-single-threaded"))]
pub(crate) mod unsafe_single_threaded;
#[cfg(all(not(feature = "std"), not(feature = "unsafe-single-threaded")))]
compile_error!(
"At least one of the following feature need to be enabled: `std` or `unsafe-single-threaded`"
);
use crate::items::OperatingSystemType;
#[cfg(all(not(feature = "std"), feature = "unsafe-single-threaded"))]
use crate::unsafe_single_threaded::thread_local;
#[cfg(feature = "std")]
use std::thread_local;
pub mod accessibility;
pub mod animations;
pub mod api;
pub mod callbacks;
pub mod component_factory;
pub mod context;
pub mod date_time;
pub mod future;
pub mod graphics;
pub mod input;
pub mod item_focus;
pub mod item_rendering;
pub mod item_tree;
pub mod items;
pub mod layout;
pub mod lengths;
pub mod menus;
pub mod model;
pub mod partial_renderer;
pub mod platform;
pub mod properties;
pub mod renderer;
#[cfg(feature = "rtti")]
pub mod rtti;
pub mod sharedvector;
pub mod slice;
#[cfg(feature = "software-renderer")]
pub mod software_renderer;
pub mod string;
pub mod tests;
pub mod textlayout;
pub mod timers;
pub mod translations;
pub mod window;
#[doc(inline)]
pub use string::SharedString;
/// Register a font from memory.
#[cfg(feature = "std")]
pub use i_slint_common::sharedfontique::register_font_from_memory;
/// Handle to a registered font.
#[cfg(feature = "std")]
pub use i_slint_common::sharedfontique::FontHandle;
/// Error type for font registration failures.
#[cfg(feature = "std")]
pub use i_slint_common::sharedfontique::RegisterFontError;
#[doc(inline)]
pub use sharedvector::SharedVector;
#[doc(inline)]
pub use graphics::{ImageInner, StaticTextures};
#[doc(inline)]
pub use properties::Property;
#[doc(inline)]
pub use callbacks::Callback;
#[doc(inline)]
pub use graphics::Color;
#[doc(inline)]
pub use graphics::Brush;
#[doc(inline)]
pub use graphics::RgbaColor;
#[cfg(feature = "std")]
#[doc(inline)]
pub use graphics::PathData;
#[doc(inline)]
pub use graphics::BorderRadius;
pub use context::{SlintContext, with_global_context};
#[cfg(not(slint_int_coord))]
pub type Coord = f32;
#[cfg(slint_int_coord)]
pub type Coord = i32;
/// This type is not exported from the public API crate, so function having this
/// parameter cannot be called from the public API without naming it
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct InternalToken;
#[cfg(feature = "std")]
thread_local!(
/// Permit testing code to force an OS type
pub static OPERATING_SYSTEM_OVERRIDE: core::cell::Cell<Option<OperatingSystemType>> =
Default::default();
);
#[cfg(not(target_family = "wasm"))]
pub fn detect_operating_system() -> OperatingSystemType {
#[cfg(feature = "std")]
if let Some(os_override) = OPERATING_SYSTEM_OVERRIDE.with(|os_override| os_override.get()) {
return os_override;
}
if cfg!(target_os = "android") {
OperatingSystemType::Android
} else if cfg!(target_os = "ios") {
OperatingSystemType::Ios
} else if cfg!(target_os = "macos") {
OperatingSystemType::Macos
} else if cfg!(target_os = "windows") {
OperatingSystemType::Windows
} else if cfg!(target_os = "linux") {
OperatingSystemType::Linux
} else {
OperatingSystemType::Other
}
}
#[cfg(target_family = "wasm")]
pub fn detect_operating_system() -> OperatingSystemType {
if let Some(os_override) = OPERATING_SYSTEM_OVERRIDE.with(|os_override| os_override.get()) {
return os_override;
}
let mut user_agent =
web_sys::window().and_then(|w| w.navigator().user_agent().ok()).unwrap_or_default();
user_agent.make_ascii_lowercase();
let mut platform =
web_sys::window().and_then(|w| w.navigator().platform().ok()).unwrap_or_default();
platform.make_ascii_lowercase();
if user_agent.contains("ipad") || user_agent.contains("iphone") {
OperatingSystemType::Ios
} else if user_agent.contains("android") {
OperatingSystemType::Android
} else if platform.starts_with("mac") {
OperatingSystemType::Macos
} else if platform.starts_with("win") {
OperatingSystemType::Windows
} else if platform.starts_with("linux") {
OperatingSystemType::Linux
} else {
OperatingSystemType::Other
}
}
/// Returns true if the current platform is an Apple platform (macOS, iOS, iPadOS)
pub fn is_apple_platform() -> bool {
matches!(detect_operating_system(), OperatingSystemType::Macos | OperatingSystemType::Ios)
}
#[cfg_attr(not(feature = "std"), allow(unused))]
pub fn open_url(url: &str) {
#[cfg(feature = "std")]
if let Err(err) = webbrowser::open(url) {
debug_log!("Error opening url {}: {}", url, err);
}
}