From 68d461eb205e84f2b52a85976ed8d545e57f73c1 Mon Sep 17 00:00:00 2001 From: Be Date: Tue, 15 Feb 2022 17:35:22 -0600 Subject: [PATCH] switch to yeslogic-fontconfig-sys instead of servo-fontconfig servo-fontconfig statically links a vendored fontconfig library if fontconfig is not found by pkgconfig. Using a vendored fontconfig library instead of the system fontconfig library doesn't actually work well though: https://github.com/slint-ui/slint/issues/88 Building a vendored copy of fontconfig is also problematic because fontconfig has a lot of C dependencies, which makes it difficult to cross compile the vendored copy of fontconfig: $ pkg-config fontconfig --static --libs -lfontconfig -lfreetype -lz -lbz2 -lpng16 -lm -lm -lz -lharfbuzz -lm -lglib-2.0 -lm -lpcre -lsysprof-capture-4 -pthread -lgraphite2 -lbrotlidec -lbrotlicommon -lxml2 -lz -llzma -lm Instead of using a vendored copy, with https://github.com/yeslogic/fontconfig-rs/pull/12 yeslogic-fontconfig-sys will have a Cargo feature to dlopen fontconfig at runtime instead of linking it at build time. This is exposed in font-kit with the new source-fontconfig-dlopen feature, which is disabled by default. The feature can be enabled by setting the RUST_FONTCONFIG_DLOPEN environment variable to avoid needing to propagate the Cargo feature all the way through downstream Cargo.toml's. This feature makes it considerably easier to cross compile by avoiding the need to cross compile fontconfig and all its dependencies. --- Cargo.toml | 11 +++++----- build.rs | 7 +++++++ src/sources/fontconfig.rs | 42 ++++++++++++++++++++++----------------- 3 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 1415a66..1e41c98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "font-kit" -version = "0.10.1" +version = "0.11.0" authors = ["Patrick Walton "] description = "A cross-platform font loading library" license = "MIT/Apache-2.0" @@ -14,7 +14,8 @@ edition = "2018" default = ["source"] loader-freetype = ["freetype"] loader-freetype-default = ["loader-freetype"] -source-fontconfig = ["servo-fontconfig"] +source-fontconfig = ["yeslogic-fontconfig-sys"] +source-fontconfig-dlopen = ["yeslogic-fontconfig-sys/dlopen"] source-fontconfig-default = ["source-fontconfig"] source = [] @@ -32,8 +33,8 @@ pathfinder_simd = "0.5.1" version = "0.7" optional = true -[dependencies.servo-fontconfig] -version = "0.5" +[dependencies.yeslogic-fontconfig-sys] +version = "3.0.0" optional = true [dev-dependencies] @@ -58,7 +59,7 @@ core-text = "19.1.0" freetype = "0.7" [target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_arch = "wasm32")))'.dependencies] -servo-fontconfig = "0.5" +yeslogic-fontconfig-sys = "3.0.0" [target.'cfg(not(any(target_arch = "wasm32", target_family = "windows", target_os = "android")))'.dependencies] dirs-next = "2.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..be57bdd --- /dev/null +++ b/build.rs @@ -0,0 +1,7 @@ +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=\"source-fontconfig-dlopen\""); + } +} diff --git a/src/sources/fontconfig.rs b/src/sources/fontconfig.rs index b3a04ab..d6f48dd 100644 --- a/src/sources/fontconfig.rs +++ b/src/sources/fontconfig.rs @@ -244,7 +244,13 @@ impl Source for FontconfigSource { mod fc { #![allow(dead_code)] - use fontconfig::fontconfig as ffi; + use fontconfig_sys as ffi; + use fontconfig_sys::ffi_dispatch; + + #[cfg(feature = "source-fontconfig-dlopen")] + use ffi::statics::LIB; + #[cfg(not(feature = "source-fontconfig-dlopen"))] + use ffi::*; use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_uchar}; @@ -308,7 +314,7 @@ mod fc { pub fn new() -> Self { unsafe { Config { - d: ffi::FcInitLoadConfigAndFonts(), + d: ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcInitLoadConfigAndFonts,), } } } @@ -317,7 +323,7 @@ mod fc { impl Drop for Config { fn drop(&mut self) { unsafe { - ffi::FcConfigDestroy(self.d); + ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcConfigDestroy, self.d); } } } @@ -337,23 +343,23 @@ mod fc { // FcPatternCreate pub fn new() -> Self { - unsafe { Pattern::from_ptr(ffi::FcPatternCreate()) } + unsafe { Pattern::from_ptr(ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcPatternCreate,)) } } // FcNameParse pub fn from_name(name: &str) -> Self { let c_name = CString::new(name).unwrap(); - unsafe { Pattern::from_ptr(ffi::FcNameParse(c_name.as_ptr() as *mut c_uchar)) } + unsafe { Pattern::from_ptr(ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcNameParse, c_name.as_ptr() as *mut c_uchar)) } } // FcPatternAddString pub fn push_string(&mut self, object: Object, value: String) { unsafe { let c_string = CString::new(value).unwrap(); - ffi::FcPatternAddString( + ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcPatternAddString, self.d, object.as_ptr(), - c_string.as_ptr() as *const c_uchar, + c_string.as_ptr() as *const c_uchar ); // We have to keep this string, because `FcPattern` has a pointer to it now. @@ -364,21 +370,21 @@ mod fc { // FcConfigSubstitute pub fn config_substitute(&mut self, match_kind: MatchKind) { unsafe { - ffi::FcConfigSubstitute(ptr::null_mut(), self.d, match_kind.to_u32()); + ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcConfigSubstitute, ptr::null_mut(), self.d, match_kind.to_u32()); } } // FcDefaultSubstitute pub fn default_substitute(&mut self) { unsafe { - ffi::FcDefaultSubstitute(self.d); + ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcDefaultSubstitute, self.d); } } // FcFontSort pub fn sorted(&self, config: &Config) -> Result { let mut res = ffi::FcResultMatch; - let d = unsafe { ffi::FcFontSort(config.d, self.d, 1, ptr::null_mut(), &mut res) }; + let d = unsafe { ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcFontSort, config.d, self.d, 1, ptr::null_mut(), &mut res) }; match res { ffi::FcResultMatch => Ok(FontSet { d, idx: 0 }), @@ -391,7 +397,7 @@ mod fc { // FcFontList pub fn list(&self, config: &Config, set: ObjectSet) -> Result { - let d = unsafe { ffi::FcFontList(config.d, self.d, set.d) }; + let d = unsafe { ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcFontList, config.d, self.d, set.d) }; if !d.is_null() { Ok(FontSet { d, idx: 0 }) } else { @@ -403,7 +409,7 @@ mod fc { impl Drop for Pattern { #[inline] fn drop(&mut self) { - unsafe { ffi::FcPatternDestroy(self.d) } + unsafe { ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcPatternDestroy, self.d) } } } @@ -417,7 +423,7 @@ mod fc { pub fn get_string(&self, object: Object) -> Option { unsafe { let mut string = ptr::null_mut(); - let res = ffi::FcPatternGetString(self.d, object.as_ptr(), 0, &mut string); + let res = ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcPatternGetString, self.d, object.as_ptr(), 0, &mut string); if res != ffi::FcResultMatch { return None; } @@ -437,7 +443,7 @@ mod fc { pub fn get_integer(&self, object: Object) -> Option { unsafe { let mut integer = 0; - let res = ffi::FcPatternGetInteger(self.d, object.as_ptr(), 0, &mut integer); + let res = ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcPatternGetInteger, self.d, object.as_ptr(), 0, &mut integer); if res != ffi::FcResultMatch { return None; } @@ -484,7 +490,7 @@ mod fc { impl Drop for FontSet { fn drop(&mut self) { - unsafe { ffi::FcFontSetDestroy(self.d) } + unsafe { ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcFontSetDestroy, self.d) } } } @@ -497,7 +503,7 @@ mod fc { pub fn new() -> Self { unsafe { ObjectSet { - d: ffi::FcObjectSetCreate(), + d: ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcObjectSetCreate,), } } } @@ -507,14 +513,14 @@ mod fc { unsafe { // Returns `false` if the property name cannot be inserted // into the set (due to allocation failure). - assert_eq!(ffi::FcObjectSetAdd(self.d, object.as_ptr()), 1); + assert_eq!(ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcObjectSetAdd, self.d, object.as_ptr()), 1); } } } impl Drop for ObjectSet { fn drop(&mut self) { - unsafe { ffi::FcObjectSetDestroy(self.d) } + unsafe { ffi_dispatch!(feature="source-fontconfig-dlopen", LIB, FcObjectSetDestroy, self.d) } } } }