├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── ci
└── ldd-grep
├── fontconfig-sys
├── Cargo.toml
├── LICENSE
├── README.md
├── build.rs
└── src
│ └── lib.rs
└── fontconfig
├── Cargo.toml
├── LICENSE
├── README.md
├── build.rs
└── src
└── lib.rs
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: ["master"]
6 | tags: ["v[0-9]+.[0-9]+.[0-9]+", "yeslogic-fontconfig-sys-[0-9]+.[0-9]+.[0-9]+"]
7 | pull_request:
8 | branches: ["master"]
9 | workflow_dispatch:
10 |
11 | jobs:
12 | ci:
13 | strategy:
14 | matrix:
15 | rust: [stable, 1.77.0]
16 | os: [ubuntu-latest]
17 | runs-on: ${{ matrix.os }}
18 | steps:
19 | - uses: actions/checkout@v3
20 | - uses: dtolnay/rust-toolchain@v1
21 | with:
22 | toolchain: ${{ matrix.rust }}
23 | - run: sudo apt-get -y install libfontconfig1-dev jq
24 | - run: cargo test
25 | - run: |
26 | if [ "${{matrix.rust}}" = "stable" ]; then
27 | ./ci/ldd-grep
28 | else
29 | true
30 | fi
31 | - run: cargo test --features dlopen --manifest-path fontconfig/Cargo.toml
32 | - run: |
33 | if [ "${{matrix.rust}}" = "stable" ]; then
34 | ./ci/ldd-grep -v -- --features dlopen
35 | else
36 | true
37 | fi
38 | - run: RUST_FONTCONFIG_DLOPEN=on cargo test
39 | - run: |
40 | if [ "${{matrix.rust}}" = "stable" ]; then
41 | RUST_FONTCONFIG_DLOPEN=on ./ci/ldd-grep -v
42 | else
43 | true
44 | fi
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /Cargo.lock
3 | *.swp
4 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [
4 | "fontconfig-sys",
5 | "fontconfig"
6 | ]
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright 2019 YesLogic Pty. Ltd.
4 | Copyright 2016 Manuel Reinhardt
5 | Copyright 2014 Austin Bonander
6 | Copyright 2013 The Servo Project Developers.
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | fontconfig
2 | ==========
3 |
4 |
14 |
15 |
16 |
17 | A wrapper around [freedesktop.org's Fontconfig library][homepage], for locating fonts on UNIX-like systems such as Linux and BSD. Requires Fontconfig to be installed.
18 |
19 | Dependencies
20 | ------------
21 |
22 | This crate is a wrapper around the Fontconfig C-library, thus it must be installed. If your OS has separate `dev`/`devel` packages, then you will need to install the that version of the package. Below is the package name for a few operating systems. If your system is not listed, a search of your package repository for `fontconfig` should find what you need.
23 |
24 | * Alpine Linux: `fontconfig-dev`
25 | * Arch Linux: `fontconfig`
26 | * Debian-based systems: `libfontconfig1-dev`
27 | * FreeBSD: `fontconfig`
28 | * Nix: `fontconfig`, `pkg-config` (tested on nixos-unstable)
29 | * Void Linux: `fontconfig-devel`
30 |
31 | Usage
32 | -----
33 |
34 | `main.rs`:
35 |
36 | ```rust
37 | use fontconfig::Fontconfig;
38 |
39 | fn main() {
40 | let fc = Fontconfig::new().unwrap();
41 | // `Fontconfig::find()` returns `Option` (will rarely be `None` but still could be)
42 | let font = fc.find("freeserif", None).unwrap();
43 | // `name` is a `String`, `path` is a `Path`
44 | println!("Name: {}\nPath: {}", font.name, font.path.display());
45 | }
46 | ```
47 |
48 | You could then, for example, use `font.path` to create a `GlyphCache` from [`opengl_graphics`][gl] and pass it to [`conrod`][conrod].
49 |
50 | ### Cargo Features
51 |
52 | | Feature | Description | Default Enabled | Extra Dependencies |
53 | |---------------|-----------------------------------|:---------------:|-----------------------|
54 | | `dlopen` | [dlopen] libfontconfig at runtime | ❌ | |
55 |
56 | The `dlopen` feature enables building this crate without dynamically linking to the Fontconfig C library at link time. Instead, Fontconfig will be dynamically loaded at runtime with the [dlopen] function. This can be useful in cross-compiling situations as you don't need to have a version of Fontcofig available for the target platform available at compile time.
57 |
58 | Other Fontconfig Crates
59 | -----------------------
60 |
61 | * [servo-fontconfig] — This crate provides a low-level interface only. It
62 | depends on [servo-fontconfig-sys], which will fall back to building a
63 | vendored version of Fontconfig if a compatible version can't be found. It
64 | in-turn depends on [expat-sys], which does the same thing regarding a vendored
65 | version of Expat. This makes it easier if you are distributing a code base
66 | that needs Fontconfig, but provides less control over the libraries that will
67 | be used.
68 | * [fontconfig-sys] — superseded by [yeslogic-fontconfig-sys].
69 | * [yeslogic-fontconfig] — This crate was previously published under this name before we were given access to publish it as [fontconfig].
70 |
71 | For our needs in [Prince] we wanted higher-level bindings that did not fall back on vendored versions of libraries, which is what the crates in this repo provide.
72 |
73 | Credits
74 | -------
75 |
76 | Thanks to [Austin Bonander][abonander] for originally creating the
77 | `fontconfig` crate and [allowing us to publish ours under that
78 | name](https://github.com/abonander/fontconfig-rs/issues/9).
79 |
80 | [conrod]: https://github.com/PistonDevelopers/conrod
81 | [expat-sys]: https://crates.io/crates/expat-sys
82 | [fontconfig-sys]: https://crates.io/crates/fontconfig-sys
83 | [fontconfig]: https://crates.io/crates/fontconfig
84 | [gl]: https://github.com/PistonDevelopers/opengl_graphics
85 | [homepage]: https://www.freedesktop.org/wiki/Software/fontconfig/
86 | [Prince]: https://www.princexml.com/
87 | [servo-fontconfig-sys]: https://crates.io/crates/servo-fontconfig-sys
88 | [servo-fontconfig]: https://crates.io/crates/servo-fontconfig
89 | [yeslogic-fontconfig]: https://crates.io/crates/yeslogic-fontconfig
90 | [yeslogic-fontconfig-sys]: https://crates.io/crates/yeslogic-fontconfig-sys
91 | [abonander]: https://github.com/abonander
92 | [dlopen]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html
93 | [dlib]: https://crates.io/crates/dlib
94 |
--------------------------------------------------------------------------------
/ci/ldd-grep:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -eu
4 |
5 | INVERT_MATCH=""
6 | while getopts "v" opt; do
7 | case "$opt" in
8 | v) INVERT_MATCH=1;;
9 | *) ;;
10 | esac
11 | done
12 |
13 | shift $((OPTIND - 1))
14 |
15 | EXE=$(cargo test --no-run --message-format=json "$@" | \
16 | jq --raw-output 'select(.reason == "compiler-artifact" and .target.name == "fontconfig" and .target.test and .executable != null) | .executable')
17 |
18 |
19 | FOUND=""
20 | if ldd "$EXE" | grep --quiet libfontconfig ; then
21 | FOUND=1
22 | fi
23 |
24 | if [ -z $INVERT_MATCH ]; then
25 | if [ -z $FOUND ]; then
26 | echo "fail - libfontconfig not found when expected"
27 | exit 1
28 | else
29 | echo "ok - libfontconfig found"
30 | fi
31 | else
32 | if [ -z $FOUND ]; then
33 | echo "ok - libfontconfig not found"
34 | else
35 | echo "fail - libfontconfig found when not expected"
36 | exit 1
37 | fi
38 | fi
39 |
--------------------------------------------------------------------------------
/fontconfig-sys/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "yeslogic-fontconfig-sys"
3 | version = "6.0.0"
4 | edition = "2021"
5 | rust-version = "1.77"
6 | authors = [
7 | "Austin Bonander ",
8 | "The Servo Project Developers",
9 | "YesLogic Pty. Ltd. "
10 | ]
11 | license = "MIT"
12 |
13 | description = "Raw bindings to Fontconfig without a vendored C library"
14 | keywords = ["font", "bindings", "fontconfig", "sys"]
15 | categories = ["text-processing"]
16 |
17 | homepage = "https://github.com/yeslogic/fontconfig-rs"
18 | documentation = "https://docs.rs/crate/yeslogic-fontconfig-sys"
19 | repository = "https://github.com/yeslogic/fontconfig-rs"
20 |
21 | links = "fontconfig"
22 |
23 | [lib]
24 | name = "fontconfig_sys"
25 |
26 | [dependencies]
27 | dlib = "0.5.0"
28 | # This can't be optional because build.rs can't conditionally enable an
29 | # optional dependency:
30 | #
31 | # > Note that this does not affect Cargo's dependency resolution. This cannot
32 | # > be used to enable an optional dependency, or enable other Cargo features.
33 | #
34 | # - https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-cfg
35 | once_cell = "1.9.0"
36 |
37 | [features]
38 | dlopen = []
39 |
40 | [build-dependencies]
41 | pkg-config = "0.3"
42 |
--------------------------------------------------------------------------------
/fontconfig-sys/LICENSE:
--------------------------------------------------------------------------------
1 | ../LICENSE
--------------------------------------------------------------------------------
/fontconfig-sys/README.md:
--------------------------------------------------------------------------------
1 | fontconfig-sys
2 | ==============
3 |
4 | Raw bindings to [freedesktop.org's Fontconfig library][fontconfig]. Used by the [fontconfig][fontconfig-rs] crate.
5 |
6 | [fontconfig]: https://www.freedesktop.org/wiki/Software/fontconfig/
7 | [fontconfig-rs]: https://crates.io/crates/fontconfig
8 |
--------------------------------------------------------------------------------
/fontconfig-sys/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | println!("cargo:rerun-if-env-changed=RUST_FONTCONFIG_DLOPEN");
3 | let dlopen = std::env::var_os("RUST_FONTCONFIG_DLOPEN").is_some();
4 | if dlopen {
5 | println!("cargo:rustc-cfg=feature=\"dlopen\"");
6 | }
7 | if !(dlopen || cfg!(feature = "dlopen")) {
8 | pkg_config::find_library("fontconfig").unwrap();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/fontconfig-sys/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Servo Project Developers. See the LICENSE
2 | // file at the top-level directory of this distribution.
3 | //
4 | // Licensed under the the MIT license. This file may not be
5 | // copied, modified, or distributed except according to those terms.
6 |
7 | #![allow(non_upper_case_globals)]
8 | #![allow(non_camel_case_types)]
9 | #![allow(non_snake_case)]
10 |
11 | use std::os::raw::{c_char, c_double, c_int, c_uchar, c_uint, c_ushort, c_void};
12 |
13 | pub use dlib::ffi_dispatch;
14 |
15 | #[cfg(feature = "dlopen")]
16 | pub mod statics {
17 | use super::Fc;
18 | use once_cell::sync::Lazy;
19 |
20 | static SONAME: &str = if cfg!(windows) {
21 | "libfontconfig.dll"
22 | } else if cfg!(target_vendor = "apple") {
23 | "libfontconfig.dylib.1"
24 | } else {
25 | "libfontconfig.so.1"
26 | };
27 |
28 | pub static LIB_RESULT: Lazy> =
29 | Lazy::new(|| unsafe { Fc::open(SONAME) });
30 |
31 | pub static LIB: Lazy<&'static Fc> = Lazy::new(|| LIB_RESULT.as_ref().unwrap());
32 | }
33 |
34 | pub type FcChar8 = c_uchar;
35 | pub type FcChar16 = c_ushort;
36 | pub type FcChar32 = c_uint;
37 | pub type FcBool = c_int;
38 |
39 | pub type enum__FcType = c_uint;
40 | pub const FcTypeVoid: u32 = 0_u32;
41 | pub const FcTypeInteger: u32 = 1_u32;
42 | pub const FcTypeDouble: u32 = 2_u32;
43 | pub const FcTypeString: u32 = 3_u32;
44 | pub const FcTypeBool: u32 = 4_u32;
45 | pub const FcTypeMatrix: u32 = 5_u32;
46 | pub const FcTypeCharSet: u32 = 6_u32;
47 | pub const FcTypeFTFace: u32 = 7_u32;
48 | pub const FcTypeLangSet: u32 = 8_u32;
49 |
50 | pub type FcType = enum__FcType;
51 |
52 | pub mod constants {
53 | use std::ffi::CStr;
54 |
55 | use super::c_int;
56 |
57 | pub const FC_WEIGHT_THIN: c_int = 0;
58 | pub const FC_WEIGHT_EXTRALIGHT: c_int = 40;
59 | pub const FC_WEIGHT_ULTRALIGHT: c_int = FC_WEIGHT_EXTRALIGHT;
60 | pub const FC_WEIGHT_LIGHT: c_int = 50;
61 | pub const FC_WEIGHT_BOOK: c_int = 75;
62 | pub const FC_WEIGHT_REGULAR: c_int = 80;
63 | pub const FC_WEIGHT_NORMAL: c_int = FC_WEIGHT_REGULAR;
64 | pub const FC_WEIGHT_MEDIUM: c_int = 100;
65 | pub const FC_WEIGHT_DEMIBOLD: c_int = 180;
66 | pub const FC_WEIGHT_SEMIBOLD: c_int = FC_WEIGHT_DEMIBOLD;
67 | pub const FC_WEIGHT_BOLD: c_int = 200;
68 | pub const FC_WEIGHT_EXTRABOLD: c_int = 205;
69 | pub const FC_WEIGHT_ULTRABOLD: c_int = FC_WEIGHT_EXTRABOLD;
70 | pub const FC_WEIGHT_BLACK: c_int = 210;
71 | pub const FC_WEIGHT_HEAVY: c_int = FC_WEIGHT_BLACK;
72 | pub const FC_WEIGHT_EXTRABLACK: c_int = 215;
73 | pub const FC_WEIGHT_ULTRABLACK: c_int = FC_WEIGHT_EXTRABLACK;
74 |
75 | pub const FC_SLANT_ROMAN: c_int = 0;
76 | pub const FC_SLANT_ITALIC: c_int = 100;
77 | pub const FC_SLANT_OBLIQUE: c_int = 110;
78 |
79 | pub const FC_WIDTH_ULTRACONDENSED: c_int = 50;
80 | pub const FC_WIDTH_EXTRACONDENSED: c_int = 63;
81 | pub const FC_WIDTH_CONDENSED: c_int = 75;
82 | pub const FC_WIDTH_SEMICONDENSED: c_int = 87;
83 | pub const FC_WIDTH_NORMAL: c_int = 100;
84 | pub const FC_WIDTH_SEMIEXPANDED: c_int = 113;
85 | pub const FC_WIDTH_EXPANDED: c_int = 125;
86 | pub const FC_WIDTH_EXTRAEXPANDED: c_int = 150;
87 | pub const FC_WIDTH_ULTRAEXPANDED: c_int = 200;
88 |
89 | pub const FC_PROPORTIONAL: c_int = 0;
90 | pub const FC_DUAL: c_int = 90;
91 | pub const FC_MONO: c_int = 100;
92 | pub const FC_CHARCELL: c_int = 110;
93 |
94 | pub const FC_RGBA_UNKNOWN: c_int = 0;
95 | pub const FC_RGBA_RGB: c_int = 1;
96 | pub const FC_RGBA_BGR: c_int = 2;
97 | pub const FC_RGBA_VRGB: c_int = 3;
98 | pub const FC_RGBA_VBGR: c_int = 4;
99 | pub const FC_RGBA_NONE: c_int = 5;
100 |
101 | pub const FC_HINT_NONE: c_int = 0;
102 | pub const FC_HINT_SLIGHT: c_int = 1;
103 | pub const FC_HINT_MEDIUM: c_int = 2;
104 | pub const FC_HINT_FULL: c_int = 3;
105 |
106 | pub const FC_LCD_NONE: c_int = 0;
107 | pub const FC_LCD_DEFAULT: c_int = 1;
108 | pub const FC_LCD_LIGHT: c_int = 2;
109 | pub const FC_LCD_LEGACY: c_int = 3;
110 |
111 | pub const FC_CHARSET_MAP_SIZE: c_int = 8;
112 | pub const FC_CHARSET_DONE: u32 = u32::MAX;
113 | pub const FC_UTF8_MAX_LEN: c_int = 6;
114 |
115 | pub const FC_FAMILY: &CStr = c"family";
116 | pub const FC_STYLE: &CStr = c"style";
117 | pub const FC_SLANT: &CStr = c"slant";
118 | pub const FC_WEIGHT: &CStr = c"weight";
119 | pub const FC_SIZE: &CStr = c"size";
120 | pub const FC_ASPECT: &CStr = c"aspect";
121 | pub const FC_PIXEL_SIZE: &CStr = c"pixelsize";
122 | pub const FC_SPACING: &CStr = c"spacing";
123 | pub const FC_FOUNDRY: &CStr = c"foundry";
124 | pub const FC_ANTIALIAS: &CStr = c"antialias";
125 | pub const FC_HINTING: &CStr = c"hinting";
126 | pub const FC_HINT_STYLE: &CStr = c"hintstyle";
127 | pub const FC_VERTICAL_LAYOUT: &CStr = c"verticallayout";
128 | pub const FC_AUTOHINT: &CStr = c"autohint";
129 | pub const FC_GLOBAL_ADVANCE: &CStr = c"globaladvance";
130 | pub const FC_WIDTH: &CStr = c"width";
131 | pub const FC_FILE: &CStr = c"file";
132 | pub const FC_INDEX: &CStr = c"index";
133 | pub const FC_FT_FACE: &CStr = c"ftface";
134 | pub const FC_RASTERIZER: &CStr = c"rasterizer";
135 | pub const FC_OUTLINE: &CStr = c"outline";
136 | pub const FC_SCALABLE: &CStr = c"scalable";
137 | pub const FC_COLOR: &CStr = c"color";
138 | pub const FC_VARIABLE: &CStr = c"variable";
139 | pub const FC_SCALE: &CStr = c"scale";
140 | pub const FC_SYMBOL: &CStr = c"symbol";
141 | pub const FC_DPI: &CStr = c"dpi";
142 | pub const FC_RGBA: &CStr = c"rgba";
143 | pub const FC_MINSPACE: &CStr = c"minspace";
144 | pub const FC_SOURCE: &CStr = c"source";
145 | pub const FC_CHARSET: &CStr = c"charset";
146 | pub const FC_LANG: &CStr = c"lang";
147 | pub const FC_FONTVERSION: &CStr = c"fontversion";
148 | pub const FC_FULLNAME: &CStr = c"fullname";
149 | pub const FC_FAMILYLANG: &CStr = c"familylang";
150 | pub const FC_STYLELANG: &CStr = c"stylelang";
151 | pub const FC_FULLNAMELANG: &CStr = c"fullnamelang";
152 | pub const FC_CAPABILITY: &CStr = c"capability";
153 | pub const FC_FONTFORMAT: &CStr = c"fontformat";
154 | pub const FC_EMBOLDEN: &CStr = c"embolden";
155 | pub const FC_EMBEDDED_BITMAP: &CStr = c"embeddedbitmap";
156 | pub const FC_DECORATIVE: &CStr = c"decorative";
157 | pub const FC_LCD_FILTER: &CStr = c"lcdfilter";
158 | pub const FC_FONT_FEATURES: &CStr = c"fontfeatures";
159 | pub const FC_FONT_VARIATIONS: &CStr = c"fontvariations";
160 | pub const FC_NAMELANG: &CStr = c"namelang";
161 | pub const FC_PRGNAME: &CStr = c"prgname";
162 | pub const FC_HASH: &CStr = c"hash";
163 | pub const FC_POSTSCRIPT_NAME: &CStr = c"postscriptname";
164 | pub const FC_FONT_HAS_HINT: &CStr = c"fonthashint";
165 | pub const FC_CACHE_SUFFIX: &CStr = c".cache-";
166 | pub const FC_DIR_CACHE_FILE: &CStr = c"fonts.cache-";
167 | pub const FC_USER_CACHE_FILE: &CStr = c".fonts.cache-";
168 | pub const FC_CHARWIDTH: &CStr = c"charwidth";
169 | pub const FC_CHAR_WIDTH: &CStr = c"charwidth";
170 | pub const FC_CHAR_HEIGHT: &CStr = c"charheight";
171 | pub const FC_MATRIX: &CStr = c"matrix";
172 | pub const FC_ORDER: &CStr = c"order";
173 | }
174 |
175 | #[repr(C)]
176 | #[derive(Copy, Clone)]
177 | pub struct struct__FcMatrix {
178 | pub xx: c_double,
179 | pub xy: c_double,
180 | pub yx: c_double,
181 | pub yy: c_double,
182 | }
183 |
184 | pub type FcMatrix = struct__FcMatrix;
185 |
186 | pub type struct__FcCharSet = c_void;
187 |
188 | pub type FcCharSet = struct__FcCharSet;
189 |
190 | #[repr(C)]
191 | #[allow(missing_copy_implementations)]
192 | pub struct struct__FcObjectType {
193 | pub object: *mut c_char,
194 | pub _type: FcType,
195 | }
196 |
197 | pub type FcObjectType = struct__FcObjectType;
198 |
199 | #[repr(C)]
200 | #[allow(missing_copy_implementations)]
201 | pub struct struct__FcConstant {
202 | pub name: *mut FcChar8,
203 | pub object: *mut c_char,
204 | pub value: c_int,
205 | }
206 |
207 | pub type FcConstant = struct__FcConstant;
208 |
209 | pub type enum__FcResult = c_uint;
210 | pub const FcResultMatch: u32 = 0_u32;
211 | pub const FcResultNoMatch: u32 = 1_u32;
212 | pub const FcResultTypeMismatch: u32 = 2_u32;
213 | pub const FcResultNoId: u32 = 3_u32;
214 | pub const FcResultOutOfMemory: u32 = 4_u32;
215 |
216 | pub type FcResult = enum__FcResult;
217 |
218 | pub type struct__FcPattern = c_void;
219 |
220 | pub type FcPattern = struct__FcPattern;
221 |
222 | pub type struct__FcLangSet = c_void;
223 |
224 | pub type FcLangSet = struct__FcLangSet;
225 |
226 | #[repr(C)]
227 | #[allow(missing_copy_implementations)]
228 | pub struct struct__FcValue {
229 | pub _type: FcType,
230 | pub u: union_unnamed1,
231 | }
232 |
233 | pub type FcValue = struct__FcValue;
234 |
235 | #[repr(C)]
236 | #[allow(missing_copy_implementations)]
237 | pub struct struct__FcFontSet {
238 | pub nfont: c_int,
239 | pub sfont: c_int,
240 | pub fonts: *mut *mut FcPattern,
241 | }
242 |
243 | pub type FcFontSet = struct__FcFontSet;
244 |
245 | #[repr(C)]
246 | #[allow(missing_copy_implementations)]
247 | pub struct struct__FcObjectSet {
248 | pub nobject: c_int,
249 | pub sobject: c_int,
250 | pub objects: *mut *mut c_char,
251 | }
252 |
253 | pub type FcObjectSet = struct__FcObjectSet;
254 |
255 | pub type enum__FcMatchKind = c_uint;
256 | pub const FcMatchPattern: u32 = 0_u32;
257 | pub const FcMatchFont: u32 = 1_u32;
258 | pub const FcMatchScan: u32 = 2_u32;
259 |
260 | pub type FcMatchKind = enum__FcMatchKind;
261 |
262 | pub type enum__FcLangResult = c_uint;
263 | pub const FcLangEqual: u32 = 0_u32;
264 | pub const FcLangDifferentCountry: u32 = 1_u32;
265 | pub const FcLangDifferentTerritory: u32 = 1_u32;
266 | pub const FcLangDifferentLang: u32 = 2_u32;
267 |
268 | pub type FcLangResult = enum__FcLangResult;
269 |
270 | pub type enum__FcSetName = c_uint;
271 | pub const FcSetSystem: u32 = 0_u32;
272 | pub const FcSetApplication: u32 = 1_u32;
273 |
274 | pub type FcSetName = enum__FcSetName;
275 |
276 | pub type struct__FcAtomic = c_void;
277 |
278 | pub type FcAtomic = struct__FcAtomic;
279 |
280 | pub type FcEndian = c_uint;
281 | pub const FcEndianBig: u32 = 0_u32;
282 | pub const FcEndianLittle: u32 = 1_u32;
283 |
284 | pub type struct__FcConfig = c_void;
285 |
286 | pub type FcConfig = struct__FcConfig;
287 |
288 | pub type struct__FcGlobalCache = c_void;
289 |
290 | pub type FcFileCache = struct__FcGlobalCache;
291 |
292 | pub type struct__FcBlanks = c_void;
293 |
294 | pub type FcBlanks = struct__FcBlanks;
295 |
296 | pub type struct__FcStrList = c_void;
297 |
298 | pub type FcStrList = struct__FcStrList;
299 |
300 | pub type struct__FcStrSet = c_void;
301 |
302 | pub type FcStrSet = struct__FcStrSet;
303 |
304 | pub type struct__FcCache = c_void;
305 |
306 | pub type FcCache = struct__FcCache;
307 |
308 | pub type union_unnamed1 = c_void;
309 |
310 | dlib::external_library!(Fc, "fontconfig",
311 | functions:
312 | fn FcBlanksCreate() -> *mut FcBlanks,
313 |
314 | fn FcBlanksDestroy(*mut FcBlanks) -> (),
315 |
316 | fn FcBlanksAdd(*mut FcBlanks, FcChar32) -> FcBool,
317 |
318 | fn FcBlanksIsMember(*mut FcBlanks, FcChar32) -> FcBool,
319 |
320 | fn FcCacheDir(*mut FcCache) -> *const FcChar8,
321 |
322 | fn FcCacheCopySet(*const FcCache) -> *mut FcFontSet,
323 |
324 | fn FcCacheSubdir(*const FcCache, c_int) -> *const FcChar8,
325 |
326 | fn FcCacheNumSubdir(*const FcCache) -> c_int,
327 |
328 | fn FcCacheNumFont(*const FcCache) -> c_int,
329 |
330 | fn FcDirCacheUnlink(*const FcChar8, *mut FcConfig) -> FcBool,
331 |
332 | fn FcDirCacheValid(*const FcChar8) -> FcBool,
333 |
334 | fn FcConfigHome() -> *mut FcChar8,
335 |
336 | fn FcConfigEnableHome(FcBool) -> FcBool,
337 |
338 | fn FcConfigFilename(*const FcChar8) -> *mut FcChar8,
339 |
340 | fn FcConfigCreate() -> *mut FcConfig,
341 |
342 | fn FcConfigReference(*mut FcConfig) -> *mut FcConfig,
343 |
344 | fn FcConfigDestroy(*mut FcConfig) -> (),
345 |
346 | fn FcConfigSetCurrent(*mut FcConfig) -> FcBool,
347 |
348 | fn FcConfigGetCurrent() -> *mut FcConfig,
349 |
350 | fn FcConfigUptoDate(*mut FcConfig) -> FcBool,
351 |
352 | fn FcConfigBuildFonts(*mut FcConfig) -> FcBool,
353 |
354 | fn FcConfigGetFontDirs(*mut FcConfig) -> *mut FcStrList,
355 |
356 | fn FcConfigGetConfigDirs(*mut FcConfig) -> *mut FcStrList,
357 |
358 | fn FcConfigGetConfigFiles(*mut FcConfig) -> *mut FcStrList,
359 |
360 | fn FcConfigGetCache(*mut FcConfig) -> *mut FcChar8,
361 |
362 | fn FcConfigGetBlanks(*mut FcConfig) -> *mut FcBlanks,
363 |
364 | fn FcConfigGetCacheDirs(*const FcConfig) -> *mut FcStrList,
365 |
366 | fn FcConfigGetRescanInterval(*mut FcConfig) -> c_int,
367 |
368 | fn FcConfigSetRescanInterval(*mut FcConfig, c_int) -> FcBool,
369 |
370 | fn FcConfigGetFonts(*mut FcConfig, FcSetName) -> *mut FcFontSet,
371 |
372 | fn FcConfigAppFontAddFile(*mut FcConfig, *const FcChar8) -> FcBool,
373 |
374 | fn FcConfigAppFontAddDir(*mut FcConfig, *const FcChar8) -> FcBool,
375 |
376 | fn FcConfigAppFontClear(*mut FcConfig) -> (),
377 |
378 | fn FcConfigSubstituteWithPat(
379 | *mut FcConfig,
380 | *mut FcPattern,
381 | *mut FcPattern,
382 | FcMatchKind
383 | ) -> FcBool,
384 |
385 | fn FcConfigSubstitute(
386 | *mut FcConfig,
387 | *mut FcPattern,
388 | FcMatchKind
389 | ) -> FcBool,
390 |
391 | fn FcCharSetCreate() -> *mut FcCharSet,
392 |
393 | fn FcCharSetNew() -> *mut FcCharSet,
394 |
395 | fn FcCharSetDestroy(*mut FcCharSet) -> (),
396 |
397 | fn FcCharSetAddChar(*mut FcCharSet, FcChar32) -> FcBool,
398 |
399 | fn FcCharSetDelChar(*mut FcCharSet, FcChar32) -> FcBool,
400 |
401 | fn FcCharSetCopy(*mut FcCharSet) -> *mut FcCharSet,
402 |
403 | fn FcCharSetEqual(*const FcCharSet, *const FcCharSet) -> FcBool,
404 |
405 | fn FcCharSetIntersect(*const FcCharSet, *const FcCharSet) -> *mut FcCharSet,
406 |
407 | fn FcCharSetUnion(*const FcCharSet, *const FcCharSet) -> *mut FcCharSet,
408 |
409 | fn FcCharSetSubtract(*const FcCharSet, *const FcCharSet) -> *mut FcCharSet,
410 |
411 | fn FcCharSetMerge(*mut FcCharSet, *const FcCharSet, *mut FcBool) -> FcBool,
412 |
413 | fn FcCharSetHasChar(*const FcCharSet, FcChar32) -> FcBool,
414 |
415 | fn FcCharSetCount(*const FcCharSet) -> FcChar32,
416 |
417 | fn FcCharSetIntersectCount(*const FcCharSet, *const FcCharSet) -> FcChar32,
418 |
419 | fn FcCharSetSubtractCount(*const FcCharSet, *const FcCharSet) -> FcChar32,
420 |
421 | fn FcCharSetIsSubset(*const FcCharSet, *const FcCharSet) -> FcBool,
422 |
423 | fn FcCharSetFirstPage(
424 | *const FcCharSet,
425 | *mut FcChar32,
426 | *mut FcChar32
427 | ) -> FcChar32,
428 |
429 | fn FcCharSetNextPage(
430 | *const FcCharSet,
431 | *mut FcChar32,
432 | *mut FcChar32
433 | ) -> FcChar32,
434 |
435 | fn FcCharSetCoverage(
436 | *const FcCharSet,
437 | FcChar32,
438 | *mut FcChar32
439 | ) -> FcChar32,
440 |
441 | fn FcValuePrint(FcValue) -> (),
442 |
443 | fn FcPatternPrint(*const FcPattern) -> (),
444 |
445 | fn FcFontSetPrint(*mut FcFontSet) -> (),
446 |
447 | fn FcDefaultSubstitute(*mut FcPattern) -> (),
448 |
449 | fn FcFileIsDir(*const FcChar8) -> FcBool,
450 |
451 | fn FcFileScan(
452 | *mut FcFontSet,
453 | *mut FcStrSet,
454 | *mut FcFileCache,
455 | *mut FcBlanks,
456 | *const FcChar8,
457 | FcBool
458 | ) -> FcBool,
459 |
460 | fn FcDirScan(
461 | *mut FcFontSet,
462 | *mut FcStrSet,
463 | *mut FcFileCache,
464 | *mut FcBlanks,
465 | *const FcChar8,
466 | FcBool
467 | ) -> FcBool,
468 |
469 | fn FcDirSave(*mut FcFontSet, *const FcStrSet, *mut FcChar8) -> FcBool,
470 |
471 | fn FcDirCacheLoad(
472 | *const FcChar8,
473 | *mut FcConfig,
474 | *mut *mut FcChar8
475 | ) -> *mut FcCache,
476 |
477 | fn FcDirCacheRead(
478 | *const FcChar8,
479 | FcBool,
480 | *mut FcConfig
481 | ) -> *mut FcCache,
482 |
483 | // fn FcDirCacheLoadFile(*mut FcChar8, *mut struct_stat) -> *mut FcCache,
484 |
485 | fn FcDirCacheUnload(*mut FcCache) -> (),
486 |
487 | fn FcFreeTypeQuery(
488 | *const FcChar8,
489 | c_int,
490 | *mut FcBlanks,
491 | *mut c_int
492 | ) -> *mut FcPattern,
493 |
494 | fn FcFontSetCreate() -> *mut FcFontSet,
495 |
496 | fn FcFontSetDestroy(*mut FcFontSet) -> (),
497 |
498 | fn FcFontSetAdd(*mut FcFontSet, *mut FcPattern) -> FcBool,
499 |
500 | fn FcInitLoadConfig() -> *mut FcConfig,
501 |
502 | fn FcInitLoadConfigAndFonts() -> *mut FcConfig,
503 |
504 | fn FcInit() -> FcBool,
505 |
506 | fn FcFini() -> (),
507 |
508 | fn FcGetVersion() -> c_int,
509 |
510 | fn FcInitReinitialize() -> FcBool,
511 |
512 | fn FcInitBringUptoDate() -> FcBool,
513 |
514 | fn FcGetLangs() -> *mut FcStrSet,
515 |
516 | fn FcLangGetCharSet(*const FcChar8) -> *mut FcCharSet,
517 |
518 | fn FcLangSetCreate() -> *mut FcLangSet,
519 |
520 | fn FcLangSetDestroy(*mut FcLangSet) -> (),
521 |
522 | fn FcLangSetCopy(*const FcLangSet) -> *mut FcLangSet,
523 |
524 | fn FcLangSetAdd(*mut FcLangSet, *const FcChar8) -> FcBool,
525 |
526 | fn FcLangSetHasLang(*const FcLangSet, *const FcChar8) -> FcLangResult,
527 |
528 | fn FcLangSetCompare(*const FcLangSet, *const FcLangSet) -> FcLangResult,
529 |
530 | fn FcLangSetContains(*const FcLangSet, *const FcLangSet) -> FcBool,
531 |
532 | fn FcLangSetEqual(*const FcLangSet, *const FcLangSet) -> FcBool,
533 |
534 | fn FcLangSetHash(*const FcLangSet) -> FcChar32,
535 |
536 | fn FcLangSetGetLangs(*const FcLangSet) -> *mut FcStrSet,
537 |
538 | fn FcObjectSetCreate() -> *mut FcObjectSet,
539 |
540 | fn FcObjectSetAdd(*mut FcObjectSet, *const c_char) -> FcBool,
541 |
542 | fn FcObjectSetDestroy(*mut FcObjectSet) -> (),
543 |
544 | // fn FcObjectSetVaBuild(*mut c_char, *mut __va_list_tag) -> *mut FcObjectSet,
545 |
546 | fn FcFontSetList(
547 | *mut FcConfig,
548 | *mut *mut FcFontSet,
549 | c_int,
550 | *mut FcPattern,
551 | *mut FcObjectSet
552 | ) -> *mut FcFontSet,
553 |
554 | fn FcFontList(
555 | *mut FcConfig,
556 | *mut FcPattern,
557 | *mut FcObjectSet
558 | ) -> *mut FcFontSet,
559 |
560 | fn FcAtomicCreate(*const FcChar8) -> *mut FcAtomic,
561 |
562 | fn FcAtomicLock(*mut FcAtomic) -> FcBool,
563 |
564 | fn FcAtomicNewFile(*mut FcAtomic) -> *mut FcChar8,
565 |
566 | fn FcAtomicOrigFile(*mut FcAtomic) -> *mut FcChar8,
567 |
568 | fn FcAtomicReplaceOrig(*mut FcAtomic) -> FcBool,
569 |
570 | fn FcAtomicDeleteNew(*mut FcAtomic) -> (),
571 |
572 | fn FcAtomicUnlock(*mut FcAtomic) -> (),
573 |
574 | fn FcAtomicDestroy(*mut FcAtomic) -> (),
575 |
576 | fn FcFontSetMatch(
577 | *mut FcConfig,
578 | *mut *mut FcFontSet,
579 | c_int,
580 | *mut FcPattern,
581 | *mut FcResult
582 | ) -> *mut FcPattern,
583 |
584 | fn FcFontMatch(
585 | *mut FcConfig,
586 | *mut FcPattern,
587 | *mut FcResult
588 | ) -> *mut FcPattern,
589 |
590 | fn FcFontRenderPrepare(
591 | *mut FcConfig,
592 | *mut FcPattern,
593 | *mut FcPattern
594 | ) -> *mut FcPattern,
595 |
596 | fn FcFontSetSort(
597 | *mut FcConfig,
598 | *mut *mut FcFontSet,
599 | c_int,
600 | *mut FcPattern,
601 | FcBool,
602 | *mut *mut FcCharSet,
603 | *mut FcResult
604 | ) -> *mut FcFontSet,
605 |
606 | fn FcFontSort(
607 | *mut FcConfig,
608 | *mut FcPattern,
609 | FcBool,
610 | *mut *mut FcCharSet,
611 | *mut FcResult
612 | ) -> *mut FcFontSet,
613 |
614 | fn FcFontSetSortDestroy(*mut FcFontSet) -> (),
615 |
616 | fn FcMatrixCopy(*const FcMatrix) -> *mut FcMatrix,
617 |
618 | fn FcMatrixEqual(*const FcMatrix, *const FcMatrix) -> FcBool,
619 |
620 | fn FcMatrixMultiply(*mut FcMatrix, *const FcMatrix, *const FcMatrix) -> (),
621 |
622 | fn FcMatrixRotate(*mut FcMatrix, c_double, c_double) -> (),
623 |
624 | fn FcMatrixScale(*mut FcMatrix, c_double, c_double) -> (),
625 |
626 | fn FcMatrixShear(*mut FcMatrix, c_double, c_double) -> (),
627 |
628 | fn FcNameRegisterObjectTypes(*const FcObjectType, c_int) -> FcBool,
629 |
630 | fn FcNameUnregisterObjectTypes(*const FcObjectType, c_int) -> FcBool,
631 |
632 | fn FcNameGetObjectType(*const c_char) -> *const FcObjectType,
633 |
634 | fn FcNameRegisterConstants(*const FcConstant, c_int) -> FcBool,
635 |
636 | fn FcNameUnregisterConstants(*const FcConstant, c_int) -> FcBool,
637 |
638 | fn FcNameGetConstant(*mut FcChar8) -> *const FcConstant,
639 |
640 | fn FcNameConstant(*mut FcChar8, *mut c_int) -> FcBool,
641 |
642 | fn FcNameParse(*const FcChar8) -> *mut FcPattern,
643 |
644 | fn FcNameUnparse(*mut FcPattern) -> *mut FcChar8,
645 |
646 | fn FcPatternCreate() -> *mut FcPattern,
647 |
648 | fn FcPatternDuplicate(*const FcPattern) -> *mut FcPattern,
649 |
650 | fn FcPatternReference(*mut FcPattern) -> (),
651 |
652 | fn FcPatternFilter(*mut FcPattern, *const FcObjectSet) -> *mut FcPattern,
653 |
654 | fn FcValueDestroy(FcValue) -> (),
655 |
656 | fn FcValueEqual(FcValue, FcValue) -> FcBool,
657 |
658 | fn FcValueSave(FcValue) -> FcValue,
659 |
660 | fn FcPatternDestroy(*mut FcPattern) -> (),
661 |
662 | fn FcPatternEqual(*const FcPattern, *const FcPattern) -> FcBool,
663 |
664 | fn FcPatternEqualSubset(
665 | *const FcPattern,
666 | *const FcPattern,
667 | *const FcObjectSet
668 | ) -> FcBool,
669 |
670 | fn FcPatternHash(*const FcPattern) -> FcChar32,
671 |
672 | fn FcPatternAdd(
673 | *mut FcPattern,
674 | *const c_char,
675 | FcValue,
676 | FcBool
677 | ) -> FcBool,
678 |
679 | fn FcPatternAddWeak(
680 | *mut FcPattern,
681 | *const c_char,
682 | FcValue,
683 | FcBool
684 | ) -> FcBool,
685 |
686 | fn FcPatternGet(
687 | *mut FcPattern,
688 | *const c_char,
689 | c_int,
690 | *mut FcValue
691 | ) -> FcResult,
692 |
693 | fn FcPatternDel(*mut FcPattern, *const c_char) -> FcBool,
694 |
695 | fn FcPatternRemove(*mut FcPattern, *const c_char, c_int) -> FcBool,
696 |
697 | fn FcPatternAddInteger(*mut FcPattern, *const c_char, c_int) -> FcBool,
698 |
699 | fn FcPatternAddDouble(*mut FcPattern, *const c_char, c_double) -> FcBool,
700 |
701 | fn FcPatternAddString(
702 | *mut FcPattern,
703 | *const c_char,
704 | *const FcChar8
705 | ) -> FcBool,
706 |
707 | fn FcPatternAddMatrix(
708 | *mut FcPattern,
709 | *const c_char,
710 | *const FcMatrix
711 | ) -> FcBool,
712 |
713 | fn FcPatternAddCharSet(
714 | *mut FcPattern,
715 | *const c_char,
716 | *const FcCharSet
717 | ) -> FcBool,
718 |
719 | fn FcPatternAddBool(*mut FcPattern, *const c_char, FcBool) -> FcBool,
720 |
721 | fn FcPatternAddLangSet(
722 | *mut FcPattern,
723 | *const c_char,
724 | *const FcLangSet
725 | ) -> FcBool,
726 |
727 | fn FcPatternGetInteger(
728 | *mut FcPattern,
729 | *const c_char,
730 | c_int,
731 | *mut c_int
732 | ) -> FcResult,
733 |
734 | fn FcPatternGetDouble(
735 | *mut FcPattern,
736 | *const c_char,
737 | c_int,
738 | *mut c_double
739 | ) -> FcResult,
740 |
741 | fn FcPatternGetString(
742 | *mut FcPattern,
743 | *const c_char,
744 | c_int,
745 | *mut *mut FcChar8
746 | ) -> FcResult,
747 |
748 | fn FcPatternGetMatrix(
749 | *mut FcPattern,
750 | *const c_char,
751 | c_int,
752 | *mut *mut FcMatrix
753 | ) -> FcResult,
754 |
755 | fn FcPatternGetCharSet(
756 | *mut FcPattern,
757 | *const c_char,
758 | c_int,
759 | *mut *mut FcCharSet
760 | ) -> FcResult,
761 |
762 | fn FcPatternGetBool(
763 | *mut FcPattern,
764 | *const c_char,
765 | c_int,
766 | *mut FcBool
767 | ) -> FcResult,
768 |
769 | fn FcPatternGetLangSet(
770 | *mut FcPattern,
771 | *const c_char,
772 | c_int,
773 | *mut *mut FcLangSet
774 | ) -> FcResult,
775 |
776 | // The last argument is a pointer to a FreeType Face object (`FT_Face *`)
777 | //
778 | //
779 | fn FcPatternGetFTFace(*mut FcPattern, *const c_char, c_int, *mut *mut c_void) -> FcResult,
780 |
781 | // fn FcPatternVaBuild(*mut FcPattern, *mut __va_list_tag) -> *mut FcPattern,
782 |
783 | fn FcPatternFormat(*mut FcPattern, *const FcChar8) -> *mut FcChar8,
784 |
785 | fn FcStrCopy(*const FcChar8) -> *mut FcChar8,
786 |
787 | fn FcStrCopyFilename(*const FcChar8) -> *mut FcChar8,
788 |
789 | fn FcStrPlus(*const FcChar8, *const FcChar8) -> *mut FcChar8,
790 |
791 | fn FcStrFree(*mut FcChar8) -> (),
792 |
793 | fn FcStrDowncase(*const FcChar8) -> *mut FcChar8,
794 |
795 | fn FcStrCmpIgnoreCase(*const FcChar8, *const FcChar8) -> c_int,
796 |
797 | fn FcStrCmp(*const FcChar8, *const FcChar8) -> c_int,
798 |
799 | fn FcStrStrIgnoreCase(*const FcChar8, *const FcChar8) -> *mut FcChar8,
800 |
801 | fn FcStrStr(*const FcChar8, *const FcChar8) -> *mut FcChar8,
802 |
803 | fn FcUtf8ToUcs4(*mut FcChar8, *mut FcChar32, c_int) -> c_int,
804 |
805 | fn FcUtf8Len(
806 | *mut FcChar8,
807 | c_int,
808 | *mut c_int,
809 | *mut c_int
810 | ) -> FcBool,
811 |
812 | fn FcUcs4ToUtf8(FcChar32, *mut FcChar8) -> c_int,
813 |
814 | fn FcUtf16ToUcs4(
815 | *mut FcChar8,
816 | FcEndian,
817 | *mut FcChar32,
818 | c_int
819 | ) -> c_int,
820 |
821 | fn FcUtf16Len(
822 | *mut FcChar8,
823 | FcEndian,
824 | c_int,
825 | *mut c_int,
826 | *mut c_int
827 | ) -> FcBool,
828 |
829 | fn FcStrDirname(*const FcChar8) -> *mut FcChar8,
830 |
831 | fn FcStrBasename(*const FcChar8) -> *mut FcChar8,
832 |
833 | fn FcStrSetCreate() -> *mut FcStrSet,
834 |
835 | fn FcStrSetMember(*mut FcStrSet, *const FcChar8) -> FcBool,
836 |
837 | fn FcStrSetEqual(*mut FcStrSet, *mut FcStrSet) -> FcBool,
838 |
839 | fn FcStrSetAdd(*mut FcStrSet, *const FcChar8) -> FcBool,
840 |
841 | fn FcStrSetAddFilename(*mut FcStrSet, *const FcChar8) -> FcBool,
842 |
843 | fn FcStrSetDel(*mut FcStrSet, *const FcChar8) -> FcBool,
844 |
845 | fn FcStrSetDestroy(*mut FcStrSet) -> (),
846 |
847 | fn FcStrListCreate(*mut FcStrSet) -> *mut FcStrList,
848 |
849 | fn FcStrListNext(*mut FcStrList) -> *mut FcChar8,
850 |
851 | fn FcStrListDone(*mut FcStrList) -> (),
852 |
853 | fn FcConfigParseAndLoad(
854 | *mut FcConfig,
855 | *const FcChar8,
856 | FcBool
857 | ) -> FcBool,
858 |
859 | varargs:
860 | fn FcPatternBuild(*mut FcPattern) -> *mut FcPattern,
861 | fn FcObjectSetBuild(*mut c_char) -> *mut FcObjectSet,
862 | );
863 |
--------------------------------------------------------------------------------
/fontconfig/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "fontconfig"
3 | version = "0.10.0"
4 | edition = "2021"
5 | rust-version = "1.77"
6 | authors = [
7 | "Austin Bonander ",
8 | "Manuel Reinhardt ",
9 | "YesLogic Pty. Ltd. "
10 | ]
11 | license = "MIT"
12 |
13 | description = "Safe, higher-level wrapper around the Fontconfig library"
14 | keywords = ["font", "search", "wrapper", "fontconfig"]
15 | categories = ["text-processing"]
16 |
17 | homepage = "https://github.com/yeslogic/fontconfig-rs"
18 | documentation = "https://docs.rs/crate/fontconfig"
19 | repository = "https://github.com/yeslogic/fontconfig-rs"
20 |
21 | [dependencies.yeslogic-fontconfig-sys]
22 | version = "6.0.0"
23 | path = "../fontconfig-sys"
24 |
25 | [features]
26 | dlopen = [ "yeslogic-fontconfig-sys/dlopen" ]
27 |
--------------------------------------------------------------------------------
/fontconfig/LICENSE:
--------------------------------------------------------------------------------
1 | ../LICENSE
--------------------------------------------------------------------------------
/fontconfig/README.md:
--------------------------------------------------------------------------------
1 | ../README.md
--------------------------------------------------------------------------------
/fontconfig/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | println!("cargo:rerun-if-env-changed=RUST_FONTCONFIG_DLOPEN");
3 | let dlopen = std::env::var_os("RUST_FONTCONFIG_DLOPEN").is_some();
4 | if dlopen {
5 | println!("cargo:rustc-cfg=feature=\"dlopen\"");
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/fontconfig/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![deny(missing_docs)]
2 |
3 | //! A wrapper around [freedesktop.org's Fontconfig library][homepage], for locating fonts on a UNIX
4 | //! like systems such as Linux and FreeBSD. Requires Fontconfig to be installed. Alternatively,
5 | //! set the environment variable `RUST_FONTCONFIG_DLOPEN=on` or enable the `dlopen` Cargo feature
6 | //! to load the library at runtime rather than link at build time (useful for cross compiling).
7 | //!
8 | //! See the [Fontconfig developer reference][1] for more information.
9 | //!
10 | //! [1]: http://www.freedesktop.org/software/fontconfig/fontconfig-devel/t1.html
11 | //! [homepage]: https://www.freedesktop.org/wiki/Software/fontconfig/
12 | //!
13 | //! Dependencies
14 | //! ============
15 | //!
16 | //! * Arch Linux: `fontconfig`
17 | //! * Debian-based systems: `libfontconfig1-dev`
18 | //! * FreeBSD: `fontconfig`
19 | //! * Void Linux: `fontconfig-devel`
20 | //!
21 | //! Usage
22 | //! -----
23 | //!
24 | //! ```
25 | //! use fontconfig::Fontconfig;
26 | //!
27 | //! fn main() {
28 | //! let fc = Fontconfig::new().unwrap();
29 | //! // `Fontconfig::find()` returns `Option` (will rarely be `None` but still could be)
30 | //! let font = fc.find("freeserif", None).unwrap();
31 | //! // `name` is a `String`, `path` is a `Path`
32 | //! println!("Name: {}\nPath: {}", font.name, font.path.display());
33 | //! }
34 | //! ```
35 | //!
36 | //! ### Cargo Features
37 | //!
38 | //! | Feature | Description | Default Enabled | Extra Dependencies |
39 | //! |---------------|-----------------------------------|:---------------:|-----------------------|
40 | //! | `dlopen` | [dlopen] libfontconfig at runtime | ❌ | |
41 | //!
42 | //! The `dlopen` feature enables building this crate without dynamically linking to the Fontconfig C
43 | //! library at link time. Instead, Fontconfig will be dynamically loaded at runtime with the
44 | //! [dlopen] function. This can be useful in cross-compiling situations as you don't need to have a
45 | //! version of Fontcofig available for the target platform available at compile time.
46 | //!
47 | //! [dlopen]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html
48 |
49 | use fontconfig_sys as sys;
50 | use fontconfig_sys::ffi_dispatch;
51 |
52 | #[cfg(feature = "dlopen")]
53 | use sys::statics::{LIB, LIB_RESULT};
54 | #[cfg(not(feature = "dlopen"))]
55 | use sys::*;
56 |
57 | use std::ffi::{c_int, CStr, CString};
58 | use std::marker::PhantomData;
59 | use std::mem;
60 | use std::os::raw::c_char;
61 | use std::path::PathBuf;
62 | use std::ptr;
63 | use std::str::FromStr;
64 |
65 | pub use sys::constants::*;
66 | use sys::{FcBool, FcPattern};
67 |
68 | #[allow(non_upper_case_globals)]
69 | const FcTrue: FcBool = 1;
70 | #[allow(non_upper_case_globals, dead_code)]
71 | const FcFalse: FcBool = 0;
72 |
73 | /// Handle obtained after Fontconfig has been initialised.
74 | pub struct Fontconfig {
75 | _initialised: (),
76 | }
77 |
78 | /// Error type returned from Pattern::format.
79 | ///
80 | /// The error holds the name of the unknown format.
81 | #[derive(Debug)]
82 | pub struct UnknownFontFormat(pub String);
83 |
84 | /// The format of a font matched by Fontconfig.
85 | #[derive(Eq, PartialEq)]
86 | #[allow(missing_docs)]
87 | pub enum FontFormat {
88 | TrueType,
89 | Type1,
90 | BDF,
91 | PCF,
92 | Type42,
93 | CIDType1,
94 | CFF,
95 | PFR,
96 | WindowsFNT,
97 | }
98 |
99 | impl Fontconfig {
100 | /// Initialise Fontconfig and return a handle allowing further interaction with the API.
101 | ///
102 | /// If Fontconfig fails to initialise, returns `None`.
103 | pub fn new() -> Option {
104 | #[cfg(feature = "dlopen")]
105 | if LIB_RESULT.is_err() {
106 | return None;
107 | }
108 | if unsafe { ffi_dispatch!(LIB, FcInit,) == FcTrue } {
109 | Some(Fontconfig { _initialised: () })
110 | } else {
111 | None
112 | }
113 | }
114 |
115 | /// Find a font of the given `family` (e.g. Dejavu Sans, FreeSerif),
116 | /// optionally filtering by `style`. Both fields are case-insensitive.
117 | pub fn find(&self, family: &str, style: Option<&str>) -> Option {
118 | Font::find(self, family, style)
119 | }
120 | }
121 |
122 | /// A very high-level view of a font, only concerned with the name and its file location.
123 | ///
124 | /// ##Example
125 | /// ```rust
126 | /// use fontconfig::{Font, Fontconfig};
127 | ///
128 | /// let fc = Fontconfig::new().unwrap();
129 | /// let font = fc.find("sans-serif", Some("italic")).unwrap();
130 | /// println!("Name: {}\nPath: {}", font.name, font.path.display());
131 | /// ```
132 | pub struct Font {
133 | /// The true name of this font
134 | pub name: String,
135 | /// The location of this font on the filesystem.
136 | pub path: PathBuf,
137 | /// The index of the font within the file.
138 | pub index: Option,
139 | }
140 |
141 | impl Font {
142 | fn find(fc: &Fontconfig, family: &str, style: Option<&str>) -> Option {
143 | let mut pat = Pattern::new(fc);
144 | let family = CString::new(family).ok()?;
145 | pat.add_string(FC_FAMILY, &family);
146 |
147 | if let Some(style) = style {
148 | let style = CString::new(style).ok()?;
149 | pat.add_string(FC_STYLE, &style);
150 | }
151 |
152 | let font_match = pat.font_match();
153 |
154 | font_match.name().and_then(|name| {
155 | font_match.filename().map(|filename| Font {
156 | name: name.to_owned(),
157 | path: PathBuf::from(filename),
158 | index: font_match.face_index(),
159 | })
160 | })
161 | }
162 |
163 | #[allow(dead_code)]
164 | fn print_debug(&self) {
165 | println!(
166 | "Name: {}\nPath: {}\nIndex: {:?}",
167 | self.name,
168 | self.path.display(),
169 | self.index
170 | );
171 | }
172 | }
173 |
174 | /// A safe wrapper around fontconfig's `FcPattern`.
175 | #[repr(C)]
176 | pub struct Pattern<'fc> {
177 | /// Raw pointer to `FcPattern`
178 | pat: *mut FcPattern,
179 | fc: &'fc Fontconfig,
180 | }
181 |
182 | impl<'fc> Pattern<'fc> {
183 | /// Create a new empty `Pattern`.
184 | pub fn new(fc: &Fontconfig) -> Pattern {
185 | let pat = unsafe { ffi_dispatch!(LIB, FcPatternCreate,) };
186 | assert!(!pat.is_null());
187 |
188 | Pattern { pat, fc }
189 | }
190 |
191 | /// Create a `Pattern` from a raw fontconfig FcPattern pointer.
192 | ///
193 | /// The pattern is referenced.
194 | ///
195 | /// **Safety:** The pattern pointer must be valid/non-null.
196 | pub unsafe fn from_pattern(fc: &Fontconfig, pat: *mut FcPattern) -> Pattern {
197 | ffi_dispatch!(LIB, FcPatternReference, pat);
198 |
199 | Pattern { pat, fc }
200 | }
201 |
202 | /// Add a key-value pair of type `String` to this pattern.
203 | ///
204 | /// See useful keys in the [fontconfig reference][1].
205 | ///
206 | /// [1]: http://www.freedesktop.org/software/fontconfig/fontconfig-devel/x19.html
207 | pub fn add_string(&mut self, name: &CStr, val: &CStr) {
208 | unsafe {
209 | ffi_dispatch!(
210 | LIB,
211 | FcPatternAddString,
212 | self.pat,
213 | name.as_ptr(),
214 | val.as_ptr() as *const u8
215 | );
216 | }
217 | }
218 |
219 | /// Add a key-value pair of type `Int` to this pattern
220 | ///
221 | /// See useful keys in the [fontconfig reference][1].
222 | ///
223 | /// [1]: http://www.freedesktop.org/software/fontconfig/fontconfig-devel/x19.html
224 | pub fn add_integer(&mut self, name: &CStr, val: c_int) {
225 | unsafe {
226 | ffi_dispatch!(LIB, FcPatternAddInteger, self.pat, name.as_ptr(), val);
227 | }
228 | }
229 |
230 | /// Get string the value for a key from this pattern.
231 | pub fn get_string<'a>(&'a self, name: &'a CStr) -> Option<&'a str> {
232 | unsafe {
233 | let mut ret: *mut sys::FcChar8 = ptr::null_mut();
234 | if ffi_dispatch!(
235 | LIB,
236 | FcPatternGetString,
237 | self.pat,
238 | name.as_ptr(),
239 | 0,
240 | &mut ret as *mut _
241 | ) == sys::FcResultMatch
242 | {
243 | let cstr = CStr::from_ptr(ret as *const c_char);
244 | Some(cstr.to_str().unwrap())
245 | } else {
246 | None
247 | }
248 | }
249 | }
250 |
251 | /// Get the integer value for a key from this pattern.
252 | pub fn get_int(&self, name: &CStr) -> Option {
253 | unsafe {
254 | let mut ret: i32 = 0;
255 | if ffi_dispatch!(
256 | LIB,
257 | FcPatternGetInteger,
258 | self.pat,
259 | name.as_ptr(),
260 | 0,
261 | &mut ret as *mut i32
262 | ) == sys::FcResultMatch
263 | {
264 | Some(ret)
265 | } else {
266 | None
267 | }
268 | }
269 | }
270 |
271 | /// Print this pattern to stdout with all its values.
272 | pub fn print(&self) {
273 | unsafe {
274 | ffi_dispatch!(LIB, FcPatternPrint, &*self.pat);
275 | }
276 | }
277 |
278 | /// Supplies default values for underspecified font patterns.
279 | ///
280 | /// * Patterns without a specified style or weight are set to Medium.
281 | /// * Patterns without a specified style or slant are set to Roman.
282 | /// * Patterns without a specified pixel size are given one computed from any specified point size
283 | /// (default 12), dpi (default 75) and scale (default 1).
284 | ///
285 | /// *Note:* [font_match][Self::font_match] and [sort_fonts][Self::sort_fonts] call this so you
286 | /// don't need to manually call it when using those methods.
287 | ///
288 | /// [Fontconfig reference](https://www.freedesktop.org/software/fontconfig/fontconfig-devel/fcdefaultsubstitute.html)
289 | pub fn default_substitute(&mut self) {
290 | unsafe {
291 | ffi_dispatch!(LIB, FcDefaultSubstitute, self.pat);
292 | }
293 | }
294 |
295 | /// Execute substitutions.
296 | ///
297 | /// *Note:* [font_match][Self::font_match] and [sort_fonts][Self::sort_fonts] call this so you
298 | /// don't need to manually call it when using those methods.
299 | ///
300 | /// [Fontconfig reference](https://www.freedesktop.org/software/fontconfig/fontconfig-devel/fcconfigsubstitute.html)
301 | pub fn config_substitute(&mut self) {
302 | unsafe {
303 | ffi_dispatch!(
304 | LIB,
305 | FcConfigSubstitute,
306 | ptr::null_mut(),
307 | self.pat,
308 | sys::FcMatchPattern
309 | );
310 | }
311 | }
312 |
313 | /// Get the best available match for this pattern, returned as a new pattern.
314 | pub fn font_match(&mut self) -> Pattern {
315 | self.config_substitute();
316 | self.default_substitute();
317 |
318 | unsafe {
319 | let mut res = sys::FcResultNoMatch;
320 | Pattern::from_pattern(
321 | self.fc,
322 | ffi_dispatch!(LIB, FcFontMatch, ptr::null_mut(), self.pat, &mut res),
323 | )
324 | }
325 | }
326 |
327 | /// Returns a [`FontSet`] containing fonts sorted by closeness to this pattern.
328 | ///
329 | /// If `trim` is true, elements in the list which don't include Unicode coverage not provided by
330 | /// earlier elements in the list are elided.
331 | ///
332 | /// See the [Fontconfig reference][1] for more details.
333 | ///
334 | /// [1]: https://www.freedesktop.org/software/fontconfig/fontconfig-devel/fcfontsort.html
335 | pub fn sort_fonts(&mut self, trim: bool) -> FontSet<'fc> {
336 | // Docs: This function should be called only after FcConfigSubstitute and FcDefaultSubstitute
337 | // have been called for p; otherwise the results will not be correct.
338 | self.config_substitute();
339 | self.default_substitute();
340 |
341 | // FcFontSort always returns a (possibly empty) set so we don't need to check this.
342 | let mut res = sys::FcResultNoMatch;
343 | let unicode_coverage = ptr::null_mut();
344 | let config = ptr::null_mut();
345 | unsafe {
346 | let raw_set = ffi_dispatch!(
347 | LIB,
348 | FcFontSort,
349 | config,
350 | self.pat,
351 | trim as FcBool,
352 | unicode_coverage,
353 | &mut res
354 | );
355 | FontSet::from_raw(self.fc, raw_set)
356 | }
357 | }
358 |
359 | /// Get the "fullname" (human-readable name) of this pattern.
360 | pub fn name(&self) -> Option<&str> {
361 | self.get_string(FC_FULLNAME)
362 | }
363 |
364 | /// Get the "file" (path on the filesystem) of this font pattern.
365 | pub fn filename(&self) -> Option<&str> {
366 | self.get_string(FC_FILE)
367 | }
368 |
369 | /// Get the "index" (The index of the font within the file) of this pattern.
370 | pub fn face_index(&self) -> Option {
371 | self.get_int(FC_INDEX)
372 | }
373 |
374 | /// Get the "slant" (Italic, oblique or roman) of this pattern.
375 | pub fn slant(&self) -> Option {
376 | self.get_int(FC_SLANT)
377 | }
378 |
379 | /// Get the "weight" (Light, medium, demibold, bold or black) of this pattern.
380 | pub fn weight(&self) -> Option {
381 | self.get_int(FC_WEIGHT)
382 | }
383 |
384 | /// Get the "width" (Condensed, normal or expanded) of this pattern.
385 | pub fn width(&self) -> Option {
386 | self.get_int(FC_WIDTH)
387 | }
388 |
389 | /// Get the "fontformat" ("TrueType" "Type 1" "BDF" "PCF" "Type 42" "CID Type 1" "CFF" "PFR" "Windows FNT") of this pattern.
390 | pub fn format(&self) -> Result {
391 | self.get_string(FC_FONTFORMAT)
392 | .ok_or_else(|| UnknownFontFormat(String::new()))
393 | .and_then(|format| format.parse())
394 | }
395 |
396 | /// Returns a raw pointer to underlying `FcPattern`.
397 | pub fn as_ptr(&self) -> *const FcPattern {
398 | self.pat
399 | }
400 |
401 | /// Returns an unsafe mutable pointer to the underlying `FcPattern`.
402 | pub fn as_mut_ptr(&mut self) -> *mut FcPattern {
403 | self.pat
404 | }
405 | }
406 |
407 | impl<'fc> std::fmt::Debug for Pattern<'fc> {
408 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
409 | let fcstr = unsafe { ffi_dispatch!(LIB, FcNameUnparse, self.pat) };
410 | let fcstr = unsafe { CStr::from_ptr(fcstr as *const c_char) };
411 | let result = write!(f, "{:?}", fcstr);
412 | unsafe { ffi_dispatch!(LIB, FcStrFree, fcstr.as_ptr() as *mut u8) };
413 | result
414 | }
415 | }
416 |
417 | impl<'fc> Clone for Pattern<'fc> {
418 | fn clone(&self) -> Self {
419 | let clone = unsafe { ffi_dispatch!(LIB, FcPatternDuplicate, self.pat) };
420 | Pattern {
421 | pat: clone,
422 | fc: self.fc,
423 | }
424 | }
425 | }
426 |
427 | impl<'fc> Drop for Pattern<'fc> {
428 | fn drop(&mut self) {
429 | unsafe {
430 | ffi_dispatch!(LIB, FcPatternDestroy, self.pat);
431 | }
432 | }
433 | }
434 |
435 | impl Pattern<'_> {
436 | /// Get the languages set of this pattern.
437 | pub fn lang_set(&self) -> Option> {
438 | unsafe {
439 | let mut ret: *mut sys::FcLangSet = ptr::null_mut();
440 | if ffi_dispatch!(
441 | LIB,
442 | FcPatternGetLangSet,
443 | self.pat,
444 | FC_LANG.as_ptr(),
445 | 0,
446 | &mut ret as *mut _
447 | ) == sys::FcResultMatch
448 | {
449 | let ss: *mut sys::FcStrSet = ffi_dispatch!(LIB, FcLangSetGetLangs, ret);
450 | let lang_strs: *mut sys::FcStrList = ffi_dispatch!(LIB, FcStrListCreate, ss);
451 | Some(StrList::from_raw(self.fc, lang_strs))
452 | } else {
453 | None
454 | }
455 | }
456 | }
457 | }
458 |
459 | /// Wrapper around `FcStrList`
460 | ///
461 | /// The wrapper implements `Iterator` so it can be iterated directly, filtered etc.
462 | /// **Note:** Any entries in the `StrList` that are not valid UTF-8 will be skipped.
463 | ///
464 | /// ```
465 | /// use fontconfig::{Fontconfig, Pattern};
466 | ///
467 | /// let fc = Fontconfig::new().expect("unable to init Fontconfig");
468 | ///
469 | /// // Find fonts that support japanese
470 | /// let fonts = fontconfig::list_fonts(&Pattern::new(&fc), None);
471 | /// let ja_fonts: Vec<_> = fonts
472 | /// .iter()
473 | /// .filter(|p| p.lang_set().map_or(false, |mut langs| langs.any(|l| l == "ja")))
474 | /// .collect();
475 | /// ```
476 | pub struct StrList<'a> {
477 | list: *mut sys::FcStrList,
478 | _life: PhantomData<&'a sys::FcStrList>,
479 | }
480 |
481 | impl<'a> StrList<'a> {
482 | unsafe fn from_raw(_: &Fontconfig, raw_list: *mut sys::FcStrSet) -> Self {
483 | Self {
484 | list: raw_list,
485 | _life: PhantomData,
486 | }
487 | }
488 | }
489 |
490 | impl<'a> Drop for StrList<'a> {
491 | fn drop(&mut self) {
492 | unsafe { ffi_dispatch!(LIB, FcStrListDone, self.list) };
493 | }
494 | }
495 |
496 | impl<'a> Iterator for StrList<'a> {
497 | type Item = &'a str;
498 |
499 | fn next(&mut self) -> Option<&'a str> {
500 | let lang_str: *mut sys::FcChar8 = unsafe { ffi_dispatch!(LIB, FcStrListNext, self.list) };
501 | if lang_str.is_null() {
502 | None
503 | } else {
504 | match unsafe { CStr::from_ptr(lang_str as *const c_char) }.to_str() {
505 | Ok(s) => Some(s),
506 | _ => self.next(),
507 | }
508 | }
509 | }
510 | }
511 |
512 | /// Wrapper around `FcFontSet`.
513 | pub struct FontSet<'fc> {
514 | fcset: *mut sys::FcFontSet,
515 | fc: &'fc Fontconfig,
516 | }
517 |
518 | impl<'fc> FontSet<'fc> {
519 | /// Create a new, empty `FontSet`.
520 | pub fn new(fc: &Fontconfig) -> FontSet {
521 | let fcset = unsafe { ffi_dispatch!(LIB, FcFontSetCreate,) };
522 | FontSet { fcset, fc }
523 | }
524 |
525 | /// Wrap an existing `FcFontSet`.
526 | ///
527 | /// The returned wrapper assumes ownership of the `FcFontSet`.
528 | ///
529 | /// **Safety:** The font set pointer must be valid/non-null.
530 | pub unsafe fn from_raw(fc: &Fontconfig, raw_set: *mut sys::FcFontSet) -> FontSet {
531 | FontSet { fcset: raw_set, fc }
532 | }
533 |
534 | /// Add a `Pattern` to this `FontSet`.
535 | pub fn add_pattern(&mut self, pat: Pattern) {
536 | unsafe {
537 | ffi_dispatch!(LIB, FcFontSetAdd, self.fcset, pat.pat);
538 | mem::forget(pat);
539 | }
540 | }
541 |
542 | /// Print this `FontSet` to stdout.
543 | pub fn print(&self) {
544 | unsafe { ffi_dispatch!(LIB, FcFontSetPrint, self.fcset) };
545 | }
546 |
547 | /// Iterate the fonts (as `Patterns`) in this `FontSet`.
548 | pub fn iter(&self) -> impl Iterator- > {
549 | let patterns = unsafe {
550 | let fontset = self.fcset;
551 | std::slice::from_raw_parts((*fontset).fonts, (*fontset).nfont as usize)
552 | };
553 | patterns
554 | .iter()
555 | .map(move |&pat| unsafe { Pattern::from_pattern(self.fc, pat) })
556 | }
557 | }
558 |
559 | impl<'fc> Drop for FontSet<'fc> {
560 | fn drop(&mut self) {
561 | unsafe { ffi_dispatch!(LIB, FcFontSetDestroy, self.fcset) }
562 | }
563 | }
564 |
565 | /// Return a `FontSet` containing Fonts that match the supplied `pattern` and `objects`.
566 | pub fn list_fonts<'fc>(pattern: &Pattern<'fc>, objects: Option<&ObjectSet>) -> FontSet<'fc> {
567 | let os = objects.map(|o| o.fcset).unwrap_or(ptr::null_mut());
568 | unsafe {
569 | let raw_set = ffi_dispatch!(LIB, FcFontList, ptr::null_mut(), pattern.pat, os);
570 | FontSet::from_raw(pattern.fc, raw_set)
571 | }
572 | }
573 |
574 | /// Wrapper around `FcObjectSet`.
575 | pub struct ObjectSet {
576 | fcset: *mut sys::FcObjectSet,
577 | }
578 |
579 | impl ObjectSet {
580 | /// Create a new, empty `ObjectSet`.
581 | pub fn new(_: &Fontconfig) -> ObjectSet {
582 | let fcset = unsafe { ffi_dispatch!(LIB, FcObjectSetCreate,) };
583 | assert!(!fcset.is_null());
584 |
585 | ObjectSet { fcset }
586 | }
587 |
588 | /// Wrap an existing `FcObjectSet`.
589 | ///
590 | /// The `FcObjectSet` must not be null. This method assumes ownership of the `FcObjectSet`.
591 | ///
592 | /// **Safety:** The object set pointer must be valid/non-null.
593 | pub unsafe fn from_raw(_: &Fontconfig, raw_set: *mut sys::FcObjectSet) -> ObjectSet {
594 | ObjectSet { fcset: raw_set }
595 | }
596 |
597 | /// Add a string to the `ObjectSet`.
598 | pub fn add(&mut self, name: &CStr) {
599 | let res = unsafe { ffi_dispatch!(LIB, FcObjectSetAdd, self.fcset, name.as_ptr()) };
600 | assert_eq!(res, FcTrue);
601 | }
602 | }
603 |
604 | impl Drop for ObjectSet {
605 | fn drop(&mut self) {
606 | unsafe { ffi_dispatch!(LIB, FcObjectSetDestroy, self.fcset) }
607 | }
608 | }
609 |
610 | impl FromStr for FontFormat {
611 | type Err = UnknownFontFormat;
612 |
613 | fn from_str(s: &str) -> Result {
614 | match s {
615 | "TrueType" => Ok(FontFormat::TrueType),
616 | "Type 1" => Ok(FontFormat::Type1),
617 | "BDF" => Ok(FontFormat::BDF),
618 | "PCF" => Ok(FontFormat::PCF),
619 | "Type 42" => Ok(FontFormat::Type42),
620 | "CID Type 1" => Ok(FontFormat::CIDType1),
621 | "CFF" => Ok(FontFormat::CFF),
622 | "PFR" => Ok(FontFormat::PFR),
623 | "Windows FNT" => Ok(FontFormat::WindowsFNT),
624 | _ => Err(UnknownFontFormat(s.to_string())),
625 | }
626 | }
627 | }
628 |
629 | #[cfg(test)]
630 | mod tests {
631 | use super::*;
632 |
633 | #[test]
634 | fn it_works() {
635 | assert!(Fontconfig::new().is_some())
636 | }
637 |
638 | #[test]
639 | fn test_find_font() {
640 | let fc = Fontconfig::new().unwrap();
641 | fc.find("dejavu sans", None).unwrap().print_debug();
642 | fc.find("dejavu sans", Some("oblique"))
643 | .unwrap()
644 | .print_debug();
645 | }
646 |
647 | #[test]
648 | fn test_iter_and_print() {
649 | let fc = Fontconfig::new().unwrap();
650 | let fontset = list_fonts(&Pattern::new(&fc), None);
651 | for pattern in fontset.iter() {
652 | println!("{:?}", pattern.name());
653 | }
654 |
655 | // Ensure that the set can be iterated again
656 | assert!(fontset.iter().count() > 0);
657 | }
658 |
659 | #[test]
660 | fn iter_lang_set() {
661 | let fc = Fontconfig::new().unwrap();
662 | let mut pat = Pattern::new(&fc);
663 | let family = CString::new("dejavu sans").unwrap();
664 | pat.add_string(FC_FAMILY, &family);
665 | let pattern = pat.font_match();
666 | for lang in pattern.lang_set().unwrap() {
667 | println!("{:?}", lang);
668 | }
669 |
670 | // Test find
671 | assert!(pattern
672 | .lang_set()
673 | .unwrap()
674 | .find(|&lang| lang == "za")
675 | .is_some());
676 |
677 | // Test collect
678 | let langs = pattern.lang_set().unwrap().collect::>();
679 | assert!(langs.iter().find(|&&l| l == "ie").is_some());
680 | }
681 |
682 | #[test]
683 | fn test_sort_fonts() {
684 | let fc = Fontconfig::new().unwrap();
685 | let mut pat = Pattern::new(&fc);
686 | let family = CString::new("dejavu sans").unwrap();
687 | pat.add_string(FC_FAMILY, &family);
688 |
689 | let style = CString::new("oblique").unwrap();
690 | pat.add_string(FC_STYLE, &style);
691 |
692 | let font_set = pat.sort_fonts(false);
693 |
694 | for pattern in font_set.iter() {
695 | println!("{:?}", pattern.name());
696 | }
697 |
698 | // Ensure that the set can be iterated again
699 | assert!(font_set.iter().count() > 0);
700 | }
701 | }
702 |
--------------------------------------------------------------------------------