Use the dlopen feature for fontconfig

closes #2376
This commit is contained in:
Olivier Goffart 2023-04-19 15:31:14 +02:00 committed by Olivier Goffart
parent 621ca4f56c
commit 1d3d19536e
10 changed files with 29 additions and 101 deletions

View file

@ -10,6 +10,7 @@ All notable changes to this project are documented in this file.
- Winit backend: Fix detect of dark color scheme in some circumstances.
- ListView: fix resizing a ListView to empty height would make all items invisible even if resized back (#2545)
- Fixed compiler panic when accessing unset layout properties such as `spacing` or `alignment` (#2483)
- Load fontconfig with dlopen instead of dynamic linking.
### Slint Language

View file

@ -92,6 +92,7 @@ rust-version = "1.66"
[workspace.dependencies]
resvg = { version= "0.30.0", default-features = false }
fontdb = { version = "0.13", features = ["fontconfig"] }
yeslogic-fontconfig-sys = { version = "3.2.0", features = ["dlopen"] }
[profile.release]
lto = true

View file

@ -23,9 +23,6 @@ For Linux a few additional packages beyond the usual build essentials are needed
`xcb` and `xcbcommon` aren't needed if you are only using `backend-winit-wayland` without `backend-winit-x11`.
fontconfig can be `dlopen`ed at runtime instead of linking it at build time by setting the
environment variable `RUST_FONTCONFIG_DLOPEN=on`. This can be useful for [cross-compiling](#cross-compiling).
### macOS
- Make sure the "Xcode Command Line Tools" are installed: `xcode-select --install`

View file

@ -15,7 +15,7 @@ name = "plotter"
[dependencies]
slint = { path = "../../api/rs/slint" }
plotters = { version = "0.3.4", default-features = false, features = ["bitmap_backend", "surface_series"] }
plotters = { version = "0.3.4", default-features = false, features = ["bitmap_backend", "surface_series", "fontconfig-dlopen"] }
[build-dependencies]
slint-build = { path = "../../api/rs/build" }

View file

@ -28,7 +28,7 @@ proc_macro_span = ["quote", "proc-macro2"]
display-diagnostics = ["codemap", "codemap-diagnostic"]
# Enabled the support to render images and font in the binary
software-renderer = ["image", "dep:resvg", "dep:fontdb", "fontdue", "libc", "yeslogic-fontconfig-sys"]
software-renderer = ["image", "dep:resvg", "dep:fontdb", "fontdue", "libc", "dep:yeslogic-fontconfig-sys"]
[dependencies]
@ -63,7 +63,7 @@ fontdue = { version = "0.7.1", optional = true }
[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_arch = "wasm32")))'.dependencies]
libc = { version = "0.2", optional = true }
yeslogic-fontconfig-sys = { version = "3.2.0", optional = true }
yeslogic-fontconfig-sys = { workspace = true, optional = true }
[dev-dependencies]
i-slint-parser-test-macro = { path = "./parser-test-macro" }

View file

@ -6,12 +6,6 @@ use std::io::Write;
use std::path::{Path, PathBuf};
fn main() -> std::io::Result<()> {
println!("cargo:rerun-if-env-changed=RUST_FONTCONFIG_DLOPEN");
let dlopen = std::env::var("RUST_FONTCONFIG_DLOPEN").is_ok();
if dlopen {
println!("cargo:rustc-cfg=feature=\"fontconfig-dlopen\"");
}
let mut library_dir = PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap());
library_dir.push("widgets");

View file

@ -2,57 +2,30 @@
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
use fontconfig_sys as ffi;
use fontconfig_sys::ffi_dispatch;
#[cfg(feature = "fontconfig-dlopen")]
use ffi::statics::LIB;
#[cfg(not(feature = "fontconfig-dlopen"))]
use ffi::*;
// This is duplicated in the slint-compiler's glyph embedding code
pub fn find_families(requested_family: &str) -> Vec<String> {
#[allow(unsafe_code)]
unsafe {
let config = ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcInitLoadConfigAndFonts,);
let config = (LIB.FcInitLoadConfigAndFonts)();
let family_cstr = std::ffi::CString::new(requested_family).unwrap();
let pattern = ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcNameParse,
family_cstr.as_ptr() as *mut libc::c_uchar
);
ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcConfigSubstitute,
std::ptr::null_mut(),
pattern,
ffi::FcMatchPattern
);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcDefaultSubstitute, pattern);
let pattern = (LIB.FcNameParse)(family_cstr.as_ptr() as *mut libc::c_uchar);
(LIB.FcConfigSubstitute)(std::ptr::null_mut(), pattern, ffi::FcMatchPattern);
(LIB.FcDefaultSubstitute)(pattern);
let mut sort_result = ffi::FcResultMatch;
let result_set = ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcFontSort,
config,
pattern,
1,
std::ptr::null_mut(),
&mut sort_result
);
let result_set =
(LIB.FcFontSort)(config, pattern, 1, std::ptr::null_mut(), &mut sort_result);
let mut families = Vec::new();
for idx in 0..(*result_set).nfont {
let mut raw_family_name = std::ptr::null_mut();
if ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcPatternGetString,
if (LIB.FcPatternGetString)(
*(*result_set).fonts.offset(idx as isize),
b"family\0".as_ptr() as *const libc::c_char,
0,
&mut raw_family_name
&mut raw_family_name,
) != ffi::FcResultMatch
{
continue;
@ -71,9 +44,9 @@ pub fn find_families(requested_family: &str) -> Vec<String> {
}
}
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcFontSetDestroy, result_set);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcPatternDestroy, pattern);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcConfigDestroy, config);
(LIB.FcFontSetDestroy)(result_set);
(LIB.FcPatternDestroy)(pattern);
(LIB.FcConfigDestroy)(config);
families
}
}

View file

@ -10,7 +10,6 @@ license = "GPL-3.0-only OR LicenseRef-Slint-commercial"
description = "FemtoVG based renderer for Slint"
repository = "https://github.com/slint-ui/slint"
homepage = "https://slint-ui.com"
build = "build.rs"
rust-version.workspace = true
[lib]
@ -18,7 +17,7 @@ path = "lib.rs"
[features]
diskfonts = ["fontdb/memmap", "fontdb/fontconfig"]
fontconfig = ["yeslogic-fontconfig-sys"]
fontconfig = ["dep:yeslogic-fontconfig-sys"]
[dependencies]
i-slint-core = { version = "=1.0.1", path = "../../../internal/core", features = [ "box-shadow-cache" ] }
@ -61,4 +60,4 @@ wasm-bindgen = { version = "0.2" }
[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_arch = "wasm32")))'.dependencies]
libc = { version = "0.2" }
yeslogic-fontconfig-sys = { version = "3.2", optional = true }
yeslogic-fontconfig-sys = { workspace = true, optional = true }

View file

@ -1,10 +0,0 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
fn main() {
println!("cargo:rerun-if-env-changed=RUST_FONTCONFIG_DLOPEN");
let dlopen = std::env::var("RUST_FONTCONFIG_DLOPEN").is_ok();
if dlopen {
println!("cargo:rustc-cfg=feature=\"fontconfig-dlopen\"");
}
}

View file

@ -2,56 +2,29 @@
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
use fontconfig_sys as ffi;
use fontconfig_sys::ffi_dispatch;
#[cfg(feature = "fontconfig-dlopen")]
use ffi::statics::LIB;
#[cfg(not(feature = "fontconfig-dlopen"))]
use ffi::*;
// This is duplicated in the slint-compiler's glyph embedding code
pub fn find_families(requested_family: &str) -> Vec<String> {
unsafe {
let config = ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcInitLoadConfigAndFonts,);
let config = (LIB.FcInitLoadConfigAndFonts)();
let family_cstr = std::ffi::CString::new(requested_family).unwrap();
let pattern = ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcNameParse,
family_cstr.as_ptr() as *mut libc::c_uchar
);
ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcConfigSubstitute,
std::ptr::null_mut(),
pattern,
ffi::FcMatchPattern
);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcDefaultSubstitute, pattern);
let pattern = (LIB.FcNameParse)(family_cstr.as_ptr() as *mut libc::c_uchar);
(LIB.FcConfigSubstitute)(std::ptr::null_mut(), pattern, ffi::FcMatchPattern);
(LIB.FcDefaultSubstitute)(pattern);
let mut sort_result = ffi::FcResultMatch;
let result_set = ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcFontSort,
config,
pattern,
1,
std::ptr::null_mut(),
&mut sort_result
);
let result_set =
(LIB.FcFontSort)(config, pattern, 1, std::ptr::null_mut(), &mut sort_result);
let mut families = Vec::new();
for idx in 0..(*result_set).nfont {
let mut raw_family_name = std::ptr::null_mut();
if ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcPatternGetString,
if (LIB.FcPatternGetString)(
*(*result_set).fonts.offset(idx as isize),
b"family\0".as_ptr() as *const libc::c_char,
0,
&mut raw_family_name
&mut raw_family_name,
) != ffi::FcResultMatch
{
continue;
@ -70,9 +43,9 @@ pub fn find_families(requested_family: &str) -> Vec<String> {
}
}
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcFontSetDestroy, result_set);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcPatternDestroy, pattern);
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcConfigDestroy, config);
(LIB.FcFontSetDestroy)(result_set);
(LIB.FcPatternDestroy)(pattern);
(LIB.FcConfigDestroy)(config);
families
}
}