Skip to content

Commit

Permalink
switch to yeslogic-fontconfig-sys from servo-fontconfig
Browse files Browse the repository at this point in the history
This allows setting the RUST_FONTCONFIG_DLOPEN environment variable
to dlopen fontconfig at runtime rather than linking it at build
time. This is helpful for cross compiling to Linux, particularly
because fontconfig has lots of C dependencies. Building a vendored
copy of fontconfig does not work as expected:
#88
  • Loading branch information
Be-ing authored and tronical committed Oct 5, 2022
1 parent 6edf210 commit ecb6fd5
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 37 deletions.
2 changes: 1 addition & 1 deletion examples/plotter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name = "plotter"

[dependencies]
slint = { path = "../../api/rs/slint" }
plotters = { version = "0.3.1", default-features = false, features = ["bitmap_backend", "surface_series"] }
plotters = { version = "0.3.4", default-features = false, features = ["bitmap_backend", "surface_series"] }

[build-dependencies]
slint-build = { path = "../../api/rs/build" }
Expand Down
6 changes: 2 additions & 4 deletions internal/backends/winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ path = "lib.rs"
[features]
wayland = ["winit/wayland", "glutin/wayland", "copypasta/wayland"]
x11 = ["winit/x11", "glutin/x11", "copypasta/x11"]
renderer-winit-femtovg = ["femtovg", "fontdb", "libc", "servo-fontconfig", "winapi", "dwrote", "imgref", "unicode-script", "ttf-parser", "rgb"]
renderer-winit-femtovg = ["femtovg", "fontdb", "libc", "yeslogic-fontconfig-sys", "winapi", "dwrote", "imgref", "unicode-script", "ttf-parser", "rgb"]
renderer-winit-skia = ["skia-safe", "glow", "unicode-segmentation", "metal", "objc", "core-graphics-types", "foreign-types", "wio", "winapi/d3d12", "winapi/dxgi", "winapi/dxgi1_2", "winapi/dxgi1_3", "winapi/dxgi1_4", "winapi/d3d12sdklayers", "winapi/synchapi"]
renderer-winit-skia-opengl = ["skia-safe/gl", "glow", "unicode-segmentation"]
renderer-winit-software = ["femtovg", "imgref", "rgb"]
Expand Down Expand Up @@ -77,9 +77,7 @@ wio = { version = "0.2.2", 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 }
# Require font-config from the system on Linux. Issue #88 indicates that the copy provided by servo-fontconfig may be incompatible
# with distros at times.
servo-fontconfig = { version = "0.5", optional = true, features = [ "force_system_lib" ] }
yeslogic-fontconfig-sys = { version = "3.2", optional = true }

[target.'cfg(target_os = "macos")'.dependencies]
# For GL rendering
Expand Down
6 changes: 6 additions & 0 deletions internal/backends/winit/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ fn main() {
skia_backend_metal: { all(target_os = "macos", not(feature = "renderer-winit-skia-opengl")) },
skia_backend_d3d: { all(target_family = "windows", not(feature = "renderer-winit-skia-opengl")) },
}

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\"");
}
}
57 changes: 43 additions & 14 deletions internal/backends/winit/renderer/femtovg/fonts/fontconfig.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
// Copyright © SixtyFPS GmbH <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial

use fontconfig::fontconfig;
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 = fontconfig::FcInitLoadConfigAndFonts();
let config = ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcInitLoadConfigAndFonts,);
let family_cstr = std::ffi::CString::new(requested_family).unwrap();
let pattern = fontconfig::FcNameParse(family_cstr.as_ptr() as *mut libc::c_uchar);
fontconfig::FcConfigSubstitute(std::ptr::null_mut(), pattern, fontconfig::FcMatchPattern);
fontconfig::FcDefaultSubstitute(pattern);
let mut sort_result = fontconfig::FcResultMatch;
let result_set =
fontconfig::FcFontSort(config, pattern, 1, std::ptr::null_mut(), &mut sort_result);
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 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 mut families = Vec::new();
for idx in 0..(*result_set).nfont {
let mut raw_family_name = std::ptr::null_mut();
if fontconfig::FcPatternGetString(
if ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcPatternGetString,
*(*result_set).fonts.offset(idx as isize),
b"family\0".as_ptr() as *const libc::c_char,
0,
&mut raw_family_name,
) != fontconfig::FcResultMatch
&mut raw_family_name
) != ffi::FcResultMatch
{
continue;
}
Expand All @@ -41,9 +70,9 @@ pub fn find_families(requested_family: &str) -> Vec<String> {
}
}

fontconfig::FcFontSetDestroy(result_set);
fontconfig::FcPatternDestroy(pattern);
fontconfig::FcConfigDestroy(config);
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);
families
}
}
4 changes: 1 addition & 3 deletions internal/compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ usvg = "0.23"

[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_arch = "wasm32")))'.dependencies]
libc = { version = "0.2" }
# Require font-config from the system on Linux. Issue #88 indicates that the copy provided by servo-fontconfig may be incompatible
# with distros at times.
servo-fontconfig = { version = "0.5", features = [ "force_system_lib" ] }
yeslogic-fontconfig-sys = "3.2.0"

[dev-dependencies]
i-slint-parser-test-macro = { path = "./parser-test-macro" }
Expand Down
6 changes: 6 additions & 0 deletions internal/compiler/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ 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");

Expand Down
59 changes: 44 additions & 15 deletions internal/compiler/passes/embed_glyphs/fontconfig.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
// Copyright © SixtyFPS GmbH <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial

use fontconfig::fontconfig;
use fontconfig_sys as ffi;
use fontconfig_sys::ffi_dispatch;

// This is duplicated from the GL backend
#[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 = fontconfig::FcInitLoadConfigAndFonts();
let config = ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcInitLoadConfigAndFonts,);
let family_cstr = std::ffi::CString::new(requested_family).unwrap();
let pattern = fontconfig::FcNameParse(family_cstr.as_ptr() as *mut libc::c_uchar);
fontconfig::FcConfigSubstitute(std::ptr::null_mut(), pattern, fontconfig::FcMatchPattern);
fontconfig::FcDefaultSubstitute(pattern);
let mut sort_result = fontconfig::FcResultMatch;
let result_set =
fontconfig::FcFontSort(config, pattern, 1, std::ptr::null_mut(), &mut sort_result);
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 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 mut families = Vec::new();
for idx in 0..(*result_set).nfont {
let mut raw_family_name = std::ptr::null_mut();
if fontconfig::FcPatternGetString(
if ffi_dispatch!(
feature = "fontconfig-dlopen",
LIB,
FcPatternGetString,
*(*result_set).fonts.offset(idx as isize),
b"family\0".as_ptr() as *const libc::c_char,
0,
&mut raw_family_name,
) != fontconfig::FcResultMatch
&mut raw_family_name
) != ffi::FcResultMatch
{
continue;
}
Expand All @@ -42,9 +71,9 @@ pub fn find_families(requested_family: &str) -> Vec<String> {
}
}

fontconfig::FcFontSetDestroy(result_set);
fontconfig::FcPatternDestroy(pattern);
fontconfig::FcConfigDestroy(config);
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);
families
}
}

0 comments on commit ecb6fd5

Please sign in to comment.