]> git.seodisparate.com - mpd_info_screen/commitdiff
Impl freetype use, bindgen for fontconfig
authorStephen Seo <seo.disparate@gmail.com>
Sun, 31 Jul 2022 10:52:00 +0000 (19:52 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 31 Jul 2022 10:52:04 +0000 (19:52 +0900)
TODO: fontconfig

Cargo.lock
Cargo.toml
build.rs [new file with mode: 0644]
src/bindgen_wrapper.h [new file with mode: 0644]
src/unicode_support/fontconfig.rs
src/unicode_support/freetype.rs

index 4286095290877ce8e909e0ffc980440cb7163365..2a53ad652a4bbe0a9bf50f1ee65704e77b5406a5 100644 (file)
@@ -30,6 +30,15 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
 
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "alsa"
 version = "0.6.0"
@@ -120,21 +129,26 @@ checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
 
 [[package]]
 name = "bindgen"
-version = "0.59.2"
+version = "0.53.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
+checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5"
 dependencies = [
  "bitflags",
  "cexpr",
+ "cfg-if 0.1.10",
  "clang-sys",
+ "clap",
+ "env_logger",
  "lazy_static",
  "lazycell",
+ "log",
  "peeking_take_while",
  "proc-macro2",
  "quote",
  "regex",
  "rustc-hash",
  "shlex",
+ "which",
 ]
 
 [[package]]
@@ -264,11 +278,11 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
 
 [[package]]
 name = "cexpr"
-version = "0.6.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
 dependencies = [
- "nom",
+ "nom 5.1.2",
 ]
 
 [[package]]
@@ -294,13 +308,13 @@ dependencies = [
 
 [[package]]
 name = "clang-sys"
-version = "1.3.3"
+version = "0.29.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
+checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
 dependencies = [
  "glob",
  "libc",
- "libloading 0.7.3",
+ "libloading 0.5.2",
 ]
 
 [[package]]
@@ -380,12 +394,6 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "const-cstr"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6"
-
 [[package]]
 name = "core-foundation"
 version = "0.6.4"
@@ -496,9 +504,9 @@ dependencies = [
 
 [[package]]
 name = "coreaudio-sys"
-version = "0.2.10"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dff444d80630d7073077d38d40b4501fd518bd2b922c2a55edcc8b0f7be57e6"
+checksum = "17f73df0f29f4c3c374854f076c47dc018f19acaa63538880dba0937ad4fa8d7"
 dependencies = [
  "bindgen",
 ]
@@ -781,6 +789,19 @@ version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
 
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
 [[package]]
 name = "error-chain"
 version = "0.12.4"
@@ -862,15 +883,6 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
-[[package]]
-name = "fontconfig"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a25320ad784a9578ada0b395dd7dcd2321109404bbb341ec27e64b01a1e49b47"
-dependencies = [
- "yeslogic-fontconfig-sys",
-]
-
 [[package]]
 name = "foreign-types"
 version = "0.3.2"
@@ -1215,6 +1227,15 @@ version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549"
 
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -1385,6 +1406,16 @@ version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
 
+[[package]]
+name = "libloading"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
+dependencies = [
+ "cc",
+ "winapi",
+]
+
 [[package]]
 name = "libloading"
 version = "0.6.7"
@@ -1639,7 +1670,7 @@ dependencies = [
 name = "mpd_info_screen"
 version = "0.2.20"
 dependencies = [
- "fontconfig",
+ "bindgen",
  "freetype",
  "ggez",
  "image 0.24.3",
@@ -1793,6 +1824,16 @@ dependencies = [
  "memoffset",
 ]
 
+[[package]]
+name = "nom"
+version = "5.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
+dependencies = [
+ "memchr",
+ "version_check",
+]
+
 [[package]]
 name = "nom"
 version = "7.1.1"
@@ -2156,6 +2197,12 @@ dependencies = [
  "unicase",
 ]
 
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
 [[package]]
 name = "quote"
 version = "1.0.20"
@@ -2264,6 +2311,8 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
 dependencies = [
+ "aho-corasick",
+ "memchr",
  "regex-syntax",
 ]
 
@@ -2446,9 +2495,9 @@ dependencies = [
 
 [[package]]
 name = "shlex"
-version = "1.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 
 [[package]]
 name = "sid"
@@ -2660,6 +2709,15 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "textwrap"
 version = "0.11.0"
@@ -2982,6 +3040,15 @@ version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
 
+[[package]]
+name = "which"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -3062,7 +3129,7 @@ version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7"
 dependencies = [
- "nom",
+ "nom 7.1.1",
 ]
 
 [[package]]
@@ -3086,18 +3153,6 @@ version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
 
-[[package]]
-name = "yeslogic-fontconfig-sys"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386"
-dependencies = [
- "const-cstr",
- "dlib 0.5.0",
- "once_cell",
- "pkg-config",
-]
-
 [[package]]
 name = "zip"
 version = "0.5.13"
index 93a2ac869b34224a15b00caf85d42d21f4b00759..abb330c5271b234cfd466edde8549a07ec81b96c 100644 (file)
@@ -13,7 +13,9 @@ structopt = "0.3"
 image = "0.24"
 ggez = "0.7"
 freetype = { version = "0.7", optional = true }
-fontconfig = { version = "0.5", optional = true }
+
+[build-dependencies]
+bindgen = { version = "0.53", optional = true }
 
 [features]
-unicode_support = ["dep:freetype", "dep:fontconfig"]
+unicode_support = ["dep:freetype", "dep:bindgen"]
diff --git a/build.rs b/build.rs
new file mode 100644 (file)
index 0000000..458302e
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,26 @@
+use std::env;
+use std::path::PathBuf;
+
+use bindgen;
+
+#[cfg(not(feature = "unicode_support"))]
+fn main() {
+}
+
+#[cfg(feature = "unicode_support")]
+fn main() {
+    println!("cargo:rustc-link-search=/usr/lib");
+    println!("cargo:rustc-link-lib=fontconfig");
+    println!("cargo:rerun-if-changed=src/bindgen_wrapper.h");
+
+    let bindings = bindgen::Builder::default()
+        .header("src/bindgen_wrapper.h")
+        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
+        .generate()
+        .expect("Unable to generate bindings");
+
+    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+    bindings
+        .write_to_file(out_path.join("unicode_support_bindings.rs"))
+        .expect("Couldn't write bindings");
+}
diff --git a/src/bindgen_wrapper.h b/src/bindgen_wrapper.h
new file mode 100644 (file)
index 0000000..79bf5b9
--- /dev/null
@@ -0,0 +1 @@
+#include <fontconfig/fontconfig.h>
index 8f6520db3dbbb1d785c99105b8860e1847b1bc71..74de4e8dd7ed4ba07236ad34e5320a3cfad1b4ae 100644 (file)
@@ -1 +1,9 @@
-use fontconfig;
+mod ffi {
+    mod bindgen {
+        #![allow(non_upper_case_globals)]
+        #![allow(non_camel_case_types)]
+        #![allow(non_snake_case)]
+
+        include!(concat!(env!("OUT_DIR"), "/unicode_support_bindings.rs"));
+    }
+}
index 9dab281f2a901b34b52c60180a024e692ddc39b1..91705d51be3d6594c6bcebff59687922a4d0f6e1 100644 (file)
@@ -1 +1,157 @@
-use freetype;
+use std::path::Path;
+
+mod ffi {
+    use freetype::freetype::{
+        FT_Done_Face, FT_Done_Library, FT_Face, FT_FaceRec_, FT_Get_Char_Index, FT_Init_FreeType,
+        FT_Library, FT_ModuleRec_, FT_Open_Args, FT_Open_Face, FT_Parameter_, FT_StreamRec_,
+        FT_OPEN_PATHNAME,
+    };
+    use std::ffi::CString;
+    use std::path::Path;
+
+    pub struct FTLibrary {
+        library: FT_Library,
+    }
+
+    impl Drop for FTLibrary {
+        fn drop(&mut self) {
+            if !self.library.is_null() {
+                unsafe {
+                    FT_Done_Library(self.library);
+                }
+            }
+        }
+    }
+
+    impl FTLibrary {
+        pub fn new() -> Option<FTLibrary> {
+            unsafe {
+                let mut library_ptr: FT_Library = 0 as FT_Library;
+                if FT_Init_FreeType(&mut library_ptr) != 0 {
+                    Some(FTLibrary {
+                        library: library_ptr,
+                    })
+                } else {
+                    None
+                }
+            }
+        }
+
+        pub fn get(&self) -> FT_Library {
+            self.library
+        }
+    }
+
+    pub struct FTOpenArgs {
+        args: FT_Open_Args,
+        pathname: Option<CString>,
+    }
+
+    impl FTOpenArgs {
+        pub fn new_with_path(path: &Path) -> Self {
+            unsafe {
+                let cstring: CString = CString::from_vec_unchecked(
+                    path.as_os_str().to_str().unwrap().as_bytes().to_vec(),
+                );
+                let mut args = FT_Open_Args {
+                    flags: FT_OPEN_PATHNAME,
+                    memory_base: 0 as *const u8,
+                    memory_size: 0,
+                    pathname: cstring.as_ptr() as *mut i8,
+                    stream: 0 as *mut FT_StreamRec_,
+                    driver: 0 as *mut FT_ModuleRec_,
+                    num_params: 0,
+                    params: 0 as *mut FT_Parameter_,
+                };
+
+                FTOpenArgs {
+                    args,
+                    pathname: Some(cstring),
+                }
+            }
+        }
+
+        pub fn get_args(&self) -> FT_Open_Args {
+            self.args
+        }
+
+        pub fn get_ptr(&mut self) -> *mut FT_Open_Args {
+            &mut self.args as *mut FT_Open_Args
+        }
+    }
+
+    pub struct FTFaces {
+        faces: Vec<FT_Face>,
+    }
+
+    impl Drop for FTFaces {
+        fn drop(&mut self) {
+            for face in &self.faces {
+                unsafe {
+                    FT_Done_Face(*face);
+                }
+            }
+        }
+    }
+
+    impl FTFaces {
+        pub fn new(library: &FTLibrary, args: &mut FTOpenArgs) -> Result<FTFaces, ()> {
+            let mut faces = FTFaces { faces: Vec::new() };
+            unsafe {
+                let count;
+                let mut face: FT_Face = 0 as FT_Face;
+                // first get number of faces
+                let mut result = FT_Open_Face(
+                    library.get(),
+                    args.get_ptr(),
+                    -1,
+                    &mut face as *mut *mut FT_FaceRec_,
+                );
+                if result != 0 {
+                    FT_Done_Face(face);
+                    return Err(());
+                }
+                count = (*face).num_faces;
+
+                for i in 0..count {
+                    result = FT_Open_Face(
+                        library.get(),
+                        args.get_ptr(),
+                        i,
+                        &mut face as *mut *mut FT_FaceRec_,
+                    );
+                    if result != 0 {
+                        FT_Done_Face(face);
+                        return Err(());
+                    }
+                    faces.faces.push(face);
+                }
+            }
+
+            Ok(faces)
+        }
+
+        pub fn has_char(&self, c: char) -> bool {
+            let char_value: u64 = c as u64;
+
+            for face in &self.faces {
+                unsafe {
+                    let result = FT_Get_Char_Index(*face, char_value);
+                    if result != 0 {
+                        return true;
+                    }
+                }
+            }
+
+            false
+        }
+    }
+}
+
+pub fn font_has_char(c: char, font_path: &Path) -> Result<bool, ()> {
+    let library = ffi::FTLibrary::new().ok_or(())?;
+    let mut args = ffi::FTOpenArgs::new_with_path(font_path);
+    let faces = ffi::FTFaces::new(&library, &mut args)?;
+
+    Ok(faces.has_char(c))
+}