Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to yeslogic-fontconfig-sys from servo-fontconfig #956

Merged
merged 2 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ For Linux a few additional packages beyond the usual build essentials are needed
- fontconfig library (`libfontconfig-dev` on debian based distributions)
- (optional) Qt will be used when `qmake` is found in `PATH`

`xcb` and `xcbcommon` are not 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).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is my understanding correct that RUST_FONTCONFIG_DLOPEN is the name of the environment variable that's not only used by Slint's build script but also by yeslogic-fontconfig itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, if Slint used the safe fontconfig wrapper around yeslogic-fontconfig-sys, the build.rs scripts in Slint wouldn't be necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, that looks new/updated and promising. I might look into that separately unless somebody beats me to it. But then I think this merge request can go in - yay :)


### macOS

- Make sure the "Xcode Command Line Tools" are installed: `xcode-select --install`
Expand Down Expand Up @@ -125,7 +130,7 @@ in the dependencies section of your `package.json`:
Slint can be cross-compiled to different target architectures and environments. For the Rust build we
have had a good experience using [`cross`](https://github.com/rust-embedded/cross). For convenience we're
including a `Cross.toml` configuration file for `cross` in the source tree along with Docker containers that
allow targeting a Debian ARMv7 and ARMv8 based Distribution with X11 or Wayland, out of the box.
allow targeting a Debian ARMv7 and ARMv8 based Distribution with X11 or Wayland, out of the box. If you want to use the default Cross containers or your own, make sure the [dependencies](#Prerequisites) are in the container.

This includes for example the Raspberry Pi OS. Using the following steps you can run the examples on a
pi:
Expand Down
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\"");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a feature, just a plain cfg.

Also, could we have the default reversed? Default to dlopen and have a env variable to disable it?

Copy link
Contributor Author

@Be-ing Be-ing Oct 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a feature, just a plain cfg.

I'm not sure what you mean. Listing it as a feature in Cargo.toml? I could do that, but it requires doing that in every crate that uses fontconfig for building the workspace with --all-features to work.

Also, could we have the default reversed? Default to dlopen and have a env variable to disable it?

Technically possible, but that would require changing how the build scripts handle the environment variable all up and down the stack (yeslogic-fontconfig-sys, fontconfig, fontkit, plotters, Slint crates) which I'd rather not deal with.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean println!("cargo:rustc-cfg=fontconfig-dlopen");. Because i believe the feature= is to be used with cargo features.
Unless i'm missing something. What other crate are using that.

Technically possible, but that would require changing how the build scripts handle the environment variable all up and down the stack (yeslogic-fontconfig-sys, fontconfig, fontkit, plotters, Slint crates) which I'd rather not deal with.

I see. This is unfortunate.

Copy link
Contributor Author

@Be-ing Be-ing Oct 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, feature= is intended to be used with Cargo features. It is unusual for build scripts to print rustc-cfg=feature. This has the limitation of not being able to enable optional dependencies because Cargo.toml is parsed before build scripts are run, but that's not relevant in this case. Also, feature= is required for dlib::ffi_dispatch!.

}
}
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 <info@slint-ui.com>
// 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 <info@slint-ui.com>
// 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
}
}