fontconfig: Branch 'main' - 5 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu May 22 05:54:32 UTC 2025
fc-fontations/charset.rs | 90 +++++++++++++++++++++++++++
fc-fontations/instance_enumerate.rs | 1
fc-fontations/lang.rs | 67 ++++++++++++++++++++
fc-fontations/mod.rs | 87 ++++++++++++++++++++++++--
fc-fontations/pattern_bindings/fc_wrapper.rs | 17 ++++-
fc-fontations/pattern_bindings/mod.rs | 28 ++++++--
test/test_fontations_ft_query.py | 5 +
7 files changed, 280 insertions(+), 15 deletions(-)
New commits:
commit 1c63ed3cffefb21defaafd5ba4e52af77c53b8ad
Merge: 8cf0ce7 5e8e9a0
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu May 22 05:54:29 2025 +0000
Merge branch 'charset' into 'main'
[Fontations] Add charset, langset, symbol, fontwrapper and file pattern elements
See merge request fontconfig/fontconfig!404
commit 5e8e9a0f0cdd140eae4969d803a4d5a611f86bae
Author: Dominik Röttsches <drott at chromium.org>
Date: Fri May 16 12:29:16 2025 +0000
[Fontations] Add woff wrapper and filename if file is woff or woff2
diff --git a/fc-fontations/instance_enumerate.rs b/fc-fontations/instance_enumerate.rs
index 84deb08..89b26fe 100644
--- a/fc-fontations/instance_enumerate.rs
+++ b/fc-fontations/instance_enumerate.rs
@@ -29,7 +29,6 @@ use read_fonts::{
};
use skrifa::MetadataProvider;
-#[allow(unused)]
pub fn fonts_and_indices(
file_ref: Option<FileRef>,
) -> impl Iterator<Item = (FontRef<'_>, Option<i32>)> {
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index bd6a064..4fba651 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -40,9 +40,9 @@ use names::add_names;
use fc_fontations_bindgen::{
fcint::{
FcFreeTypeLangSet, FC_CAPABILITY_OBJECT, FC_CHARSET_OBJECT, FC_COLOR_OBJECT,
- FC_DECORATIVE_OBJECT, FC_FILE_OBJECT, FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT,
- FC_FONT_HAS_HINT_OBJECT, FC_FONT_WRAPPER_OBJECT, FC_FOUNDRY_OBJECT, FC_LANG_OBJECT,
- FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT, FC_SYMBOL_OBJECT,
+ FC_DECORATIVE_OBJECT, FC_FILE_OBJECT, FC_FONTFORMAT_OBJECT,
+ FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT, FC_FONT_WRAPPER_OBJECT, FC_FOUNDRY_OBJECT,
+ FC_LANG_OBJECT, FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT, FC_SYMBOL_OBJECT,
},
FcFontSet, FcFontSetAdd, FcPattern,
};
@@ -79,14 +79,24 @@ pub unsafe extern "C" fn add_patterns_to_fontset(
let fileref = FileRef::new(&bytes).ok();
let fonts = fonts_and_indices(fileref);
+
+ let mut patterns_added: u32 = 0;
for (font, ttc_index) in fonts {
for pattern in build_patterns_for_font(&font, font_file, ttc_index) {
if FcFontSetAdd(font_set, pattern) == 0 {
return 0;
}
+ patterns_added += 1;
}
}
+ // Fontations does not natively understand WOFF/WOFF2 compressed file,
+ // if we are asked to scan one of those, only add wrapper information
+ // and filename.
+ if patterns_added == 0 {
+ try_append_woff_pattern(font_set, bytes.as_slice(), font_file);
+ }
+
1
}
@@ -102,6 +112,24 @@ enum InstanceMode {
Variable,
}
+fn try_append_woff_pattern(font_set: *mut FcFontSet, bytes: &[u8], font_file: *const libc::c_char) {
+ let wrapper: Option<CString> = match bytes.get(0..4) {
+ Some(b"wOFF") => CString::new("WOFF").ok(),
+ Some(b"wOF2") => CString::new("WOFF2").ok(),
+ _ => None,
+ };
+
+ if let Some(w) = wrapper {
+ let mut pattern = FcPatternBuilder::new();
+ pattern.append_element(PatternElement::new(FC_FONT_WRAPPER_OBJECT as i32, w.into()));
+ add_font_file_name(&mut pattern, font_file);
+
+ pattern
+ .create_fc_pattern()
+ .map(|p| unsafe { FcFontSetAdd(font_set, p.into_raw() as *mut FcPattern) });
+ }
+}
+
fn has_one_of_tables<I>(font_ref: &FontRef, tags: I) -> bool
where
I: IntoIterator,
@@ -127,6 +155,17 @@ fn has_hint(font_ref: &FontRef) -> bool {
false
}
+fn add_font_file_name(pattern: &mut FcPatternBuilder, font_file: *const libc::c_char) {
+ if !font_file.is_null() {
+ let filename = unsafe { std::ffi::CStr::from_ptr(font_file) };
+
+ pattern.append_element(PatternElement::new(
+ FC_FILE_OBJECT as i32,
+ filename.to_owned().into(),
+ ));
+ }
+}
+
fn build_patterns_for_font(
font: &FontRef,
font_file: *const libc::c_char,
@@ -220,14 +259,7 @@ fn build_patterns_for_font(
.unwrap_or_default()
.to_bits();
- if !font_file.is_null() {
- let filename = unsafe { std::ffi::CStr::from_ptr(font_file) };
-
- pattern.append_element(PatternElement::new(
- FC_FILE_OBJECT as i32,
- filename.to_owned().into(),
- ));
- }
+ add_font_file_name(&mut pattern, font_file);
pattern.append_element(PatternElement::new(
FC_FONT_WRAPPER_OBJECT as i32,
diff --git a/fc-fontations/pattern_bindings/mod.rs b/fc-fontations/pattern_bindings/mod.rs
index d3e0f37..990d5e1 100644
--- a/fc-fontations/pattern_bindings/mod.rs
+++ b/fc-fontations/pattern_bindings/mod.rs
@@ -32,7 +32,7 @@ use std::fmt::Debug;
use fc_fontations_bindgen::fcint::{
FcPattern, FcPatternObjectAddBool, FcPatternObjectAddCharSet, FcPatternObjectAddDouble,
FcPatternObjectAddInteger, FcPatternObjectAddLangSet, FcPatternObjectAddRange,
- FcPatternObjectAddString, FC_FAMILY_OBJECT,
+ FcPatternObjectAddString, FC_FAMILY_OBJECT, FC_FILE_OBJECT,
};
use fc_wrapper::{FcCharSetWrapper, FcLangSetWrapper, FcPatternWrapper, FcRangeWrapper};
@@ -165,23 +165,25 @@ impl FcPatternBuilder {
pub fn create_fc_pattern(&mut self) -> Option<FcPatternWrapper> {
let pattern = FcPatternWrapper::new()?;
- let mut family_name_encountered = false;
+ let mut family_name_or_file_name_encountered = false;
const FAMILY_ID: i32 = FC_FAMILY_OBJECT as i32;
+ const FILE_ID: i32 = FC_FILE_OBJECT as i32;
+
for element in self.elements.drain(0..) {
if let PatternElement {
- object_id: FAMILY_ID,
- value: PatternValue::String(ref fam_name),
+ object_id: FAMILY_ID | FILE_ID,
+ value: PatternValue::String(ref file_fam_name),
} = element
{
- if !fam_name.is_empty() {
- family_name_encountered = true;
+ if !file_fam_name.is_empty() {
+ family_name_or_file_name_encountered = true;
}
}
element.append_to_fc_pattern(pattern.as_ptr()).ok()?;
}
- if !family_name_encountered {
+ if !family_name_or_file_name_encountered {
return None;
}
commit 9fa2ba1d092b3f22153cc6ce1d8470d14226199c
Author: Dominik Röttsches <drott at chromium.org>
Date: Wed May 14 12:35:47 2025 +0300
[Fontations] Add fontwrapper, filename and symbol elements to pattern
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index 2758679..bd6a064 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -40,14 +40,16 @@ use names::add_names;
use fc_fontations_bindgen::{
fcint::{
FcFreeTypeLangSet, FC_CAPABILITY_OBJECT, FC_CHARSET_OBJECT, FC_COLOR_OBJECT,
- FC_DECORATIVE_OBJECT, FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT,
- FC_FOUNDRY_OBJECT, FC_LANG_OBJECT, FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT,
+ FC_DECORATIVE_OBJECT, FC_FILE_OBJECT, FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT,
+ FC_FONT_HAS_HINT_OBJECT, FC_FONT_WRAPPER_OBJECT, FC_FOUNDRY_OBJECT, FC_LANG_OBJECT,
+ FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT, FC_SYMBOL_OBJECT,
},
FcFontSet, FcFontSetAdd, FcPattern,
};
use font_types::Tag;
use pattern_bindings::{fc_wrapper::FcLangSetWrapper, FcPatternBuilder, PatternElement};
+use skrifa::MetadataProvider;
use std::str::FromStr;
use read_fonts::{FileRef, FontRef, TableProvider};
@@ -127,7 +129,7 @@ fn has_hint(font_ref: &FontRef) -> bool {
fn build_patterns_for_font(
font: &FontRef,
- _: *const libc::c_char,
+ font_file: *const libc::c_char,
ttc_index: Option<i32>,
) -> Vec<*mut FcPattern> {
let mut pattern = FcPatternBuilder::new();
@@ -178,6 +180,11 @@ fn build_patterns_for_font(
foundry_string.into(),
));
+ pattern.append_element(PatternElement::new(
+ FC_SYMBOL_OBJECT as i32,
+ font.charmap().is_symbol().into(),
+ ));
+
if let Some(capabilities) = make_capabilities(font) {
pattern.append_element(PatternElement::new(
FC_CAPABILITY_OBJECT as i32,
@@ -213,6 +220,20 @@ fn build_patterns_for_font(
.unwrap_or_default()
.to_bits();
+ if !font_file.is_null() {
+ let filename = unsafe { std::ffi::CStr::from_ptr(font_file) };
+
+ pattern.append_element(PatternElement::new(
+ FC_FILE_OBJECT as i32,
+ filename.to_owned().into(),
+ ));
+ }
+
+ pattern.append_element(PatternElement::new(
+ FC_FONT_WRAPPER_OBJECT as i32,
+ CString::new("SFNT").unwrap().into(),
+ ));
+
pattern.append_element(PatternElement::new(
FC_FONTVERSION_OBJECT as i32,
version.into(),
diff --git a/test/test_fontations_ft_query.py b/test/test_fontations_ft_query.py
index 04fe4da..643f2e9 100644
--- a/test/test_fontations_ft_query.py
+++ b/test/test_fontations_ft_query.py
@@ -68,6 +68,9 @@ def test_fontations_freetype_fcquery_equal(font_file):
"capability",
"charset",
"langset",
+ "symbol",
+ "fontwrapper",
+ "file",
]
format_string = ":".join(
"%{" + entity + "}" for entity in supported_format_entitites
commit a82ab0f3cf76525cb87b2082ea706b50c3b62543
Author: Dominik Röttsches <drott at chromium.org>
Date: Wed May 14 11:48:47 2025 +0300
[Fontations] Add langset pattern element
Process charset into a langset, taking into account
the special processing that FcFreeTypeLangSet does to
not extend advertised langset support beyond what the font
advertises in OS/2.
diff --git a/fc-fontations/lang.rs b/fc-fontations/lang.rs
new file mode 100644
index 0000000..b1f7529
--- /dev/null
+++ b/fc-fontations/lang.rs
@@ -0,0 +1,67 @@
+/*
+ * fontconfig/fc-fontations/lang.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 read_fonts::TableProvider;
+use skrifa::FontRef;
+use std::ffi::CString;
+
+// See logic and comment in FcFreeTypeLangSet, check for Han charsets to make fonts
+// which advertise support for a single language not support other Han languages.
+fn exclusive_lang_in_codepage_range(codepage_ranges: u64) -> Option<String> {
+ // u32 is the position of the bit in the OS/2 codepage range.
+ const LANG_MAP: [(u32, &str); 4] = [(17, "ja"), (18, "zh-cn"), (19, "ko"), (20, "zh-tw")];
+
+ let mut found_languages = LANG_MAP
+ .iter()
+ .filter(move |bit_lang_pair| codepage_ranges & (1 << bit_lang_pair.0) != 0);
+
+ match (found_languages.next(), found_languages.next()) {
+ (Some(bit_lang_pair), None) => Some(bit_lang_pair.1.to_string()),
+ _ => None,
+ }
+}
+
+// Returns the language identifier string if according to OS/2 codepage ranges
+// the font advertises support for only one Han font, otherwise none.
+pub fn exclusive_lang(font: &FontRef) -> Option<CString> {
+ let os2 = font.os2().ok()?;
+ let codepage_ranges: u64 =
+ ((os2.ul_code_page_range_2()? as u64) << 32) + os2.ul_code_page_range_1()? as u64;
+
+ exclusive_lang_in_codepage_range(codepage_ranges).and_then(|string| CString::new(string).ok())
+}
+
+#[cfg(test)]
+mod test {
+ use super::exclusive_lang_in_codepage_range;
+ #[test]
+ fn exclusive_lang() {
+ let non_exclusive = 1 << 17 + 1 << 20;
+ assert!(exclusive_lang_in_codepage_range(non_exclusive).is_none());
+ let exclusive = 1 << 17;
+ assert_eq!(exclusive_lang_in_codepage_range(exclusive).unwrap(), "ja");
+ let unmatched_non_han = 1 << 4 + 1 << 21;
+ assert!(exclusive_lang_in_codepage_range(unmatched_non_han).is_none());
+ }
+}
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index 1568084..2758679 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -27,25 +27,27 @@ mod capabilities;
mod charset;
mod foundries;
mod instance_enumerate;
+mod lang;
mod names;
mod pattern_bindings;
use attributes::append_style_elements;
use capabilities::make_capabilities;
use foundries::make_foundry;
+use lang::exclusive_lang;
use names::add_names;
use fc_fontations_bindgen::{
fcint::{
- FC_CAPABILITY_OBJECT, FC_CHARSET_OBJECT, FC_COLOR_OBJECT, FC_DECORATIVE_OBJECT,
- FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT, FC_FOUNDRY_OBJECT,
- FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT,
+ FcFreeTypeLangSet, FC_CAPABILITY_OBJECT, FC_CHARSET_OBJECT, FC_COLOR_OBJECT,
+ FC_DECORATIVE_OBJECT, FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT,
+ FC_FOUNDRY_OBJECT, FC_LANG_OBJECT, FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT,
},
FcFontSet, FcFontSetAdd, FcPattern,
};
use font_types::Tag;
-use pattern_bindings::{FcPatternBuilder, PatternElement};
+use pattern_bindings::{fc_wrapper::FcLangSetWrapper, FcPatternBuilder, PatternElement};
use std::str::FromStr;
use read_fonts::{FileRef, FontRef, TableProvider};
@@ -183,11 +185,25 @@ fn build_patterns_for_font(
));
};
+ // CharSet and Langset.
if let Some(charset) = charset::make_charset(font) {
- pattern.append_element(PatternElement::new(
- FC_CHARSET_OBJECT as i32,
- charset.into(),
- ));
+ let exclusive_lang =
+ exclusive_lang(font).map_or(std::ptr::null(), |lang| lang.as_bytes_with_nul().as_ptr());
+
+ unsafe {
+ let langset =
+ FcLangSetWrapper::from_raw(FcFreeTypeLangSet(charset.as_ptr(), exclusive_lang));
+
+ pattern.append_element(PatternElement::new(
+ FC_CHARSET_OBJECT as i32,
+ charset.into(),
+ ));
+
+ // TODO: Move FcFreeTypeLangSet to a different name, as the function does not actually depend on FreeType.
+ if !langset.is_null() {
+ pattern.append_element(PatternElement::new(FC_LANG_OBJECT as i32, langset.into()));
+ }
+ }
};
let version = font
diff --git a/fc-fontations/pattern_bindings/fc_wrapper.rs b/fc-fontations/pattern_bindings/fc_wrapper.rs
index a8b90f4..0fa727e 100644
--- a/fc-fontations/pattern_bindings/fc_wrapper.rs
+++ b/fc-fontations/pattern_bindings/fc_wrapper.rs
@@ -181,4 +181,8 @@ impl FcLangSetWrapper {
})
}
}
+
+ pub fn is_null(&self) -> bool {
+ self.inner.is_null()
+ }
}
diff --git a/fc-fontations/pattern_bindings/mod.rs b/fc-fontations/pattern_bindings/mod.rs
index 5f8c8a4..d3e0f37 100644
--- a/fc-fontations/pattern_bindings/mod.rs
+++ b/fc-fontations/pattern_bindings/mod.rs
@@ -85,6 +85,12 @@ impl From<FcCharSetWrapper> for PatternValue {
}
}
+impl From<FcLangSetWrapper> for PatternValue {
+ fn from(value: FcLangSetWrapper) -> Self {
+ PatternValue::LangSet(value)
+ }
+}
+
#[derive(Debug, Clone)]
pub struct PatternElement {
object_id: i32,
diff --git a/test/test_fontations_ft_query.py b/test/test_fontations_ft_query.py
index eaf7a15..04fe4da 100644
--- a/test/test_fontations_ft_query.py
+++ b/test/test_fontations_ft_query.py
@@ -67,6 +67,7 @@ def test_fontations_freetype_fcquery_equal(font_file):
"slant",
"capability",
"charset",
+ "langset",
]
format_string = ":".join(
"%{" + entity + "}" for entity in supported_format_entitites
commit 614275b0d8b29ea350929053deea576c9fca1af0
Author: Dominik Röttsches <drott at chromium.org>
Date: Wed May 14 10:41:41 2025 +0300
[Fontations] Add charset pattern element
Generate charset from cmap mappings, check for ink in control
characters, same as in the FreeType-backed fccharset.c.
diff --git a/fc-fontations/charset.rs b/fc-fontations/charset.rs
new file mode 100644
index 0000000..7affb09
--- /dev/null
+++ b/fc-fontations/charset.rs
@@ -0,0 +1,90 @@
+/*
+ * fontconfig/fc-fontations/charset.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 font_types::GlyphId;
+
+use skrifa::outline::DrawSettings;
+use skrifa::prelude::{LocationRef, Size};
+use skrifa::{outline::pen::OutlinePen, FontRef, MetadataProvider};
+
+use crate::pattern_bindings::fc_wrapper::FcCharSetWrapper;
+
+struct HasAnyContourPen {
+ has_ink: bool,
+}
+
+impl HasAnyContourPen {
+ pub fn new() -> Self {
+ Self { has_ink: false }
+ }
+}
+
+impl OutlinePen for HasAnyContourPen {
+ fn move_to(&mut self, _x: f32, _y: f32) {}
+ fn line_to(&mut self, _x: f32, _y: f32) {}
+ fn quad_to(&mut self, _cx0: f32, _cy0: f32, _x: f32, _y: f32) {}
+ fn curve_to(&mut self, _cx0: f32, _cy0: f32, _cx1: f32, _cy1: f32, _x: f32, _y: f32) {}
+ fn close(&mut self) {
+ self.has_ink = true;
+ }
+}
+
+const CONTROL_CHAR_MAX: u32 = 0x1F;
+
+// For control characters, check for whether they have ink/any-contour since
+// these might be mapped to space. Simulates fcfreetype.c behavior.
+// Specifically, FreeType checks for face->glyph->outline.n_contours - so,
+// number of contours, not for actually pixel coverage / contour area.
+fn control_char_without_ink(font: &FontRef, char: u32, glyph: GlyphId) -> bool {
+ let mut pen = HasAnyContourPen::new();
+ if char <= CONTROL_CHAR_MAX {
+ font.outline_glyphs().get(glyph).and_then(|outline| {
+ outline
+ .draw(
+ DrawSettings::unhinted(Size::new(12.0), LocationRef::default()),
+ &mut pen,
+ )
+ .ok()
+ });
+ if !pen.has_ink {
+ return true;
+ }
+ }
+ false
+}
+
+pub fn make_charset(font: &FontRef) -> Option<FcCharSetWrapper> {
+ let mut charset = FcCharSetWrapper::new()?;
+ let mappings = font.charmap().mappings();
+ for mapping in mappings {
+ if control_char_without_ink(font, mapping.0, mapping.1) {
+ continue;
+ }
+
+ if charset.add_char(mapping.0).is_err() {
+ return None;
+ }
+ }
+ Some(charset)
+}
diff --git a/fc-fontations/mod.rs b/fc-fontations/mod.rs
index 72f5ac7..1568084 100644
--- a/fc-fontations/mod.rs
+++ b/fc-fontations/mod.rs
@@ -24,6 +24,7 @@
mod attributes;
mod capabilities;
+mod charset;
mod foundries;
mod instance_enumerate;
mod names;
@@ -36,9 +37,9 @@ use names::add_names;
use fc_fontations_bindgen::{
fcint::{
- FC_CAPABILITY_OBJECT, FC_COLOR_OBJECT, FC_DECORATIVE_OBJECT, FC_FONTFORMAT_OBJECT,
- FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT, FC_FOUNDRY_OBJECT, FC_OUTLINE_OBJECT,
- FC_SCALABLE_OBJECT,
+ FC_CAPABILITY_OBJECT, FC_CHARSET_OBJECT, FC_COLOR_OBJECT, FC_DECORATIVE_OBJECT,
+ FC_FONTFORMAT_OBJECT, FC_FONTVERSION_OBJECT, FC_FONT_HAS_HINT_OBJECT, FC_FOUNDRY_OBJECT,
+ FC_OUTLINE_OBJECT, FC_SCALABLE_OBJECT,
},
FcFontSet, FcFontSetAdd, FcPattern,
};
@@ -182,6 +183,13 @@ fn build_patterns_for_font(
));
};
+ if let Some(charset) = charset::make_charset(font) {
+ pattern.append_element(PatternElement::new(
+ FC_CHARSET_OBJECT as i32,
+ charset.into(),
+ ));
+ };
+
let version = font
.head()
.ok()
diff --git a/fc-fontations/pattern_bindings/fc_wrapper.rs b/fc-fontations/pattern_bindings/fc_wrapper.rs
index ccc3269..a8b90f4 100644
--- a/fc-fontations/pattern_bindings/fc_wrapper.rs
+++ b/fc-fontations/pattern_bindings/fc_wrapper.rs
@@ -28,7 +28,7 @@ use fc_fontations_bindgen::{
FcPatternCreate, FcPatternDestroy, FcRange, FcRangeCopy, FcRangeCreateDouble,
FcRangeDestroy,
},
- FcLangSetCopy, FcLangSetCreate, FcLangSetDestroy,
+ FcCharSetAddChar, FcLangSetCopy, FcLangSetCreate, FcLangSetDestroy,
};
macro_rules! wrap_fc_object {
@@ -134,7 +134,6 @@ wrap_fc_object! {
}
impl FcCharSetWrapper {
- #[allow(unused)]
pub fn new() -> Option<Self> {
let created_charset: *mut FcCharSet;
unsafe {
@@ -148,6 +147,16 @@ impl FcCharSetWrapper {
})
}
}
+
+ pub fn add_char(&mut self, char: u32) -> Result<(), ()> {
+ unsafe {
+ if FcCharSetAddChar(self.as_ptr(), char) == 1 {
+ Ok(())
+ } else {
+ Err(())
+ }
+ }
+ }
}
wrap_fc_object! {
diff --git a/fc-fontations/pattern_bindings/mod.rs b/fc-fontations/pattern_bindings/mod.rs
index 32f604a..5f8c8a4 100644
--- a/fc-fontations/pattern_bindings/mod.rs
+++ b/fc-fontations/pattern_bindings/mod.rs
@@ -79,6 +79,12 @@ impl From<FcRangeWrapper> for PatternValue {
}
}
+impl From<FcCharSetWrapper> for PatternValue {
+ fn from(value: FcCharSetWrapper) -> Self {
+ PatternValue::CharSet(value)
+ }
+}
+
#[derive(Debug, Clone)]
pub struct PatternElement {
object_id: i32,
diff --git a/test/test_fontations_ft_query.py b/test/test_fontations_ft_query.py
index b7baf0b..eaf7a15 100644
--- a/test/test_fontations_ft_query.py
+++ b/test/test_fontations_ft_query.py
@@ -66,6 +66,7 @@ def test_fontations_freetype_fcquery_equal(font_file):
"width",
"slant",
"capability",
+ "charset",
]
format_string = ":".join(
"%{" + entity + "}" for entity in supported_format_entitites
More information about the Fontconfig
mailing list