fontconfig: Branch 'main' - 3 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Mar 31 12:05:52 UTC 2025
.gitlab-ci/build.sh | 12 +
fc-fontations/mod.rs | 33 ++-
fc-fontations/pattern_bindings/fc_wrapper.rs | 123 +++++++++++++
fc-fontations/pattern_bindings/mod.rs | 254 +++++++++++++++++++++++++++
4 files changed, 417 insertions(+), 5 deletions(-)
New commits:
commit 31252db1e652d63ab34d3a63c22aea16dce23db4
Merge: 564a8a9 738eb8a
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon Mar 31 12:05:49 2025 +0000
Merge branch 'patternBindings' into 'main'
[Fontations] Add internal PatternBuilder abstraction
See merge request fontconfig/fontconfig!371
commit 738eb8a73ab05301163479ddab7ceebab88907bb
Author: Dominik Röttsches <drott at chromium.org>
Date: Tue Mar 18 12:33:09 2025 +0200
[Fontations] Add internal PatternBuilder abstraction
Rust abstraction for creating FcPatterns. Implements Drop methods for
handling memory of destroying FontConfig-side allocated objects
where needed for complex pattern objects.
Used in the Fontations backend, not exposed as external API.
Changelog: added
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index b3a82a6..3929924 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -1,5 +1,31 @@
+/*
+ * fontconfig/fc-fontations/mod.rs
+ *
+ * Copyright 2025 Google LLC.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the author(s) not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
extern crate fc_fontations_bindgen;
+mod pattern_bindings;
+
use fc_fontations_bindgen::{
fcint::{FcPatternCreate, FcPatternObjectAddBool, FC_COLOR_OBJECT},
FcFontSet, FcFontSetAdd,
diff --git a/fc-fontations/pattern_bindings/fc_wrapper.rs b/fc-fontations/pattern_bindings/fc_wrapper.rs
new file mode 100644
index 0000000..e3ad063
--- /dev/null
+++ b/fc-fontations/pattern_bindings/fc_wrapper.rs
@@ -0,0 +1,123 @@
+/*
+ * fontconfig/fc-fontations/pattern_bindings/fc_wrapper.rs
+ *
+ * Copyright 2025 Google LLC.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the author(s) not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+ use fc_fontations_bindgen::fcint::{
+ FcPattern, FcPatternCreate, FcPatternDestroy, FcRange, FcRangeCopy, FcRangeCreateDouble,
+ FcRangeDestroy,
+};
+
+macro_rules! wrap_fc_object {
+ (
+ $wrapper_name:ident,
+ $wrapped_type:ident,
+ $destroy_fn:ident
+ $(, $copy_fn:ident)?
+ ) => {
+ #[allow(unused)]
+ #[derive(Debug)]
+ pub struct $wrapper_name {
+ inner: *mut $wrapped_type,
+ }
+
+ impl $wrapper_name {
+ #[allow(unused)]
+ pub fn from_raw(ptr: *mut $wrapped_type) -> Self {
+ Self { inner: ptr }
+ }
+
+ #[allow(unused)]
+ pub fn into_raw(self) -> *mut $wrapped_type {
+ let ptr = self.inner;
+ std::mem::forget(self);
+ ptr
+ }
+
+ #[allow(unused)]
+ pub fn as_ptr(&self) -> *mut $wrapped_type {
+ assert!(!self.inner.is_null());
+ self.inner
+ }
+ }
+
+ impl Drop for $wrapper_name {
+ fn drop(&mut self) {
+ unsafe {
+ $destroy_fn(self.inner);
+ }
+ }
+ }
+
+ $(
+ impl Clone for $wrapper_name {
+ fn clone(&self) -> Self {
+ Self {
+ inner: unsafe { $copy_fn(self.inner) },
+ }
+ }
+ }
+ )?
+ };
+}
+
+wrap_fc_object! {
+ FcRangeWrapper,
+ FcRange,
+ FcRangeDestroy,
+ FcRangeCopy
+}
+
+impl FcRangeWrapper {
+ #[allow(unused)]
+ pub fn new(min: f64, max: f64) -> Option<Self> {
+ unsafe {
+ let ptr = FcRangeCreateDouble(min, max);
+ if ptr.is_null() {
+ None
+ } else {
+ Some(Self { inner: ptr })
+ }
+ }
+ }
+}
+
+wrap_fc_object! {
+ FcPatternWrapper,
+ FcPattern,
+ FcPatternDestroy
+}
+
+impl FcPatternWrapper {
+ #[allow(unused)]
+ pub fn new() -> Option<Self> {
+ // Corrected new function for FcPattern
+ unsafe {
+ let ptr = FcPatternCreate();
+ if ptr.is_null() {
+ None
+ } else {
+ Some(Self { inner: ptr })
+ }
+ }
+ }
+}
diff --git a/fc-fontations/pattern_bindings/mod.rs b/fc-fontations/pattern_bindings/mod.rs
new file mode 100644
index 0000000..0174487
--- /dev/null
+++ b/fc-fontations/pattern_bindings/mod.rs
@@ -0,0 +1,254 @@
+/*
+ * fontconfig/fc-fontations/pattern_bindings/mod.rs
+ *
+ * Copyright 2025 Google LLC.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the author(s) not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+ extern crate fc_fontations_bindgen;
+
+mod fc_wrapper;
+
+use std::ffi::CString;
+use std::fmt::Debug;
+
+use fc_fontations_bindgen::fcint::{
+ FcPattern, FcPatternObjectAddBool, FcPatternObjectAddDouble, FcPatternObjectAddInteger,
+ FcPatternObjectAddRange, FcPatternObjectAddString, FC_FAMILY_OBJECT,
+};
+
+use self::fc_wrapper::{FcPatternWrapper, FcRangeWrapper};
+
+#[allow(unused)]
+#[derive(Debug)]
+pub enum PatternValue {
+ String(CString),
+ Boolean(bool),
+ Integer(i32),
+ Double(f64),
+ Range(FcRangeWrapper),
+}
+
+#[derive(Debug)]
+pub struct PatternElement {
+ object_id: i32,
+ value: PatternValue,
+}
+
+impl PatternElement {
+ #[allow(unused)]
+ fn new(object_id: i32, value: PatternValue) -> Self {
+ Self { object_id, value }
+ }
+}
+
+#[derive(Debug, Clone)]
+struct PatternAddError;
+
+impl std::fmt::Display for PatternAddError {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "Failed to add object to Fontconfig pattern.")
+ }
+}
+
+impl PatternElement {
+ fn append_to_fc_pattern(self, pattern: *mut FcPattern) -> Result<(), PatternAddError> {
+ let pattern_add_success = match self.value {
+ PatternValue::String(string) => unsafe {
+ FcPatternObjectAddString(pattern, self.object_id, string.as_ptr() as *const u8)
+ },
+ PatternValue::Boolean(value) => unsafe {
+ FcPatternObjectAddBool(pattern, self.object_id, value as i32)
+ },
+ PatternValue::Integer(value) => unsafe {
+ FcPatternObjectAddInteger(pattern, self.object_id, value)
+ },
+ PatternValue::Double(value) => unsafe {
+ FcPatternObjectAddDouble(pattern, self.object_id, value)
+ },
+ PatternValue::Range(value) => unsafe {
+ FcPatternObjectAddRange(pattern, self.object_id, value.into_raw())
+ },
+ } == 1;
+ if pattern_add_success {
+ return Ok(());
+ }
+ Err(PatternAddError)
+ }
+}
+
+#[derive(Default, Debug)]
+pub struct FcPatternBuilder {
+ elements: Vec<PatternElement>,
+}
+
+impl FcPatternBuilder {
+ #[allow(unused)]
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ #[allow(unused)]
+ pub fn append_element(&mut self, element: PatternElement) {
+ self.elements.push(element);
+ }
+
+ #[allow(unused)]
+ pub fn create_fc_pattern(&mut self) -> Option<FcPatternWrapper> {
+ let pattern = FcPatternWrapper::new()?;
+
+ let mut family_name_encountered = false;
+
+ const FAMILY_ID: i32 = FC_FAMILY_OBJECT as i32;
+ for element in self.elements.drain(0..) {
+ if let PatternElement {
+ object_id: FAMILY_ID,
+ value: PatternValue::String(ref fam_name),
+ } = element
+ {
+ if !fam_name.is_empty() {
+ family_name_encountered = true;
+ }
+ }
+ element.append_to_fc_pattern(pattern.as_ptr()).ok()?;
+ }
+
+ if !family_name_encountered {
+ return None;
+ }
+
+ Some(pattern)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::ffi::CString;
+
+ use super::{FcPatternBuilder, FcRangeWrapper, PatternElement, PatternValue};
+ use fc_fontations_bindgen::fcint::{
+ FcPatternObjectGetBool, FcPatternObjectGetDouble, FcPatternObjectGetInteger,
+ FcPatternObjectGetRange, FcPatternObjectGetString, FcRange, FC_COLOR_OBJECT,
+ FC_FAMILY_OBJECT, FC_SLANT_OBJECT, FC_WEIGHT_OBJECT, FC_WIDTH_OBJECT,
+ };
+
+ #[test]
+ fn verify_pattern_bindings() {
+ let mut pattern_builder = FcPatternBuilder::new();
+
+ // Add a bunch of test properties.
+ pattern_builder.append_element(PatternElement::new(
+ FC_COLOR_OBJECT as i32,
+ PatternValue::Boolean(true),
+ ));
+ pattern_builder.append_element(PatternElement::new(
+ FC_WEIGHT_OBJECT as i32,
+ PatternValue::Double(800.),
+ ));
+ pattern_builder.append_element(PatternElement::new(
+ FC_SLANT_OBJECT as i32,
+ PatternValue::Integer(15),
+ ));
+
+ pattern_builder.append_element(PatternElement::new(
+ FC_WIDTH_OBJECT as i32,
+ PatternValue::Range(FcRangeWrapper::new(100., 400.).unwrap()),
+ ));
+
+ pattern_builder.append_element(PatternElement::new(
+ FC_FAMILY_OBJECT as i32,
+ PatternValue::String(CString::new("TestFont").unwrap()),
+ ));
+
+ let pattern = pattern_builder.create_fc_pattern().unwrap();
+
+ let fontconfig_pattern = pattern.as_ptr();
+ unsafe {
+ // Verify color properties.
+ let mut result: i32 = 0;
+ let get_result =
+ FcPatternObjectGetBool(fontconfig_pattern, FC_COLOR_OBJECT as i32, 0, &mut result);
+ assert_eq!(get_result, 0);
+ assert_eq!(result, 1);
+
+ // Verify weight value.
+ let mut weight_result: f64 = 0.;
+ let get_result = FcPatternObjectGetDouble(
+ fontconfig_pattern,
+ FC_WEIGHT_OBJECT as i32,
+ 0,
+ &mut weight_result,
+ );
+ assert_eq!(get_result, 0);
+ assert_eq!(weight_result, 800.0);
+
+ // Verify that weight is not a range.
+ let range_result: *mut *mut FcRange = std::mem::zeroed();
+ assert_eq!(
+ FcPatternObjectGetRange(
+ fontconfig_pattern,
+ FC_WEIGHT_OBJECT as i32,
+ 0,
+ range_result
+ ),
+ 2
+ );
+
+ // Verify slant.
+ let mut slant_result: i32 = 0;
+ let get_result = FcPatternObjectGetInteger(
+ fontconfig_pattern,
+ FC_SLANT_OBJECT as i32,
+ 0,
+ &mut slant_result,
+ );
+ assert_eq!(get_result, 0);
+ assert_eq!(slant_result, 15);
+
+ // Verify width.
+ let mut width_result: *mut FcRange = std::mem::zeroed();
+ let get_result = FcPatternObjectGetRange(
+ fontconfig_pattern,
+ FC_WIDTH_OBJECT as i32,
+ 0,
+ &mut width_result,
+ );
+ assert_eq!(get_result, 0);
+ assert_eq!((*width_result).begin, 100.);
+ assert_eq!((*width_result).end, 400.);
+
+ // Verify family name.
+ let mut family_result: *mut u8 = std::mem::zeroed();
+ let get_result = FcPatternObjectGetString(
+ fontconfig_pattern,
+ FC_FAMILY_OBJECT as i32,
+ 0,
+ &mut family_result,
+ );
+ assert_eq!(get_result, 0);
+ assert_eq!(
+ std::ffi::CStr::from_ptr(family_result as *const i8)
+ .to_str()
+ .unwrap(),
+ "TestFont"
+ );
+ }
+ }
+}
commit 5d8833ed65208c811c82d4855ce2c874684075a9
Author: Dominik Röttsches <drott at chromium.org>
Date: Mon Mar 24 11:00:51 2025 +0200
Upgrade bindgen in Fontations enabled Rust builds
Fixes issues with Rust constant generation for FC_.*_OBJECT type constants.
diff --git a/.gitlab-ci/build.sh b/.gitlab-ci/build.sh
index 55a0722..db4accc 100755
--- a/.gitlab-ci/build.sh
+++ b/.gitlab-ci/build.sh
@@ -111,6 +111,18 @@ elif [ x"$buildsys" == "xmeson" ]; then
pip install tomli
for i in "${enable[@]}"; do
buildopt+=(-D$i=enabled)
+
+ # Update bindgen on Fontations builds to improve support for constants in fcint.h
+ if [[ "$i" == "fontations" ]]; then
+ cargo install bindgen-cli
+ # Prepend the cargo bin directory to PATH
+ if [[ -d "$HOME/.cargo/bin" ]]; then
+ export PATH="$HOME/.cargo/bin:$PATH"
+ echo "Cargo bin directory added to PATH."
+ else
+ echo "Cargo bin directory not found."
+ fi
+ fi
done
for i in "${disable[@]}"; do
buildopt+=(-D$i=disabled)
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index 1a9be87..b3a82a6 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -1,7 +1,7 @@
extern crate fc_fontations_bindgen;
use fc_fontations_bindgen::{
- fcint::{FcPatternCreate, FcPatternObjectAddBool},
+ fcint::{FcPatternCreate, FcPatternObjectAddBool, FC_COLOR_OBJECT},
FcFontSet, FcFontSetAdd,
};
@@ -20,10 +20,7 @@ pub unsafe extern "C" fn add_patterns_to_fontset(
let empty_pattern = FcPatternCreate();
// Test call to ensure that an FcPrivate API function FcPatternObjectAddBool
// is accessible and can be linked to.
- // TODO(drott): This should be FC_COLOR_OBJECT imported from fcint.h,
- // but there's a separate bindgen issue that needs to be sorted out.
- const COLOR_OBJECT: i32 = 46;
- FcPatternObjectAddBool(empty_pattern, COLOR_OBJECT, 0 as i32);
+ FcPatternObjectAddBool(empty_pattern, FC_COLOR_OBJECT as i32, 0_i32);
if !font_set.is_null() {
FcFontSetAdd(
font_set,
More information about the Fontconfig
mailing list