Skip to content

Commit ae98071

Browse files
authored
Fontique: rename dlopen feature to fontconfig-dlopen (#471)
The name `dlopen` is quite generic. This feature applies specifically to the `fontconfig` dependency. No release has yet been made with this feature flag, so this change is non-breaking. --------- Signed-off-by: Nico Burns <nico@nicoburns.com>
1 parent 9b1da96 commit ae98071

File tree

2 files changed

+150
-25
lines changed

2 files changed

+150
-25
lines changed

fontique/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ system = [
3333
"dep:yeslogic-fontconfig-sys",
3434
"dep:roxmltree",
3535
]
36-
# Use dlopen to load the fontconfig library.
37-
dlopen = ["yeslogic-fontconfig-sys?/dlopen"]
36+
37+
# Use dlopen to load the fontconfig library. This allows Fontique to compile even if the
38+
# system does not have fontconfig installed, although the font fallback to system fonts
39+
# will not work properly in this case (no such fallback will occur)
40+
fontconfig-dlopen = ["yeslogic-fontconfig-sys?/dlopen"]
3841

3942
[dependencies]
4043
bytemuck = { workspace = true }

fontique/src/backend/fontconfig.rs

Lines changed: 145 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::{
1414
sync::Arc,
1515
};
1616

17-
#[cfg(feature = "dlopen")]
17+
#[cfg(feature = "fontconfig-dlopen")]
1818
use fontconfig_sys::statics::{LIB, LIB_RESULT};
1919
use fontconfig_sys::{
2020
FcChar8, FcCharSet, FcConfig, FcFontSet, FcLangSet, FcMatchKind, FcMatchPattern, FcPattern,
@@ -23,7 +23,7 @@ use fontconfig_sys::{
2323
constants::{FC_CHARSET, FC_FAMILY, FC_FILE, FC_INDEX, FC_LANG, FC_SLANT, FC_WEIGHT, FC_WIDTH},
2424
ffi_dispatch,
2525
};
26-
#[cfg(not(feature = "dlopen"))]
26+
#[cfg(not(feature = "fontconfig-dlopen"))]
2727
use fontconfig_sys::{
2828
FcCharSetAddChar, FcCharSetCopy, FcCharSetCreate, FcCharSetDestroy, FcConfigBuildFonts,
2929
FcConfigDestroy, FcConfigGetFonts, FcConfigReference, FcConfigSubstitute, FcFontMatch,
@@ -87,7 +87,10 @@ struct Pattern {
8787
impl Pattern {
8888
fn new() -> Option<Self> {
8989
Some(unsafe {
90-
Self::from_raw(ffi_dispatch!(LIB, FcPatternCreate,), Ownership::Application)?
90+
Self::from_raw(
91+
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcPatternCreate,),
92+
Ownership::Application,
93+
)?
9194
})
9295
}
9396

@@ -96,7 +99,12 @@ impl Pattern {
9699
// Don't free this object when we are dropped.
97100
if ownership == Ownership::Fontconfig {
98101
unsafe {
99-
ffi_dispatch!(LIB, FcPatternReference, inner.as_ptr());
102+
ffi_dispatch!(
103+
feature = "fontconfig-dlopen",
104+
LIB,
105+
FcPatternReference,
106+
inner.as_ptr()
107+
);
100108
}
101109
}
102110
Some(Self { inner })
@@ -106,6 +114,7 @@ impl Pattern {
106114
// All objects passed to FcPatternAddWhatever are cloned.
107115
unsafe {
108116
ffi_dispatch!(
117+
feature = "fontconfig-dlopen",
109118
LIB,
110119
FcPatternAddString,
111120
self.inner.as_ptr(),
@@ -118,6 +127,7 @@ impl Pattern {
118127
fn add_charset(&mut self, object: &CStr, s: &CharSet) -> bool {
119128
unsafe {
120129
ffi_dispatch!(
130+
feature = "fontconfig-dlopen",
121131
LIB,
122132
FcPatternAddCharSet,
123133
self.inner.as_ptr(),
@@ -130,6 +140,7 @@ impl Pattern {
130140
fn add_langset(&mut self, object: &CStr, s: &LangSet) -> bool {
131141
unsafe {
132142
ffi_dispatch!(
143+
feature = "fontconfig-dlopen",
133144
LIB,
134145
FcPatternAddLangSet,
135146
self.inner.as_ptr(),
@@ -147,6 +158,7 @@ impl Pattern {
147158
let mut dest: *mut FcChar8 = std::ptr::null_mut();
148159
let result = unsafe {
149160
ffi_dispatch!(
161+
feature = "fontconfig-dlopen",
150162
LIB,
151163
FcPatternGetString,
152164
self.inner.as_ptr(),
@@ -166,6 +178,7 @@ impl Pattern {
166178
let mut dest = 0;
167179
let result = unsafe {
168180
ffi_dispatch!(
181+
feature = "fontconfig-dlopen",
169182
LIB,
170183
FcPatternGetInteger,
171184
self.inner.as_ptr(),
@@ -183,25 +196,53 @@ impl Pattern {
183196

184197
impl Clone for Pattern {
185198
fn clone(&self) -> Self {
186-
unsafe { ffi_dispatch!(LIB, FcPatternReference, self.inner.as_ptr()) };
199+
unsafe {
200+
ffi_dispatch!(
201+
feature = "fontconfig-dlopen",
202+
LIB,
203+
FcPatternReference,
204+
self.inner.as_ptr()
205+
);
206+
};
187207
Self { inner: self.inner }
188208
}
189209
}
190210

191211
impl Drop for Pattern {
192212
fn drop(&mut self) {
193-
unsafe { ffi_dispatch!(LIB, FcPatternDestroy, self.inner.as_ptr()) };
213+
unsafe {
214+
ffi_dispatch!(
215+
feature = "fontconfig-dlopen",
216+
LIB,
217+
FcPatternDestroy,
218+
self.inner.as_ptr()
219+
);
220+
};
194221
}
195222
}
196223

197224
impl std::fmt::Debug for Pattern {
198225
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
199-
match NonNull::new(unsafe { ffi_dispatch!(LIB, FcNameUnparse, self.inner.as_ptr()) }) {
226+
match NonNull::new(unsafe {
227+
ffi_dispatch!(
228+
feature = "fontconfig-dlopen",
229+
LIB,
230+
FcNameUnparse,
231+
self.inner.as_ptr()
232+
)
233+
}) {
200234
Some(unparsed) => {
201235
let res = f.write_str(unsafe {
202236
&CStr::from_ptr(unparsed.as_ptr() as *const c_char).to_string_lossy()
203237
});
204-
unsafe { ffi_dispatch!(LIB, FcStrFree, unparsed.as_ptr()) };
238+
unsafe {
239+
ffi_dispatch!(
240+
feature = "fontconfig-dlopen",
241+
LIB,
242+
FcStrFree,
243+
unparsed.as_ptr()
244+
);
245+
};
205246
res
206247
}
207248
None => f.debug_struct("Pattern").finish(),
@@ -243,7 +284,14 @@ impl FontSet<'_> {
243284
impl Drop for FontSet<'_> {
244285
fn drop(&mut self) {
245286
if self.ownership == Ownership::Application {
246-
unsafe { ffi_dispatch!(LIB, FcFontSetDestroy, self.inner.as_ptr()) };
287+
unsafe {
288+
ffi_dispatch!(
289+
feature = "fontconfig-dlopen",
290+
LIB,
291+
FcFontSetDestroy,
292+
self.inner.as_ptr()
293+
);
294+
};
247295
}
248296
}
249297
}
@@ -282,13 +330,16 @@ struct LangSet {
282330

283331
impl LangSet {
284332
fn new() -> Option<Self> {
285-
let inner = NonNull::new(unsafe { ffi_dispatch!(LIB, FcLangSetCreate,) })?;
333+
let inner = NonNull::new(unsafe {
334+
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcLangSetCreate,)
335+
})?;
286336
Some(Self { inner })
287337
}
288338

289339
fn add(&mut self, lang: &CStr) -> bool {
290340
unsafe {
291341
ffi_dispatch!(
342+
feature = "fontconfig-dlopen",
292343
LIB,
293344
FcLangSetAdd,
294345
self.inner.as_ptr(),
@@ -300,15 +351,28 @@ impl LangSet {
300351

301352
impl Drop for LangSet {
302353
fn drop(&mut self) {
303-
unsafe { ffi_dispatch!(LIB, FcLangSetDestroy, self.inner.as_ptr()) };
354+
unsafe {
355+
ffi_dispatch!(
356+
feature = "fontconfig-dlopen",
357+
LIB,
358+
FcLangSetDestroy,
359+
self.inner.as_ptr()
360+
);
361+
};
304362
}
305363
}
306364

307365
impl Clone for LangSet {
308366
fn clone(&self) -> Self {
309367
Self {
310368
inner: unsafe {
311-
NonNull::new(ffi_dispatch!(LIB, FcLangSetCopy, self.inner.as_ptr())).unwrap()
369+
NonNull::new(ffi_dispatch!(
370+
feature = "fontconfig-dlopen",
371+
LIB,
372+
FcLangSetCopy,
373+
self.inner.as_ptr()
374+
))
375+
.unwrap()
312376
},
313377
}
314378
}
@@ -320,26 +384,49 @@ struct CharSet {
320384

321385
impl CharSet {
322386
fn new() -> Option<Self> {
323-
let inner = NonNull::new(unsafe { ffi_dispatch!(LIB, FcCharSetCreate,) })?;
387+
let inner = NonNull::new(unsafe {
388+
ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcCharSetCreate,)
389+
})?;
324390
Some(Self { inner })
325391
}
326392

327393
fn add(&mut self, c: char) -> bool {
328-
unsafe { ffi_dispatch!(LIB, FcCharSetAddChar, self.inner.as_ptr(), c as u32) != 0 }
394+
unsafe {
395+
ffi_dispatch!(
396+
feature = "fontconfig-dlopen",
397+
LIB,
398+
FcCharSetAddChar,
399+
self.inner.as_ptr(),
400+
c as u32
401+
) != 0
402+
}
329403
}
330404
}
331405

332406
impl Drop for CharSet {
333407
fn drop(&mut self) {
334-
unsafe { ffi_dispatch!(LIB, FcCharSetDestroy, self.inner.as_ptr()) };
408+
unsafe {
409+
ffi_dispatch!(
410+
feature = "fontconfig-dlopen",
411+
LIB,
412+
FcCharSetDestroy,
413+
self.inner.as_ptr()
414+
);
415+
};
335416
}
336417
}
337418

338419
impl Clone for CharSet {
339420
fn clone(&self) -> Self {
340421
Self {
341422
inner: unsafe {
342-
NonNull::new(ffi_dispatch!(LIB, FcCharSetCopy, self.inner.as_ptr())).unwrap()
423+
NonNull::new(ffi_dispatch!(
424+
feature = "fontconfig-dlopen",
425+
LIB,
426+
FcCharSetCopy,
427+
self.inner.as_ptr()
428+
))
429+
.unwrap()
343430
},
344431
}
345432
}
@@ -355,7 +442,12 @@ impl Config {
355442
// Don't free this object when we are dropped.
356443
if ownership == Ownership::Fontconfig {
357444
unsafe {
358-
ffi_dispatch!(LIB, FcConfigReference, inner.as_ptr());
445+
ffi_dispatch!(
446+
feature = "fontconfig-dlopen",
447+
LIB,
448+
FcConfigReference,
449+
inner.as_ptr()
450+
);
359451
}
360452
}
361453
Some(Self { inner })
@@ -364,6 +456,7 @@ impl Config {
364456
fn substitute(&self, pattern: &mut Pattern, kind: FcMatchKind) {
365457
unsafe {
366458
ffi_dispatch!(
459+
feature = "fontconfig-dlopen",
367460
LIB,
368461
FcConfigSubstitute,
369462
self.inner.as_ptr(),
@@ -383,6 +476,7 @@ impl Config {
383476
let font_set = unsafe {
384477
FontSet::from_raw(
385478
ffi_dispatch!(
479+
feature = "fontconfig-dlopen",
386480
LIB,
387481
FcFontSort,
388482
self.inner.as_ptr(),
@@ -407,6 +501,7 @@ impl Config {
407501
let pattern = unsafe {
408502
Pattern::from_raw(
409503
ffi_dispatch!(
504+
feature = "fontconfig-dlopen",
410505
LIB,
411506
FcFontMatch,
412507
self.inner.as_ptr(),
@@ -428,6 +523,7 @@ impl Config {
428523
unsafe {
429524
Pattern::from_raw(
430525
ffi_dispatch!(
526+
feature = "fontconfig-dlopen",
431527
LIB,
432528
FcFontRenderPrepare,
433529
self.inner.as_ptr(),
@@ -442,14 +538,28 @@ impl Config {
442538

443539
impl Clone for Config {
444540
fn clone(&self) -> Self {
445-
unsafe { ffi_dispatch!(LIB, FcConfigReference, self.inner.as_ptr()) };
541+
unsafe {
542+
ffi_dispatch!(
543+
feature = "fontconfig-dlopen",
544+
LIB,
545+
FcConfigReference,
546+
self.inner.as_ptr()
547+
)
548+
};
446549
Self { inner: self.inner }
447550
}
448551
}
449552

450553
impl Drop for Config {
451554
fn drop(&mut self) {
452-
unsafe { ffi_dispatch!(LIB, FcConfigDestroy, self.inner.as_ptr()) };
555+
unsafe {
556+
ffi_dispatch!(
557+
feature = "fontconfig-dlopen",
558+
LIB,
559+
FcConfigDestroy,
560+
self.inner.as_ptr()
561+
);
562+
};
453563
}
454564
}
455565

@@ -495,19 +605,25 @@ impl SystemFonts {
495605
// return a `SystemFonts` with no `config`. All our methods will return
496606
// `None` and shouldn't attempt any FFI calls because the first thing we
497607
// do is check for `config`.
498-
#[cfg(feature = "dlopen")]
608+
#[cfg(feature = "fontconfig-dlopen")]
499609
if LIB_RESULT.is_err() {
500610
return Self::default();
501611
}
502612

503613
// Initialize the config
504-
let config = unsafe { ffi_dispatch!(LIB, FcInitLoadConfig,) };
614+
let config =
615+
unsafe { ffi_dispatch!(feature = "fontconfig-dlopen", LIB, FcInitLoadConfig,) };
505616
// fontconfig returns a new config object each time we call FcInitLoadConfig
506617
let Some(config) = (unsafe { Config::from_raw(config, Ownership::Application) }) else {
507618
return Self::default();
508619
};
509620
unsafe {
510-
ffi_dispatch!(LIB, FcConfigBuildFonts, config.inner.as_ptr());
621+
ffi_dispatch!(
622+
feature = "fontconfig-dlopen",
623+
LIB,
624+
FcConfigBuildFonts,
625+
config.inner.as_ptr()
626+
);
511627
}
512628

513629
// Get all the fonts.
@@ -523,7 +639,13 @@ impl SystemFonts {
523639
// But we're not doing that.
524640
let Some(font_set) = (unsafe {
525641
FontSet::from_raw(
526-
ffi_dispatch!(LIB, FcConfigGetFonts, config.inner.as_ptr(), FcSetSystem),
642+
ffi_dispatch!(
643+
feature = "fontconfig-dlopen",
644+
LIB,
645+
FcConfigGetFonts,
646+
config.inner.as_ptr(),
647+
FcSetSystem
648+
),
527649
Ownership::Fontconfig,
528650
)
529651
}) else {

0 commit comments

Comments
 (0)