Stabilize the sdf-fonts feature

Enable the SDF feature by default in our compiler binaries

(Still disabled by default for other users because it takes up compile
time for something they probably don't need)
This commit is contained in:
Olivier Goffart 2025-02-19 21:24:53 +01:00 committed by GitHub
parent 28f83c64e2
commit 1e814c9bdc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 68 additions and 15 deletions

View file

@ -73,7 +73,7 @@ jobs:
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: CMakeLists.txt
cmakeAppendedArgs: "-DCMAKE_BUILD_TYPE=RelWithDebInfo ${{ env.SLINT_BINARY_FEATURES }} ${{ inputs.extra_cmake_flags }}"
cmakeAppendedArgs: "-DCMAKE_BUILD_TYPE=RelWithDebInfo ${{ env.SLINT_BINARY_FEATURES }} ${{ inputs.extra_cmake_flags }} -DSLINT_FEATURE_SDF_FONTS=ON"
buildDirectory: ${{ runner.workspace }}/cppbuild
buildWithCMakeArgs: "--config Release"
- name: cpack
@ -253,7 +253,7 @@ jobs:
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: CMakeLists.txt
cmakeAppendedArgs: "-GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSLINT_BUILD_RUNTIME=OFF ${{ inputs.extra_cmake_flags }}"
cmakeAppendedArgs: "-GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSLINT_BUILD_RUNTIME=OFF ${{ inputs.extra_cmake_flags }} -DSLINT_FEATURE_SDF_FONTS=ON"
buildDirectory: ${{ runner.workspace }}/cppbuild
buildWithCMakeArgs: "--config Release"
- name: cpack

View file

@ -25,6 +25,8 @@ option(SLINT_FEATURE_COMPILER "Enable support for compiling .slint files to C++
add_feature_info(SLINT_FEATURE_COMPILER SLINT_FEATURE_COMPILER "Enable support for compiling .slint files to C++ ahead of time")
option(SLINT_BUILD_RUNTIME "Actually build the Slint runtime libraries (Disable that to only build the compiler)" ON)
add_feature_info(SLINT_BUILD_RUNTIME SLINT_BUILD_RUNTIME "Actually build the Slint runtime libraries (Disable that to only build the compiler)")
option(SLINT_FEATURE_SDF_FONTS "Enable support for pre-rendering fonts as Signed Distance Fields (for the software renderer)" OFF)
add_feature_info(SLINT_FEATURE_SDF_FONTS SLINT_FEATURE_SDF_FONTS "Enable support for pre-rendering fonts as Signed Distance Fields (for the software renderer)")
set(SLINT_COMPILER "" CACHE STRING "Path to the slint-compiler executable. When unset, it the compiler will be build as part of the build process. When set to 'download', the compiler will be downloaded from GitHub.")
set(SLINT_LIBRARY_CARGO_FLAGS "" CACHE STRING
@ -142,6 +144,9 @@ if(SLINT_FEATURE_COMPILER AND NOT SLINT_COMPILER)
ON
)
list(APPEND slint_compiler_features "software-renderer")
if (SLINT_FEATURE_SDF_FONTS)
list(APPEND slint_compiler_features "sdf-fonts")
endif()
# Enable jemalloc, except when cross-compiling. (#7463)
if(NOT CMAKE_CROSSCOMPILING)
list(APPEND slint_compiler_features "jemalloc")

View file

@ -5,7 +5,7 @@
set(DEFAULT_SLINT_EMBED_RESOURCES as-absolute-path CACHE STRING
"The default resource embedding option to pass to the Slint compiler")
set_property(CACHE DEFAULT_SLINT_EMBED_RESOURCES PROPERTY STRINGS
"as-absolute-path" "embed-files" "embed-for-software-renderer")
"as-absolute-path" "embed-files" "embed-for-software-renderer" "embed-for-software-renderer-and-sdf-fonts")
## This requires CMake 3.23 and does not work in 3.26 AFAICT.
# define_property(TARGET PROPERTY SLINT_EMBED_RESOURCES
# INITIALIZE_FROM_VARIABLE DEFAULT_SLINT_EMBED_RESOURCES)

View file

@ -44,6 +44,9 @@ Set the `SLINT_EMBED_RESOURCES` target property on your CMake target to one of t
* `embed-files`: The raw files are embedded in the application binary.
* `embed-for-software-renderer`: The files will be loaded by the Slint compiler, optimized for use with the software renderer and embedded in the application binary.
* `embed-for-software-renderer-with-sdf`: Same as `embed-for-software-renderer`, but use [Signed Distance Fields (SDF)](https://en.wikipedia.org/wiki/Signed_distance_function) to render fonts.
This produces smaller binaries, but may result in slightly inferior visual output and slower rendering.
(Requires the `SLINT_FEATURE_SDF_FONTS` feature to be enabled.)
* `as-absolute-path`: The paths of files are made absolute and will be used at run-time to load the resources from the file system. This is the default.
This target property is initialised from the global `DEFAULT_SLINT_EMBED_RESOURCES` cache variable. Set it to configure the default for all CMake targets.

View file

@ -19,6 +19,7 @@ path = "lib.rs"
[features]
default = []
sdf-fonts = ["i-slint-compiler/sdf-fonts"]
[dependencies]
i-slint-compiler = { workspace = true, features = ["default", "rust", "display-diagnostics", "software-renderer", "bundle-translations"] }
@ -26,3 +27,6 @@ i-slint-compiler = { workspace = true, features = ["default", "rust", "display-d
spin_on = { workspace = true }
toml_edit = { workspace = true }
derive_more = { workspace = true, features = ["std", "error"] }
[package.metadata.docs.rs]
all-features = true

View file

@ -189,6 +189,24 @@ impl CompilerConfiguration {
config.translation_path_bundle = Some(path.into());
Self { config }
}
/// Configures the compiler to use Signed Distance Field (SDF) encoding for fonts.
///
/// This flag only takes effect when `embed_resources` is set to [`EmbedResourcesKind::EmbedForSoftwareRenderer`],
/// and requires the `sdf-fonts` cargo feature to be enabled.
///
/// [SDF](https://en.wikipedia.org/wiki/Signed_distance_function) reduces the binary size by
/// using an alternative representation for fonts, trading off some rendering quality
/// for a smaller binary footprint.
/// Rendering is slower and may result in slightly inferior visual output.
/// Use this on systems with limited flash memory.
#[cfg(feature = "sdf-fonts")]
#[must_use]
pub fn with_sdf_fonts(self, enable: bool) -> Self {
let mut config = self.config;
config.use_sdf_fonts = enable;
Self { config }
}
}
/// Error returned by the `compile` function

View file

@ -27,9 +27,10 @@ proc_macro_span = ["quote", "proc-macro2"]
# Feature to print the diagnostics to the console
display-diagnostics = ["codemap", "codemap-diagnostic"]
# Enabled the support to render images and font in the binary
# Enable the support to render images and font in the binary
software-renderer = ["image", "dep:resvg", "fontdue", "i-slint-common/shared-fontdb", "dep:rayon"]
embed-glyphs-as-sdf = ["dep:fdsm", "dep:ttf-parser-fdsm", "dep:nalgebra", "dep:rayon"]
# Enable support to embed the fonts as signed distance fields
sdf-fonts = ["dep:fdsm", "dep:ttf-parser-fdsm", "dep:nalgebra", "dep:rayon"]
# Translation bundler
bundle-translations = ["dep:polib"]

View file

@ -95,6 +95,9 @@ pub struct CompilerConfiguration {
/// Indicate whether to embed resources such as images in the generated output or whether
/// to retain references to the resources on the file system.
pub embed_resources: EmbedResourcesKind,
/// Whether to use SDF when pre-rendering fonts.
#[cfg(all(feature = "software-renderer", feature = "sdf-fonts"))]
pub use_sdf_fonts: bool,
/// The compiler will look in these paths for components used in the file to compile.
pub include_paths: Vec<std::path::PathBuf>,
/// The compiler will look in these paths for library imports.
@ -224,6 +227,8 @@ impl CompilerConfiguration {
components_to_generate: ComponentSelection::ExportedWindows,
#[cfg(feature = "software-renderer")]
font_cache: Default::default(),
#[cfg(all(feature = "software-renderer", feature = "sdf-fonts"))]
use_sdf_fonts: false,
#[cfg(feature = "bundle-translations")]
translation_path_bundle: std::env::var("SLINT_BUNDLE_TRANSLATIONS")
.ok()

View file

@ -263,7 +263,6 @@ pub async fn run_passes(
embed_glyphs::embed_glyphs(
doc,
&type_loader.compiler_config,
type_loader.compiler_config.const_scale_factor,
font_pixel_sizes,
characters_seen,
std::iter::once(&*doc).chain(type_loader.all_documents()),

View file

@ -53,7 +53,6 @@ pub fn embed_glyphs<'a>(
pub fn embed_glyphs<'a>(
doc: &Document,
compiler_config: &CompilerConfiguration,
scale_factor: f64,
mut pixel_sizes: Vec<i16>,
mut characters_seen: HashSet<char>,
all_docs: impl Iterator<Item = &'a crate::object_tree::Document> + 'a,
@ -62,6 +61,7 @@ pub fn embed_glyphs<'a>(
use crate::diagnostics::Spanned;
let generic_diag_location = doc.node.as_ref().map(|n| n.to_source_location());
let scale_factor = compiler_config.const_scale_factor;
characters_seen.extend(
('a'..='z')
@ -249,6 +249,7 @@ fn embed_glyphs_with_fontdb<'a>(
&pixel_sizes,
characters_seen.iter().cloned(),
&fallback_fonts,
compiler_config,
);
let resource_id = doc.embedded_file_resources.borrow().len();
@ -349,6 +350,7 @@ fn embed_font(
pixel_sizes: &[i16],
character_coverage: impl Iterator<Item = char>,
fallback_fonts: &[Font],
_compiler_config: &CompilerConfiguration,
) -> BitmapFont {
let mut character_map: Vec<CharacterMapEntry> = character_coverage
.filter(|code_point| {
@ -364,10 +366,13 @@ fn embed_font(
})
.collect();
#[cfg(feature = "embed-glyphs-as-sdf")]
let glyphs = embed_sdf_glyphs(pixel_sizes, &character_map, &font, fallback_fonts);
#[cfg(not(feature = "embed-glyphs-as-sdf"))]
#[cfg(feature = "sdf-fonts")]
let glyphs = if _compiler_config.use_sdf_fonts {
embed_sdf_glyphs(pixel_sizes, &character_map, &font, fallback_fonts)
} else {
embed_alpha_map_glyphs(pixel_sizes, &character_map, &font, fallback_fonts)
};
#[cfg(not(feature = "sdf-fonts"))]
let glyphs = embed_alpha_map_glyphs(pixel_sizes, &character_map, &font, fallback_fonts);
character_map.sort_by_key(|entry| entry.code_point);
@ -387,11 +392,14 @@ fn embed_font(
glyphs,
weight: face_info.weight.0,
italic: face_info.style != fontdb::Style::Normal,
sdf: cfg!(feature = "embed-glyphs-as-sdf"),
#[cfg(feature = "sdf-fonts")]
sdf: _compiler_config.use_sdf_fonts,
#[cfg(not(feature = "sdf-fonts"))]
sdf: false,
}
}
#[cfg(all(not(target_arch = "wasm32"), not(feature = "embed-glyphs-as-sdf")))]
#[cfg(all(not(target_arch = "wasm32")))]
fn embed_alpha_map_glyphs(
pixel_sizes: &[i16],
character_map: &Vec<CharacterMapEntry>,
@ -433,7 +441,7 @@ fn embed_alpha_map_glyphs(
glyphs
}
#[cfg(all(not(target_arch = "wasm32"), feature = "embed-glyphs-as-sdf"))]
#[cfg(all(not(target_arch = "wasm32"), feature = "sdf-fonts"))]
fn embed_sdf_glyphs(
pixel_sizes: &[i16],
character_map: &Vec<CharacterMapEntry>,
@ -470,7 +478,7 @@ fn embed_sdf_glyphs(
vec![BitmapGlyphs { pixel_size: target_pixel_size, glyph_data }]
}
#[cfg(all(not(target_arch = "wasm32"), feature = "embed-glyphs-as-sdf"))]
#[cfg(all(not(target_arch = "wasm32"), feature = "sdf-fonts"))]
fn generate_sdf_for_glyph(
font: &Font,
code_point: char,

View file

@ -20,6 +20,7 @@ path = "main.rs"
[features]
software-renderer = ["i-slint-compiler/software-renderer"]
jemalloc = ["dep:tikv-jemallocator"]
sdf-fonts = ["i-slint-compiler/sdf-fonts"]
# Keep defaults in sync with defaults applied in api/cpp/CMakeLists.txt for slint-compiler
default = ["software-renderer", "jemalloc"]

View file

@ -27,6 +27,10 @@ enum Embedding {
/// used
#[cfg(feature = "software-renderer")]
EmbedForSoftwareRenderer,
/// Same as "embed-files-for-software-renderer" but use Signed Distance Field (SDF) to render fonts.
/// This produces smaller binaries, but may result in slightly inferior visual output and slower rendering.
#[cfg(all(feature = "software-renderer", feature = "sdf-fonts"))]
EmbedForSoftwareRendererWithSdf,
}
#[derive(Parser)]
@ -151,6 +155,11 @@ fn main() -> std::io::Result<()> {
Embedding::EmbedFiles => EmbedResourcesKind::EmbedAllResources,
#[cfg(feature = "software-renderer")]
Embedding::EmbedForSoftwareRenderer => EmbedResourcesKind::EmbedTextures,
#[cfg(all(feature = "software-renderer", feature = "sdf-fonts"))]
Embedding::EmbedForSoftwareRendererWithSdf => {
compiler_config.use_sdf_fonts = true;
EmbedResourcesKind::EmbedTextures
}
};
}