diff --git a/Cargo.lock b/Cargo.lock index e272e195..51eb64bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,27 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base64" version = "0.6.0" @@ -109,6 +130,11 @@ name = "bitflags" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.3" @@ -174,6 +200,18 @@ dependencies = [ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cocoa" +version = "0.18.0" +source = "git+https://github.com/servo/core-foundation-rs#540490a9094a756fb610ee157b064d48a7f180a8" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.0 (git+https://github.com/servo/core-foundation-rs)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "color_quant" version = "1.0.1" @@ -193,35 +231,35 @@ dependencies = [ [[package]] name = "core-foundation" version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/servo/core-foundation-rs#540490a9094a756fb610ee157b064d48a7f180a8" dependencies = [ - "core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.1 (git+https://github.com/servo/core-foundation-rs)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/servo/core-foundation-rs#540490a9094a756fb610ee157b064d48a7f180a8" [[package]] name = "core-graphics" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.17.0" +source = "git+https://github.com/servo/core-foundation-rs#540490a9094a756fb610ee157b064d48a7f180a8" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.1 (git+https://github.com/servo/core-foundation-rs)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-text" -version = "11.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "13.0.0" +source = "git+https://github.com/servo/core-foundation-rs#540490a9094a756fb610ee157b064d48a7f180a8" dependencies = [ - "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.1 (git+https://github.com/servo/core-foundation-rs)", + "core-graphics 0.17.0 (git+https://github.com/servo/core-foundation-rs)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -266,18 +304,30 @@ dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "dwrite-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "dwrote" +version = "0.5.0" +source = "git+https://github.com/servo/dwrote-rs#28896a9346e60fdd7e3b929494bd7f7bfe0c2e72" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,6 +356,69 @@ dependencies = [ "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "expat-sys" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "float-ord" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "font-kit" +version = "0.1.0" +source = "git+https://github.com/pcwalton/font-kit#b6c001f663839961b70fcea1101398f589ce4fb9" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.18.0 (git+https://github.com/servo/core-foundation-rs)", + "core-foundation 0.6.1 (git+https://github.com/servo/core-foundation-rs)", + "core-graphics 0.17.0 (git+https://github.com/servo/core-foundation-rs)", + "core-text 13.0.0 (git+https://github.com/servo/core-foundation-rs)", + "dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dwrote 0.5.0 (git+https://github.com/servo/dwrote-rs)", + "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "freetype 0.4.1 (git+https://github.com/servo/rust-freetype)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fontsan" version = "0.4.0" @@ -331,8 +444,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "freetype" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.4.1" +source = "git+https://github.com/servo/rust-freetype#e6ead0a811a604654d410c8ce9c43ee142329adc" dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -528,6 +641,14 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.2" @@ -542,15 +663,6 @@ dependencies = [ "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "language-tags" version = "0.2.2" @@ -623,6 +735,14 @@ name = "lzw" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "matches" version = "0.1.6" @@ -636,6 +756,15 @@ dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memmap" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memoffset" version = "0.2.1" @@ -713,6 +842,14 @@ dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "objc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pango-sys" version = "0.5.0" @@ -729,36 +866,13 @@ dependencies = [ name = "pathfinder" version = "0.2.0" dependencies = [ - "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.1.0 (git+https://github.com/pcwalton/font-kit)", "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pathfinder_font_renderer 0.5.0", "pathfinder_partitioner 0.2.0", "pathfinder_path_utils 0.2.0", ] -[[package]] -name = "pathfinder_font_renderer" -version = "0.5.0" -dependencies = [ - "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-text 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pathfinder_gfx_utils" version = "0.2.0" @@ -805,6 +919,7 @@ dependencies = [ "cairo-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.1.0 (git+https://github.com/pcwalton/font-kit)", "fontsan 0.4.0 (git+https://github.com/servo/fontsan.git)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -812,7 +927,6 @@ dependencies = [ "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lyon_geom 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pathfinder_font_renderer 0.5.0", "pathfinder_partitioner 0.2.0", "pathfinder_path_utils 0.2.0", "rocket 0.4.0-dev (git+https://github.com/SergioBenitez/rocket)", @@ -1050,11 +1164,24 @@ dependencies = [ "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-demangle" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "same-file" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -1093,6 +1220,25 @@ dependencies = [ "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "servo-fontconfig" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "servo-fontconfig-sys" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "servo-freetype-sys" version = "4.0.3" @@ -1130,6 +1276,17 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termcolor" version = "0.3.6" @@ -1257,15 +1414,6 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "uuid-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "vec_map" version = "0.8.1" @@ -1281,6 +1429,15 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -1295,11 +1452,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1336,12 +1488,15 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33a67fd81e1922dddc335887516f2f5254534e89c9d39fa89bca5d79bd150d34" "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" +"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" +"checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9" "checksum bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2fb9e29e72fd6bc12071533d5dc7664cb01480c59406f656d7ac25c7bd8ff7" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum c_vec 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6237ac5a4b1e81c213c24c6437964c61e646df910a914b4ab1487b46df20bd13" "checksum cairo-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b5695f59fd036fe5741bc5a4eb20c78fbe42256e3b08a2af26bbcbe8070bf3" @@ -1350,25 +1505,32 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3" +"checksum cocoa 0.18.0 (git+https://github.com/servo/core-foundation-rs)" = "" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" "checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "" -"checksum core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc3532ec724375c7cb7ff0a097b714fde180bb1f6ed2ab27cfcd99ffca873cd2" -"checksum core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3fb15cdbdd9cf8b82d97d0296bb5cd3631bba58d6e31650a002a8e7fb5721f9" -"checksum core-graphics 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92801c908ea6301ae619ed842a72e01098085fc321b9c2f3f833dad555bba055" -"checksum core-text 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "157ff38a92496dc676ce36d9124554e9ac66f1c1039f952690ac64f71cfa5968" +"checksum core-foundation 0.6.1 (git+https://github.com/servo/core-foundation-rs)" = "" +"checksum core-foundation-sys 0.6.1 (git+https://github.com/servo/core-foundation-rs)" = "" +"checksum core-graphics 0.17.0 (git+https://github.com/servo/core-foundation-rs)" = "" +"checksum core-text 13.0.0 (git+https://github.com/servo/core-foundation-rs)" = "" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" +"checksum dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "37a76dd8b997af7107d0bb69d43903cf37153a18266f8b3fdb9911f28efb5444" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7918280f33862bc8542212d74f2149b1a87ab402fd15f4ce9a1c56582958d6e" +"checksum dwrote 0.5.0 (git+https://github.com/servo/dwrote-rs)" = "" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a" "checksum euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a2ebdf55fb9d6329046e026329a55ef8fbaae5ea833f56e170beb3125a8a5f" +"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1" +"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" +"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" +"checksum float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +"checksum font-kit 0.1.0 (git+https://github.com/pcwalton/font-kit)" = "" "checksum fontsan 0.4.0 (git+https://github.com/servo/fontsan.git)" = "" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d" +"checksum freetype 0.4.1 (git+https://github.com/servo/rust-freetype)" = "" "checksum gdk-pixbuf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16160d212ae91abe9f3324c3fb233929ba322dde63585d15cda3336f8c529ed1" "checksum gdk-pixbuf-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "798f97101eea8180da363d0e80e07ec7ec6d1809306601c0100c1de5bc8b4f52" "checksum gdk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4ee916f5f25c5f4b21bd9dcb12a216ae697406940ff9476358c308a8ececada" @@ -1386,9 +1548,9 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum inflate 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6f53b811ee8e2057ccf9643ca6b4277de90efaf5e61e55fd5254576926bb4245" "checksum isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6c324313540cd4d7ba008d43dc6606a32a5579f13cc17b2804c13096f0a5c522" +"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3" @@ -1400,8 +1562,10 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum lyon_geom 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "216bfb2b880554865fa9deaa14671ab9f1368b942e7007cc8c97c083ac8a7f45" "checksum lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9dc8e0746b7cca11960b602f7fe037bb067746a01eab4aa502fed1494544843" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" +"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" @@ -1412,6 +1576,7 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9833ab0efe5361b1e2122a0544a5d3359576911a42cb098c2e59be8650807367" "checksum pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34f34a1be107fe16abb2744e0e206bee4b3b07460b5fddd3009a6aaf60bd69ab" "checksum pear 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=b475140)" = "" "checksum pear_codegen 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=b475140)" = "" @@ -1435,17 +1600,22 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/rocket)" = "" "checksum rsvg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2032b49fe075a3b921573286f7debe130aebdac6cb37fb197f9b517a4237024" "checksum rsvg-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ceca0b663cfddd09062d7e3fe0a729765d1e61bbbbb6a31d5e23d141ff0db38" +"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" "checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" "checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2" +"checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9" +"checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a" "checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b" "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" "checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea" +"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" @@ -1464,13 +1634,12 @@ source = "git+https://github.com/SergioBenitez/ring?branch=v0.12#9ccfa153a27aecc "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum uuid-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "383cea1fd3b68c33bbdd25af09bc50e70f4c9f1d9b18e39e514e4acf760ec5d2" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" diff --git a/Cargo.toml b/Cargo.toml index 7d5fec2e..8cd5fc5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] members = [ - "font-renderer", "gfx-utils", "partitioner", "path-utils", diff --git a/demo/server/Cargo.toml b/demo/server/Cargo.toml index 2cd0fadb..bed701d7 100644 --- a/demo/server/Cargo.toml +++ b/demo/server/Cargo.toml @@ -5,8 +5,8 @@ authors = ["Patrick Walton "] [features] default = [] -freetype = ["pathfinder_font_renderer/freetype"] -reftests = ["rsvg", "cairo-rs", "pathfinder_font_renderer/freetype"] +freetype = ["font-kit/loader-freetype-default"] +reftests = ["rsvg", "cairo-rs", "font-kit/loader-freetype-default"] [dependencies] app_units = "0.7" @@ -45,8 +45,8 @@ git = "https://github.com/SergioBenitez/rocket" [dependencies.rocket_contrib] git = "https://github.com/SergioBenitez/rocket" -[dependencies.pathfinder_font_renderer] -path = "../../font-renderer" +[dependencies.font-kit] +git = "https://github.com/pcwalton/font-kit" [dependencies.pathfinder_partitioner] path = "../../partitioner" diff --git a/demo/server/src/main.rs b/demo/server/src/main.rs index bb5c5e50..ab493e5f 100644 --- a/demo/server/src/main.rs +++ b/demo/server/src/main.rs @@ -15,12 +15,12 @@ extern crate app_units; extern crate base64; extern crate env_logger; extern crate euclid; +extern crate font_kit; extern crate fontsan; extern crate image; extern crate lru_cache; extern crate lyon_geom; extern crate lyon_path; -extern crate pathfinder_font_renderer; extern crate pathfinder_partitioner; extern crate pathfinder_path_utils; extern crate rocket; @@ -36,15 +36,17 @@ extern crate cairo; #[cfg(feature = "reftests")] extern crate rsvg; -use app_units::Au; use euclid::{Point2D, Transform2D}; +use font_kit::canvas::Format as FontKitFormat; +use font_kit::canvas::{Canvas, RasterizationOptions}; +use font_kit::font::Font; +use font_kit::hinting::HintingOptions; +use font_kit::loaders; use image::{DynamicImage, ImageBuffer, ImageFormat, ImageRgba8}; use lru_cache::LruCache; use lyon_path::PathEvent; use lyon_path::builder::{FlatPathBuilder, PathBuilder}; use lyon_path::iterator::PathIter; -use pathfinder_font_renderer::{FontContext, FontInstance, GlyphImage}; -use pathfinder_font_renderer::{GlyphKey, SubpixelOffset}; use pathfinder_partitioner::FillRule; use pathfinder_partitioner::mesh_pack::MeshPack; use pathfinder_partitioner::partitioner::Partitioner; @@ -58,14 +60,10 @@ use rocket_contrib::json::Json; use std::fs::File; use std::io::{self, Cursor, Read}; use std::path::{self, PathBuf}; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use std::u32; -#[cfg(target_os = "macos")] -use pathfinder_font_renderer::core_graphics; - #[cfg(feature = "reftests")] use euclid::Size2D; #[cfg(feature = "reftests")] @@ -79,8 +77,6 @@ const MESH_PACK_CACHE_SIZE: usize = 16; const CUBIC_TO_QUADRATIC_APPROX_TOLERANCE: f32 = 5.0; -static NEXT_FONT_KEY: AtomicUsize = ATOMIC_USIZE_INIT; - lazy_static! { static ref MESH_PACK_CACHE: Mutex> = { Mutex::new(LruCache::new(MESH_PACK_CACHE_SIZE)) @@ -267,15 +263,6 @@ struct PartitionSvgPathCommand { values: Vec, } -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)] -struct FontKey(usize); - -impl FontKey { - fn new() -> FontKey { - FontKey(NEXT_FONT_KEY.fetch_add(1, Ordering::SeqCst)) - } -} - struct PathPartitioningResult { encoded_data: Arc>, time: Duration, @@ -409,31 +396,6 @@ fn svg_data_from_request(builtin_svg_name: &str) -> Result>, SvgErro } } -#[cfg(target_os = "macos")] -fn rasterize_glyph_with_core_graphics(font_key: &FontKey, - font_index: u32, - otf_data: Arc>, - font_instance: &FontInstance, - glyph_key: &GlyphKey) - -> Result { - let mut font_context = - try!(core_graphics::FontContext::new().map_err(|_| FontError::FontLoadingFailed)); - try!(font_context.add_font_from_memory(font_key, otf_data, font_index) - .map_err(|_| FontError::FontLoadingFailed)); - font_context.rasterize_glyph_with_native_rasterizer(&font_instance, &glyph_key, true) - .map_err(|_| FontError::RasterizationFailed) -} - -#[cfg(not(target_os = "macos"))] -fn rasterize_glyph_with_core_graphics(_: &FontKey, - _: u32, - _: Arc>, - _: &FontInstance, - _: &GlyphKey) - -> Result { - Err(FontError::ReferenceRasterizerUnavailable) -} - #[post("/partition-font", format = "application/json", data = "")] fn partition_font(request: Json) -> Result { // Check the cache. @@ -456,23 +418,10 @@ fn partition_font(request: Json) -> Result font_context, - Err(_) => { - println!("Failed to create a font context!"); - return Err(FontError::FontLoadingFailed) - } - }; - - let font_key = FontKey::new(); let otf_data = try!(otf_data_from_request(&request.face)); - if font_context.add_font_from_memory(&font_key, otf_data, request.font_index).is_err() { - return Err(FontError::FontLoadingFailed) - } - - let font_instance = FontInstance { - font_key: font_key, - size: Au::from_f64_px(request.point_size), + let font = match Font::from_bytes(otf_data, request.font_index) { + Ok(font) => font, + Err(_) => return Err(FontError::FontLoadingFailed), }; // Read glyph info. @@ -480,12 +429,12 @@ fn partition_font(request: Json) -> Result { - paths.push(Transform2DPathIter::new(glyph_outline.iter(), + // FIXME(pcwalton): Should we add first-class support for transforms to `font-kit`? + let mut path_builder = lyon_path::default::Path::builder(); + match font.outline(glyph.id, HintingOptions::None, &mut path_builder) { + Ok(()) => { + paths.push(Transform2DPathIter::new(path_builder.build().into_iter(), &glyph.transform).collect()) } Err(_) => paths.push(vec![]), @@ -601,39 +550,60 @@ fn partition_svg_paths(request: Json) #[post("/render-reference/text", format = "application/json", data = "")] fn render_reference_text(request: Json) -> Result { - let font_key = FontKey::new(); let otf_data = try!(otf_data_from_request(&request.face)); - let font_instance = FontInstance { - font_key: font_key, - size: Au::from_f64_px(request.point_size), - }; - let glyph_key = GlyphKey::new(request.glyph, SubpixelOffset(0)); // Rasterize the glyph using the right rasterizer. - let glyph_image = match request.renderer { + let mut canvas; + match request.renderer { ReferenceTextRenderer::FreeType => { - let mut font_context = - try!(FontContext::new().map_err(|_| FontError::FontLoadingFailed)); - try!(font_context.add_font_from_memory(&font_key, otf_data, request.font_index) - .map_err(|_| FontError::FontLoadingFailed)); - try!(font_context.rasterize_glyph_with_native_rasterizer(&font_instance, - &glyph_key, - true) - .map_err(|_| FontError::RasterizationFailed)) + let loader = match Font::from_bytes(otf_data, request.font_index) { + Ok(loader) => loader, + Err(_) => return Err(FontError::FontLoadingFailed), + }; + let glyph_rect = try!(loader.raster_bounds(request.glyph, + request.point_size as f32, + &Point2D::zero(), + HintingOptions::None, + RasterizationOptions::SubpixelAa) + .map_err(|_| FontError::RasterizationFailed)); + let glyph_dimensions = glyph_rect.size.to_u32(); + canvas = Canvas::new(&glyph_dimensions, FontKitFormat::Rgba32); + let origin = Point2D::new(-glyph_rect.origin.x, -glyph_rect.origin.y).to_f32(); + try!(loader.rasterize_glyph(&mut canvas, + request.glyph, + request.point_size as f32, + &origin, + HintingOptions::None, + RasterizationOptions::SubpixelAa) + .map_err(|_| FontError::RasterizationFailed)); } ReferenceTextRenderer::CoreGraphics => { - try!(rasterize_glyph_with_core_graphics(&font_key, - request.font_index, - otf_data, - &font_instance, - &glyph_key)) + let loader = match loaders::core_text::Font::from_bytes(otf_data, request.font_index) { + Ok(loader) => loader, + Err(_) => return Err(FontError::FontLoadingFailed), + }; + let glyph_rect = try!(loader.raster_bounds(request.glyph, + request.point_size as f32, + &Point2D::zero(), + HintingOptions::None, + RasterizationOptions::SubpixelAa) + .map_err(|_| FontError::RasterizationFailed)); + let glyph_dimensions = glyph_rect.size.to_u32(); + canvas = Canvas::new(&glyph_dimensions, FontKitFormat::Rgba32); + let origin = Point2D::new(-glyph_rect.origin.x, -glyph_rect.origin.y).to_f32(); + try!(loader.rasterize_glyph(&mut canvas, + request.glyph, + request.point_size as f32, + &origin, + HintingOptions::None, + RasterizationOptions::SubpixelAa) + .map_err(|_| FontError::RasterizationFailed)); } }; - let dimensions = &glyph_image.dimensions; - let image_buffer = ImageBuffer::from_raw(dimensions.size.width, - dimensions.size.height, - glyph_image.pixels).unwrap(); + let image_buffer = ImageBuffer::from_raw(canvas.size.width, + canvas.size.height, + canvas.pixels).unwrap(); let reference_image = ReferenceImage { image: ImageRgba8(image_buffer), }; diff --git a/font-renderer/Cargo.toml b/font-renderer/Cargo.toml deleted file mode 100644 index ef03ae1e..00000000 --- a/font-renderer/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "pathfinder_font_renderer" -version = "0.5.0" -authors = ["Patrick Walton "] - -[features] -default = [] -freetype-backend = ["freetype"] - -[dependencies] -app_units = "0.7" -libc = "0.2" -log = "0.3" -lyon_path = "0.12" -serde = "1.0" -serde_derive = "1.0" - -[dependencies.euclid] -version = "0.19" -features = ["serde"] - -[dependencies.freetype] -version = "0.4" -optional = true - -[target.'cfg(not(any(target_os = "macos", target_os = "ios")))'.dependencies] -freetype = { version = "0.4" } - -[target.'cfg(target_os = "macos")'.dependencies] -core-graphics = "0.16" -core-text = "11" - -[target.'cfg(target_os = "windows")'.dependencies] -dwrite-sys = "0.2" -kernel32-sys = "0.2" -uuid-sys = "0.1" -winapi = "0.2" - -[dev-dependencies] -env_logger = "0.5" diff --git a/font-renderer/src/core_graphics.rs b/font-renderer/src/core_graphics.rs deleted file mode 100644 index 31fbfc49..00000000 --- a/font-renderer/src/core_graphics.rs +++ /dev/null @@ -1,346 +0,0 @@ -// pathfinder/font-renderer/src/core_graphics.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Font loading using macOS Core Graphics/Quartz. - -use core_graphics_sys::base::{CGFloat, kCGImageAlphaNoneSkipFirst, kCGBitmapByteOrder32Little}; -use core_graphics_sys::color_space::CGColorSpace; -use core_graphics_sys::context::{CGContext, CGTextDrawingMode}; -use core_graphics_sys::data_provider::CGDataProvider; -use core_graphics_sys::font::{CGFont, CGGlyph}; -use core_graphics_sys::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGPoint, CGRect}; -use core_graphics_sys::geometry::{CGSize, CG_ZERO_POINT}; -use core_graphics_sys::path::CGPathElementType; -use core_text::font::CTFont; -use core_text; -use euclid::{Point2D, Rect, Size2D, Vector2D}; -use lyon_path::PathEvent; -use std::collections::BTreeMap; -use std::collections::btree_map::Entry; -use std::hash::Hash; -use std::iter::Cloned; -use std::slice::Iter; -use std::sync::Arc; -use {FontInstance, GlyphDimensions, GlyphImage, GlyphKey}; - -const CG_ZERO_RECT: CGRect = CGRect { - origin: CG_ZERO_POINT, - size: CGSize { - width: 0.0, - height: 0.0, - }, -}; - -// A conservative overestimate of the amount of font dilation that Core Graphics performs, as a -// fraction of ppem. -// -// The actual amount as of High Sierra is 0.0121 in the X direction and 0.015125 in the Y -// direction. -const FONT_DILATION_AMOUNT: f32 = 0.02; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -#[derive(Clone)] -pub struct NativeFontHandle(pub CGFont); - -/// An object that loads and renders fonts using macOS Core Graphics/Quartz. -pub struct FontContext where FK: Clone + Hash + Eq + Ord { - core_graphics_fonts: BTreeMap, - core_text_fonts: BTreeMap, CTFont>, -} - -// Core Text is thread-safe. -unsafe impl Send for FontContext where FK: Clone + Hash + Eq + Ord + Send {} - -impl FontContext where FK: Clone + Hash + Eq + Ord { - /// Creates a new font context instance. - pub fn new() -> Result { - Ok(FontContext { - core_graphics_fonts: BTreeMap::new(), - core_text_fonts: BTreeMap::new(), - }) - } - - /// Loads an OpenType font from a Quartz `CGFont` handle. - pub fn add_native_font(&mut self, font_key: &FK, handle: H) -> Result<(), ()> - where H: Into { - match self.core_graphics_fonts.entry((*font_key).clone()) { - Entry::Occupied(_) => Ok(()), - Entry::Vacant(entry) => { - entry.insert(handle.into()); - Ok(()) - } - } - } - - /// Loads an OpenType font from memory. - /// - /// `font_key` is a handle that is used to refer to the font later. If this context has already - /// loaded a font with the same font key, nothing is done, and `Ok` is returned. - /// - /// `bytes` is the raw OpenType data (i.e. the contents of the `.otf` or `.ttf` file on disk). - /// - /// `font_index` is the index of the font within the collection, if `bytes` refers to a - /// collection (`.ttc`). - pub fn add_font_from_memory(&mut self, font_key: &FK, bytes: Arc>, _: u32) - -> Result<(), ()> { - match self.core_graphics_fonts.entry((*font_key).clone()) { - Entry::Occupied(_) => Ok(()), - Entry::Vacant(entry) => { - let data_provider = CGDataProvider::from_buffer(bytes); - let core_graphics_font = try!(CGFont::from_data_provider(data_provider)); - entry.insert(core_graphics_font); - Ok(()) - } - } - } - - /// Unloads the font with the given font key from memory. - /// - /// If the font isn't loaded, does nothing. - pub fn delete_font(&mut self, font_key: &FK) { - self.core_graphics_fonts.remove(font_key); - - let core_text_font_keys: Vec<_> = self.core_text_fonts - .keys() - .filter(|key| key.font_key == *font_key) - .cloned() - .collect(); - for core_text_font_key in &core_text_font_keys { - self.core_text_fonts.remove(core_text_font_key); - } - } - - fn ensure_core_text_font(&mut self, font_instance: &FontInstance) -> Result { - match self.core_text_fonts.entry((*font_instance).clone()) { - Entry::Occupied(entry) => Ok((*entry.get()).clone()), - Entry::Vacant(entry) => { - let core_graphics_font = match self.core_graphics_fonts - .get(&font_instance.font_key) { - None => return Err(()), - Some(core_graphics_font) => core_graphics_font, - }; - - let core_text_font = try!(font_instance.instantiate(&core_graphics_font)); - entry.insert(core_text_font.clone()); - Ok(core_text_font) - } - } - } - - /// Returns the dimensions of the given glyph in the given font. - /// - /// If `exact` is true, then the raw outline extents as specified by the font designer are - /// returned. These may differ from the extents when rendered on screen, because some font - /// libraries (including Pathfinder) apply modifications to the outlines: for example, to - /// dilate them for easier reading. To retrieve extents that account for these modifications, - /// set `exact` to false. - pub fn glyph_dimensions(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - exact: bool) - -> Result { - let core_graphics_font = match self.core_graphics_fonts.get(&font_instance.font_key) { - None => return Err(()), - Some(core_graphics_font) => core_graphics_font, - }; - - let glyph = glyph_key.glyph_index as CGGlyph; - let mut bounding_boxes = [CG_ZERO_RECT]; - let mut advances = [0]; - if !core_graphics_font.get_glyph_b_boxes(&[glyph], &mut bounding_boxes) || - !core_graphics_font.get_glyph_advances(&[glyph], &mut advances) { - return Err(()) - } - - // FIXME(pcwalton): Vertical subpixel offsets. - let subpixel_offset = Point2D::new(glyph_key.subpixel_offset.into(), 0.0); - - // Round out to pixel boundaries. - let units_per_em = core_graphics_font.get_units_per_em(); - let scale = (font_instance.size.to_f64_px() as CGFloat) / (units_per_em as CGFloat); - let bounding_box = - Rect::new(Point2D::new(bounding_boxes[0].origin.x, - bounding_boxes[0].origin.y), - Size2D::new(bounding_boxes[0].size.width, - bounding_boxes[0].size.height)).scale(scale, scale); - let mut lower_left = Point2D::new(bounding_box.origin.x.floor() as i32, - bounding_box.origin.y.floor() as i32); - let mut upper_right = Point2D::new((bounding_box.origin.x + bounding_box.size.width + - subpixel_offset.x).ceil() as i32, - (bounding_box.origin.y + bounding_box.size.height + - subpixel_offset.y).ceil() as i32); - - // Core Graphics performs font dilation to expand the outlines a bit. As of High Sierra, - // the values seem to be 1.21% in the X direction and 1.5125% in the Y direction. Make sure - // that there's enough room to account for this. We round the values up to 2% to account - // for the possibility that Apple might tweak this later. - if !exact { - let font_dilation_radius = (font_instance.size.to_f32_px() * - FONT_DILATION_AMOUNT * 0.5).ceil() as i32; - lower_left += Vector2D::new(-font_dilation_radius, -font_dilation_radius); - upper_right += Vector2D::new(font_dilation_radius, font_dilation_radius); - } - - Ok(GlyphDimensions { - origin: lower_left, - size: Size2D::new((upper_right.x - lower_left.x) as u32, - (upper_right.y - lower_left.y) as u32), - advance: advances[0] as f32, - }) - } - - /// Returns a list of path commands that represent the given glyph in the given font. - pub fn glyph_outline(&mut self, font_instance: &FontInstance, glyph_key: &GlyphKey) - -> Result { - let core_text_font = try!(self.ensure_core_text_font(font_instance)); - let path = try!(core_text_font.create_path_for_glyph(glyph_key.glyph_index as CGGlyph, - &CG_AFFINE_TRANSFORM_IDENTITY)); - - let mut builder = vec![]; - path.apply(&|element| { - let points = element.points(); - match element.element_type { - CGPathElementType::MoveToPoint => { - builder.push(PathEvent::MoveTo(convert_point(&points[0]))) - } - CGPathElementType::AddLineToPoint => { - builder.push(PathEvent::LineTo(convert_point(&points[0]))) - } - CGPathElementType::AddQuadCurveToPoint => { - builder.push(PathEvent::QuadraticTo(convert_point(&points[0]), - convert_point(&points[1]))) - } - CGPathElementType::AddCurveToPoint => { - builder.push(PathEvent::CubicTo(convert_point(&points[0]), - convert_point(&points[1]), - convert_point(&points[2]))) - } - CGPathElementType::CloseSubpath => builder.push(PathEvent::Close), - } - }); - - return Ok(GlyphOutline { - events: builder, - }); - - fn convert_point(core_graphics_point: &CGPoint) -> Point2D { - Point2D::new(core_graphics_point.x as f32, core_graphics_point.y as f32) - } - } - - /// Uses the native Core Graphics library to rasterize a glyph on CPU. - /// - /// Pathfinder uses this for reference testing. - /// - /// If `exact` is true, then the glyph image will have precisely the size specified by the font - /// designer. Because some font libraries, such as Core Graphics, perform modifications to the - /// glyph outlines, to ensure the entire outline fits it is best to pass false for `exact`. - pub fn rasterize_glyph_with_native_rasterizer(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - exact: bool) - -> Result { - let core_graphics_font = match self.core_graphics_fonts.get(&font_instance.font_key) { - None => return Err(()), - Some(core_graphics_font) => core_graphics_font, - }; - - let dimensions = try!(self.glyph_dimensions(font_instance, glyph_key, exact)); - - // TODO(pcwalton): Add support for non-subpixel render modes. - let bitmap_context_flags = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst; - - let mut core_graphics_context = - CGContext::create_bitmap_context(None, - dimensions.size.width as usize, - dimensions.size.height as usize, - 8, - dimensions.size.width as usize * 4, - &CGColorSpace::create_device_rgb(), - bitmap_context_flags); - - // TODO(pcwalton): Add support for non-subpixel render modes. - let (antialias, smooth, bg_color) = (true, true, 1.0); - - // Use subpixel positioning. But don't let Core Graphics quantize, because we do that - // ourselves. - core_graphics_context.set_allows_font_subpixel_positioning(true); - core_graphics_context.set_should_subpixel_position_fonts(true); - core_graphics_context.set_allows_font_subpixel_quantization(false); - core_graphics_context.set_should_subpixel_quantize_fonts(false); - - // Set up antialiasing flags. - core_graphics_context.set_allows_font_smoothing(smooth); - core_graphics_context.set_should_smooth_fonts(smooth); - core_graphics_context.set_allows_antialiasing(antialias); - core_graphics_context.set_should_antialias(antialias); - - // Set up the background. - core_graphics_context.set_rgb_fill_color(bg_color, bg_color, bg_color, bg_color); - core_graphics_context.fill_rect(CGRect { - origin: CG_ZERO_POINT, - size: CGSize { - width: dimensions.size.width as CGFloat, - height: dimensions.size.height as CGFloat, - }, - }); - - // Set up the text color. - core_graphics_context.set_rgb_fill_color(0.0, 0.0, 0.0, 1.0); - core_graphics_context.set_text_drawing_mode(CGTextDrawingMode::CGTextFill); - - // Set up the font. - core_graphics_context.set_font(core_graphics_font); - core_graphics_context.set_font_size(font_instance.size.to_f64_px() as CGFloat); - - // Compute the rasterization origin. - // TODO(pcwalton): Vertical subpixel positioning. - let subpixel_offset = Point2D::new(glyph_key.subpixel_offset.into(), 0.0); - let origin = CGPoint { - x: -dimensions.origin.x as CGFloat + subpixel_offset.x, - y: -dimensions.origin.y as CGFloat, - }; - - // Draw the glyph, and extract the pixels. - core_graphics_context.show_glyphs_at_positions(&[glyph_key.glyph_index as CGGlyph], - &[origin]); - let mut pixels = core_graphics_context.data().to_vec(); - - // Swap BGRA to RGBA. - for pixel in pixels.chunks_mut(4) { - let (b, r) = (pixel[0], pixel[2]); - pixel[0] = r; - pixel[2] = b; - } - - // Return the image. - Ok(GlyphImage { - dimensions: dimensions, - pixels: pixels, - }) - } -} - -impl FontInstance where FK: Clone { - fn instantiate(&self, core_graphics_font: &CGFont) -> Result { - Ok(core_text::font::new_from_CGFont(core_graphics_font, self.size.to_f64_px())) - } -} - -pub struct GlyphOutline { - events: Vec, -} - -impl GlyphOutline { - #[inline] - pub fn iter(&self) -> Cloned> { - self.events.iter().cloned() - } -} diff --git a/font-renderer/src/directwrite/com.rs b/font-renderer/src/directwrite/com.rs deleted file mode 100644 index 0421c761..00000000 --- a/font-renderer/src/directwrite/com.rs +++ /dev/null @@ -1,124 +0,0 @@ -// pathfinder/font-renderer/src/directwrite/com.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Utility types for Microsoft COM. - -use std::mem; -use std::ops::Deref; -use std::os::raw::c_void; -use std::ptr; -use std::sync::atomic::{AtomicUsize, Ordering}; -use uuid; -use winapi::{E_NOINTERFACE, E_POINTER, GUID, HRESULT, IUnknown, REFIID, S_OK, ULONG}; - -pub struct PathfinderComPtr { - ptr: *mut T, -} - -impl PathfinderComPtr { - #[inline] - pub unsafe fn new(ptr: *mut T) -> PathfinderComPtr { - PathfinderComPtr { - ptr: ptr, - } - } - - #[inline] - pub fn into_raw(self) -> *mut T { - let ptr = self.ptr; - mem::forget(self); - ptr - } -} - -impl Clone for PathfinderComPtr { - #[inline] - fn clone(&self) -> PathfinderComPtr { - unsafe { - (*(self.ptr as *mut IUnknown)).AddRef(); - } - PathfinderComPtr { - ptr: self.ptr, - } - } -} - -impl Drop for PathfinderComPtr { - #[inline] - fn drop(&mut self) { - unsafe { - (*(self.ptr as *mut IUnknown)).Release(); - } - } -} - -impl Deref for PathfinderComPtr { - type Target = *mut T; - #[inline] - fn deref(&self) -> &*mut T { - &self.ptr - } -} - -pub trait PathfinderCoclass { - type InterfaceVtable: 'static; - fn interface_guid() -> &'static GUID; - fn vtable() -> &'static Self::InterfaceVtable; -} - -#[repr(C)] -pub struct PathfinderComObject where DerivedClass: PathfinderCoclass { - vtable: &'static DerivedClass::InterfaceVtable, - ref_count: AtomicUsize, -} - -impl PathfinderComObject where DerivedClass: PathfinderCoclass { - #[inline] - pub unsafe fn construct() -> PathfinderComObject { - PathfinderComObject { - vtable: DerivedClass::vtable(), - ref_count: AtomicUsize::new(1), - } - } - - pub unsafe extern "system" fn AddRef(this: *mut IUnknown) -> ULONG { - let this = this as *mut PathfinderComObject; - ((*this).ref_count.fetch_add(1, Ordering::SeqCst) + 1) as ULONG - } - - pub unsafe extern "system" fn Release(this: *mut IUnknown) -> ULONG { - let this = this as *mut PathfinderComObject; - let new_ref_count = (*this).ref_count.fetch_sub(1, Ordering::SeqCst) - 1; - if new_ref_count == 0 { - drop(Box::from_raw(this)) - } - new_ref_count as ULONG - } - - pub unsafe extern "system" fn QueryInterface(this: *mut IUnknown, - riid: REFIID, - object: *mut *mut c_void) - -> HRESULT { - if object.is_null() { - return E_POINTER - } - if guids_are_equal(&*riid, &uuid::IID_IUnknown) || - guids_are_equal(&*riid, DerivedClass::interface_guid()) { - *object = this as *mut c_void; - return S_OK - } - *object = ptr::null_mut(); - E_NOINTERFACE - } -} - -fn guids_are_equal(a: &GUID, b: &GUID) -> bool { - a.Data1 == b.Data1 && a.Data2 == b.Data2 && a.Data3 == b.Data3 && a.Data4 == b.Data4 -} \ No newline at end of file diff --git a/font-renderer/src/directwrite/mod.rs b/font-renderer/src/directwrite/mod.rs deleted file mode 100644 index d14616c9..00000000 --- a/font-renderer/src/directwrite/mod.rs +++ /dev/null @@ -1,669 +0,0 @@ -// pathfinder/font-renderer/src/directwrite/mod.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Font loading using a hybrid of Windows DirectWrite and FreeType for hinting. - -#![allow(non_snake_case, non_upper_case_globals)] - -use dwrite; -use euclid::{Point2D, Size2D}; -use kernel32; -use lyon_path::PathEvent; -use std::collections::BTreeMap; -use std::hash::Hash; -use std::iter::Cloned; -use std::mem; -use std::os::raw::c_void; -use std::ptr; -use std::collections::btree_map::Entry; -use std::slice::{self, Iter}; -use std::sync::Arc; -use uuid::IID_ID2D1SimplifiedGeometrySink; -use winapi::winerror::{self, S_OK}; -use winapi::{self, BOOL, D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END}; -use winapi::{D2D1_FIGURE_END_CLOSED, D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D1_POINT_2F}; -use winapi::{DWRITE_FONT_METRICS, DWRITE_GLYPH_METRICS, E_BOUNDS, E_INVALIDARG, FALSE, FILETIME}; -use winapi::{FLOAT, GUID, HRESULT, ID2D1SimplifiedGeometrySinkVtbl, IDWriteFactory}; -use winapi::{IDWriteFontCollectionLoader, IDWriteFontCollectionLoaderVtbl, IDWriteFontFace}; -use winapi::{IDWriteFontFile, IDWriteFontFileEnumerator, IDWriteFontFileEnumeratorVtbl}; -use winapi::{IDWriteFontFileLoader, IDWriteFontFileLoaderVtbl, IDWriteFontFileStream}; -use winapi::{IDWriteFontFileStreamVtbl, IDWriteGeometrySink, IUnknown, IUnknownVtbl, TRUE, UINT16}; -use winapi::{UINT32, UINT64, UINT}; - -use self::com::{PathfinderCoclass, PathfinderComObject}; -pub use self::com::{PathfinderComPtr}; -use {FontInstance, GlyphDimensions, GlyphImage, GlyphKey}; - -mod com; - -DEFINE_GUID! { - IID_IDWriteFactory, 0xb859ee5a, 0xd838, 0x4b5b, 0xa2, 0xe8, 0x1a, 0xdc, 0x7d, 0x93, 0xdb, 0x48 -} -DEFINE_GUID! { - IID_IDWriteFontCollectionLoader, - 0xcca920e4, 0x52f0, 0x492b, 0xbf, 0xa8, 0x29, 0xc7, 0x2e, 0xe0, 0xa4, 0x68 -} -DEFINE_GUID! { - IID_IDWriteFontFileEnumerator, - 0x72755049, 0x5ff7, 0x435d, 0x83, 0x48, 0x4b, 0xe9, 0x7c, 0xfa, 0x6c, 0x7c -} -DEFINE_GUID! { - IID_IDWriteFontFileLoader, - 0x727cad4e, 0xd6af, 0x4c9e, 0x8a, 0x08, 0xd6, 0x95, 0xb1, 0x1c, 0xaa, 0x49 -} -DEFINE_GUID! { - IID_IDWriteFontFileStream, - 0x6d4865fe, 0x0ab8, 0x4d91, 0x8f, 0x62, 0x5d, 0xd6, 0xbe, 0x34, 0xa3, 0xe0 -} - -static PATHFINDER_FONT_COLLECTION_KEY: [u8; 17] = *b"MEMORY_COLLECTION"; -static PATHFINDER_FONT_FILE_KEY: [u8; 11] = *b"MEMORY_FILE"; - -/// An object that loads and renders fonts using Windows DirectWrite. -pub struct FontContext where FK: Clone + Hash + Eq + Ord { - dwrite_factory: PathfinderComPtr, - dwrite_font_faces: BTreeMap>, -} - -impl FontContext where FK: Clone + Hash + Eq + Ord { - /// Creates a new font context instance. - pub fn new() -> Result, ()> { - unsafe { - let mut factory: *mut IDWriteFactory = ptr::null_mut(); - if !winerror::SUCCEEDED(dwrite::DWriteCreateFactory(winapi::DWRITE_FACTORY_TYPE_SHARED, - &IID_IDWriteFactory, - &mut factory as *mut *mut _ as - *mut *mut IUnknown)) { - return Err(()) - } - let factory = PathfinderComPtr::new(factory); - - Ok(FontContext { - dwrite_factory: factory, - dwrite_font_faces: BTreeMap::new(), - }) - } - } - - /// Loads an OpenType font from memory. - /// - /// `font_key` is a handle that is used to refer to the font later. If this context has already - /// loaded a font with the same font key, nothing is done, and `Ok` is returned. - /// - /// `bytes` is the raw OpenType data (i.e. the contents of the `.otf` or `.ttf` file on disk). - /// - /// `font_index` is the index of the font within the collection, if `bytes` refers to a - /// collection (`.ttc`). - pub fn add_font_from_memory(&mut self, font_key: &FK, bytes: Arc>, _: u32) - -> Result<(), ()> { - unsafe { - let font_file_loader = PathfinderFontFileLoader::new(bytes.clone()); - - let result = (**self.dwrite_factory).RegisterFontFileLoader( - font_file_loader.clone().into_raw() as *mut IDWriteFontFileLoader); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - - let mut font_file = ptr::null_mut(); - let result = (**self.dwrite_factory).CreateCustomFontFileReference( - PATHFINDER_FONT_FILE_KEY.as_ptr() as *const c_void, - PATHFINDER_FONT_FILE_KEY.len() as UINT, - font_file_loader.clone().into_raw() as *mut IDWriteFontFileLoader, - &mut font_file); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - let font_file = PathfinderComPtr::new(font_file); - - let font_collection_loader = PathfinderFontCollectionLoader::new(font_file); - - let result = (**self.dwrite_factory).RegisterFontCollectionLoader( - font_collection_loader.clone().into_raw() as *mut IDWriteFontCollectionLoader); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - - let mut font_collection = ptr::null_mut(); - let result = (**self.dwrite_factory).CreateCustomFontCollection( - font_collection_loader.clone().into_raw() as *mut IDWriteFontCollectionLoader, - PATHFINDER_FONT_COLLECTION_KEY.as_ptr() as *const c_void, - PATHFINDER_FONT_COLLECTION_KEY.len() as UINT32, - &mut font_collection); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - let font_collection = PathfinderComPtr::new(font_collection); - - let mut font_family = ptr::null_mut(); - let result = (**font_collection).GetFontFamily(0, &mut font_family); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - let font_family = PathfinderComPtr::new(font_family); - - let mut font = ptr::null_mut(); - let result = (**font_family).GetFont(0, &mut font); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - let font = PathfinderComPtr::new(font); - - let mut font_face = ptr::null_mut(); - let result = (**font).CreateFontFace(&mut font_face); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - let font_face = PathfinderComPtr::new(font_face); - - let result = (**self.dwrite_factory).UnregisterFontCollectionLoader( - font_collection_loader.into_raw() as *mut IDWriteFontCollectionLoader); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - - let result = (**self.dwrite_factory).UnregisterFontFileLoader( - font_file_loader.into_raw() as *mut IDWriteFontFileLoader); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - - self.dwrite_font_faces.insert((*font_key).clone(), font_face); - Ok(()) - } - } - - /// Loads an OpenType font from a COM `IDWriteFontFace` handle. - pub fn add_native_font(&mut self, font_key: &FK, handle: H) -> Result<(), ()> - where H: Into> - { - match self.dwrite_font_faces.entry((*font_key).clone()) { - Entry::Occupied(_) => Ok(()), - Entry::Vacant(entry) => { - entry.insert(handle.into()); - Ok(()) - } - } - } - - /// Unloads the font with the given font key from memory. - /// - /// If the font isn't loaded, does nothing. - #[inline] - pub fn delete_font(&mut self, font_key: &FK) { - self.dwrite_font_faces.remove(font_key); - } - - /// Returns the dimensions of the given glyph in the given font. - /// - /// If `exact` is true, then the raw outline extents as specified by the font designer are - /// returned. These may differ from the extents when rendered on screen, because some font - /// libraries (including Pathfinder) apply modifications to the outlines: for example, to - /// dilate them for easier reading. To retrieve extents that account for these modifications, - /// set `exact` to false. - pub fn glyph_dimensions(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - _exact: bool) - -> Result { - - let mut metrics: DWRITE_GLYPH_METRICS = unsafe { mem::zeroed() }; - - unsafe { - let font_face = match self.dwrite_font_faces.get(&font_instance.font_key) { - None => return Err(()), - Some(font_face) => (*font_face).clone(), - }; - - let glyph_index = glyph_key.glyph_index as UINT16; - - let result = (**font_face).GetDesignGlyphMetrics(&glyph_index, 1, &mut metrics, FALSE); - if !winerror::SUCCEEDED(result) { - return Err(()); - } - } - - let character_width = metrics.advanceWidth as i32 - metrics.rightSideBearing - metrics.leftSideBearing; - let character_height = metrics.advanceHeight as i32 - metrics.topSideBearing - metrics.bottomSideBearing; - - Ok(GlyphDimensions { - advance: metrics.advanceWidth as f32, - origin: Point2D::new(metrics.leftSideBearing, metrics.bottomSideBearing), - size: Size2D::new(character_width as u32, - character_height as u32), - }) - } - - /// Returns a list of path commands that represent the given glyph in the given font. - pub fn glyph_outline(&mut self, font_instance: &FontInstance, glyph_key: &GlyphKey) - -> Result { - unsafe { - let font_face = match self.dwrite_font_faces.get(&font_instance.font_key) { - None => return Err(()), - Some(font_face) => (*font_face).clone(), - }; - - let mut metrics: DWRITE_FONT_METRICS = mem::zeroed(); - (**font_face).GetMetrics(&mut metrics); - - let geometry_sink = PathfinderGeometrySink::new(); - let glyph_index = glyph_key.glyph_index as UINT16; - - let result = - (**font_face).GetGlyphRunOutline(metrics.designUnitsPerEm as FLOAT, - &glyph_index, - ptr::null(), - ptr::null(), - 1, - FALSE, - FALSE, - *geometry_sink as *mut IDWriteGeometrySink); - if !winerror::SUCCEEDED(result) { - return Err(()) - } - - Ok(GlyphOutline { - events: mem::replace(&mut (**geometry_sink).commands, vec![]), - }) - } - } - - pub fn rasterize_glyph_with_native_rasterizer(&self, - _font_instance: &FontInstance, - _glyph_key: &GlyphKey, - _exact: bool) - -> Result { - // TODO(pcwalton) - Err(()) - } -} - -#[repr(C)] -struct PathfinderFontCollectionLoader { - object: PathfinderComObject, - font_file: PathfinderComPtr, -} - -static PATHFINDER_FONT_COLLECTION_LOADER_VTABLE: - IDWriteFontCollectionLoaderVtbl = IDWriteFontCollectionLoaderVtbl { - parent: IUnknownVtbl { - AddRef: PathfinderComObject::::AddRef, - Release: PathfinderComObject::::Release, - QueryInterface: PathfinderComObject::::QueryInterface, - }, - CreateEnumeratorFromKey: PathfinderFontCollectionLoader::CreateEnumeratorFromKey, -}; - -impl PathfinderCoclass for PathfinderFontCollectionLoader { - type InterfaceVtable = IDWriteFontCollectionLoaderVtbl; - fn interface_guid() -> &'static GUID { &IID_IDWriteFontCollectionLoader } - fn vtable() -> &'static IDWriteFontCollectionLoaderVtbl { - &PATHFINDER_FONT_COLLECTION_LOADER_VTABLE - } -} - -impl PathfinderFontCollectionLoader { - #[inline] - fn new(font_file: PathfinderComPtr) - -> PathfinderComPtr { - unsafe { - PathfinderComPtr::new(Box::into_raw(Box::new(PathfinderFontCollectionLoader { - object: PathfinderComObject::construct(), - font_file: font_file, - }))) - } - } - - unsafe extern "system" fn CreateEnumeratorFromKey( - this: *mut IDWriteFontCollectionLoader, - factory: *mut IDWriteFactory, - _: *const c_void, - _: UINT32, - font_file_enumerator: *mut *mut IDWriteFontFileEnumerator) - -> HRESULT { - let this = this as *mut PathfinderFontCollectionLoader; - - let factory = PathfinderComPtr::new(factory); - let font_file = (*this).font_file.clone(); - let new_font_file_enumerator = PathfinderFontFileEnumerator::new(factory, font_file); - - *font_file_enumerator = new_font_file_enumerator.into_raw() as - *mut IDWriteFontFileEnumerator; - S_OK - } -} - -#[repr(C)] -struct PathfinderFontFileEnumerator { - object: PathfinderComObject, - factory: PathfinderComPtr, - font_file: PathfinderComPtr, - state: PathfinderFontFileEnumeratorState, -} - -static PATHFINDER_FONT_FILE_ENUMERATOR_VTABLE: - IDWriteFontFileEnumeratorVtbl = IDWriteFontFileEnumeratorVtbl { - parent: IUnknownVtbl { - AddRef: PathfinderComObject::::AddRef, - Release: PathfinderComObject::::Release, - QueryInterface: PathfinderComObject::::QueryInterface, - }, - GetCurrentFontFile: PathfinderFontFileEnumerator::GetCurrentFontFile, - MoveNext: PathfinderFontFileEnumerator::MoveNext, -}; - -#[derive(Clone, Copy, PartialEq, Debug)] -enum PathfinderFontFileEnumeratorState { - Start, - AtFontFile, - End, -} - -impl PathfinderCoclass for PathfinderFontFileEnumerator { - type InterfaceVtable = IDWriteFontFileEnumeratorVtbl; - fn interface_guid() -> &'static GUID { &IID_IDWriteFontFileEnumerator } - fn vtable() -> &'static IDWriteFontFileEnumeratorVtbl { - &PATHFINDER_FONT_FILE_ENUMERATOR_VTABLE - } -} - -impl PathfinderFontFileEnumerator { - #[inline] - fn new(factory: PathfinderComPtr, font_file: PathfinderComPtr) - -> PathfinderComPtr { - unsafe { - PathfinderComPtr::new(Box::into_raw(Box::new(PathfinderFontFileEnumerator { - object: PathfinderComObject::construct(), - factory: factory, - font_file: font_file, - state: PathfinderFontFileEnumeratorState::Start, - }))) - } - } - - unsafe extern "system" fn GetCurrentFontFile(this: *mut IDWriteFontFileEnumerator, - font_file: *mut *mut IDWriteFontFile) - -> HRESULT { - let this = this as *mut PathfinderFontFileEnumerator; - if (*this).state != PathfinderFontFileEnumeratorState::AtFontFile { - *font_file = ptr::null_mut(); - return E_BOUNDS - } - - *font_file = (*this).font_file.clone().into_raw(); - S_OK - } - - unsafe extern "system" fn MoveNext(this: *mut IDWriteFontFileEnumerator, - has_current_file: *mut BOOL) - -> HRESULT { - let this = this as *mut PathfinderFontFileEnumerator; - match (*this).state { - PathfinderFontFileEnumeratorState::Start => { - (*this).state = PathfinderFontFileEnumeratorState::AtFontFile; - *has_current_file = TRUE; - } - PathfinderFontFileEnumeratorState::AtFontFile => { - (*this).state = PathfinderFontFileEnumeratorState::End; - *has_current_file = FALSE; - } - PathfinderFontFileEnumeratorState::End => *has_current_file = FALSE, - } - S_OK - } -} - -#[repr(C)] -struct PathfinderFontFileLoader { - object: PathfinderComObject, - buffer: Arc>, -} - -static PATHFINDER_FONT_FILE_LOADER_VTABLE: IDWriteFontFileLoaderVtbl = IDWriteFontFileLoaderVtbl { - parent: IUnknownVtbl { - AddRef: PathfinderComObject::::AddRef, - Release: PathfinderComObject::::Release, - QueryInterface: PathfinderComObject::::QueryInterface, - }, - CreateStreamFromKey: PathfinderFontFileLoader::CreateStreamFromKey, -}; - -impl PathfinderCoclass for PathfinderFontFileLoader { - type InterfaceVtable = IDWriteFontFileLoaderVtbl; - fn interface_guid() -> &'static GUID { &IID_IDWriteFontFileLoader } - fn vtable() -> &'static IDWriteFontFileLoaderVtbl { &PATHFINDER_FONT_FILE_LOADER_VTABLE } -} - -impl PathfinderFontFileLoader { - #[inline] - fn new(buffer: Arc>) -> PathfinderComPtr { - unsafe { - PathfinderComPtr::new(Box::into_raw(Box::new(PathfinderFontFileLoader { - object: PathfinderComObject::construct(), - buffer: buffer, - }))) - } - } - - unsafe extern "system" fn CreateStreamFromKey( - this: *mut IDWriteFontFileLoader, - font_file_reference_key: *const c_void, - font_file_reference_key_size: UINT32, - font_file_stream: *mut *mut IDWriteFontFileStream) - -> HRESULT { - let this = this as *mut PathfinderFontFileLoader; - let font_file_reference = slice::from_raw_parts(font_file_reference_key as *const u8, - font_file_reference_key_size as usize); - if font_file_reference != PATHFINDER_FONT_FILE_KEY { - *font_file_stream = ptr::null_mut(); - return E_INVALIDARG - } - - *font_file_stream = PathfinderFontFileStream::new((*this).buffer.clone()).into_raw() as - *mut IDWriteFontFileStream; - S_OK - } -} - -#[repr(C)] -struct PathfinderFontFileStream { - object: PathfinderComObject, - buffer: Arc>, - creation_time: UINT64, -} - -static PATHFINDER_FONT_FILE_STREAM_VTABLE: IDWriteFontFileStreamVtbl = IDWriteFontFileStreamVtbl { - parent: IUnknownVtbl { - AddRef: PathfinderComObject::::AddRef, - Release: PathfinderComObject::::Release, - QueryInterface: PathfinderComObject::::QueryInterface, - }, - GetFileSize: PathfinderFontFileStream::GetFileSize, - GetLastWriteTime: PathfinderFontFileStream::GetLastWriteTime, - ReadFileFragment: PathfinderFontFileStream::ReadFileFragment, - ReleaseFileFragment: PathfinderFontFileStream::ReleaseFileFragment, -}; - -impl PathfinderCoclass for PathfinderFontFileStream { - type InterfaceVtable = IDWriteFontFileStreamVtbl; - fn interface_guid() -> &'static GUID { &IID_IDWriteFontFileStream } - fn vtable() -> &'static IDWriteFontFileStreamVtbl { &PATHFINDER_FONT_FILE_STREAM_VTABLE } -} - -impl PathfinderFontFileStream { - #[inline] - fn new(buffer: Arc>) -> PathfinderComPtr { - unsafe { - let mut now = FILETIME { - dwLowDateTime: 0, - dwHighDateTime: 0, - }; - kernel32::GetSystemTimeAsFileTime(&mut now); - - PathfinderComPtr::new(Box::into_raw(Box::new(PathfinderFontFileStream { - object: PathfinderComObject::construct(), - buffer: buffer, - creation_time: ((now.dwHighDateTime as UINT64) << 32) | - (now.dwLowDateTime as UINT64), - }))) - } - } - - unsafe extern "system" fn GetFileSize(this: *mut IDWriteFontFileStream, file_size: *mut UINT64) - -> HRESULT { - let this = this as *mut PathfinderFontFileStream; - *file_size = (*this).buffer.len() as UINT64; - S_OK - } - - unsafe extern "system" fn GetLastWriteTime(this: *mut IDWriteFontFileStream, - last_write_time: *mut UINT64) - -> HRESULT { - let this = this as *mut PathfinderFontFileStream; - *last_write_time = (*this).creation_time; - S_OK - } - - unsafe extern "system" fn ReadFileFragment(this: *mut IDWriteFontFileStream, - fragment_start: *mut *const c_void, - file_offset: UINT64, - fragment_size: UINT64, - fragment_context: *mut *mut c_void) - -> HRESULT { - let this = this as *mut PathfinderFontFileStream; - let buffer_length = (*this).buffer.len() as u64; - if file_offset > buffer_length || file_offset + fragment_size > buffer_length { - return E_BOUNDS - } - - let ptr = (*(*this).buffer).as_ptr().offset(file_offset as isize) as *const c_void; - *fragment_start = ptr; - *fragment_context = ptr as *mut c_void; - (*(this as *mut IUnknown)).AddRef(); - S_OK - } - - unsafe extern "system" fn ReleaseFileFragment(this: *mut IDWriteFontFileStream, - _: *mut c_void) { - let this = this as *mut PathfinderFontFileStream; - (*(this as *mut IUnknown)).Release(); - } -} - -#[repr(C)] -struct PathfinderGeometrySink { - object: PathfinderComObject, - commands: Vec, -} - -static PATHFINDER_GEOMETRY_SINK_VTABLE: ID2D1SimplifiedGeometrySinkVtbl = - ID2D1SimplifiedGeometrySinkVtbl { - parent: IUnknownVtbl { - AddRef: PathfinderComObject::::AddRef, - Release: PathfinderComObject::::Release, - QueryInterface: PathfinderComObject::::QueryInterface, - }, - AddBeziers: PathfinderGeometrySink::AddBeziers, - AddLines: PathfinderGeometrySink::AddLines, - BeginFigure: PathfinderGeometrySink::BeginFigure, - Close: PathfinderGeometrySink::Close, - EndFigure: PathfinderGeometrySink::EndFigure, - SetFillMode: PathfinderGeometrySink::SetFillMode, - SetSegmentFlags: PathfinderGeometrySink::SetSegmentFlags, -}; - -impl PathfinderCoclass for PathfinderGeometrySink { - type InterfaceVtable = ID2D1SimplifiedGeometrySinkVtbl; - fn interface_guid() -> &'static GUID { unsafe { &IID_ID2D1SimplifiedGeometrySink } } - fn vtable() -> &'static ID2D1SimplifiedGeometrySinkVtbl { &PATHFINDER_GEOMETRY_SINK_VTABLE } -} - -impl PathfinderGeometrySink { - #[inline] - fn new() -> PathfinderComPtr { - unsafe { - PathfinderComPtr::new(Box::into_raw(Box::new(PathfinderGeometrySink { - object: PathfinderComObject::construct(), - commands: vec![], - }))) - } - } - - unsafe extern "system" fn AddBeziers(this: *mut IDWriteGeometrySink, - beziers: *const D2D1_BEZIER_SEGMENT, - beziers_count: UINT) { - let this = this as *mut PathfinderGeometrySink; - let beziers = slice::from_raw_parts(beziers, beziers_count as usize); - for bezier in beziers { - let control_point_0 = - PathfinderGeometrySink::d2d_point_2f_to_flipped_f32_point(&bezier.point1); - let control_point_1 = - PathfinderGeometrySink::d2d_point_2f_to_flipped_f32_point(&bezier.point2); - let endpoint = - PathfinderGeometrySink::d2d_point_2f_to_flipped_f32_point(&bezier.point3); - (*this).commands.push(PathEvent::CubicTo(control_point_0, control_point_1, endpoint)); - } - } - - unsafe extern "system" fn AddLines(this: *mut IDWriteGeometrySink, - points: *const D2D1_POINT_2F, - points_count: UINT) { - let this = this as *mut PathfinderGeometrySink; - let points = slice::from_raw_parts(points, points_count as usize); - for point in points { - let point = PathfinderGeometrySink::d2d_point_2f_to_flipped_f32_point(&point); - (*this).commands.push(PathEvent::LineTo(point)) - } - } - - unsafe extern "system" fn BeginFigure(this: *mut IDWriteGeometrySink, - start_point: D2D1_POINT_2F, - _: D2D1_FIGURE_BEGIN) { - let this = this as *mut PathfinderGeometrySink; - let start_point = PathfinderGeometrySink::d2d_point_2f_to_flipped_f32_point(&start_point); - (*this).commands.push(PathEvent::MoveTo(start_point)) - } - - unsafe extern "system" fn Close(_: *mut IDWriteGeometrySink) -> HRESULT { - S_OK - } - - unsafe extern "system" fn EndFigure(this: *mut IDWriteGeometrySink, - figure_end: D2D1_FIGURE_END) { - let this = this as *mut PathfinderGeometrySink; - if figure_end == D2D1_FIGURE_END_CLOSED { - (*this).commands.push(PathEvent::Close) - } - } - - unsafe extern "system" fn SetFillMode(_: *mut IDWriteGeometrySink, _: D2D1_FILL_MODE) { - // TODO(pcwalton) - } - - unsafe extern "system" fn SetSegmentFlags(_: *mut IDWriteGeometrySink, _: D2D1_PATH_SEGMENT) { - // Should be unused. - } - - #[inline] - fn d2d_point_2f_to_flipped_f32_point(point: &D2D1_POINT_2F) -> Point2D { - Point2D::new(point.x, -point.y) - } -} - -pub struct GlyphOutline { - events: Vec, -} - -impl GlyphOutline { - #[inline] - pub fn iter(&self) -> Cloned> { - self.events.iter().cloned() - } -} diff --git a/font-renderer/src/freetype/fixed.rs b/font-renderer/src/freetype/fixed.rs deleted file mode 100644 index 91610cb9..00000000 --- a/font-renderer/src/freetype/fixed.rs +++ /dev/null @@ -1,51 +0,0 @@ -// pathfinder/font-renderer/src/freetype/fixed.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Utilities for FreeType 26.6 fixed-point numbers. - -use app_units::Au; -use freetype_sys::freetype::FT_F26Dot6; - -pub trait FromFtF26Dot6 { - fn from_ft_f26dot6(value: FT_F26Dot6) -> Self; -} - -impl FromFtF26Dot6 for f32 { - fn from_ft_f26dot6(value: FT_F26Dot6) -> f32 { - (value as f32) / 64.0 - } -} - -pub trait ToFtF26Dot6 { - fn to_ft_f26dot6(self) -> FT_F26Dot6; -} - -impl ToFtF26Dot6 for f32 { - fn to_ft_f26dot6(self) -> FT_F26Dot6 { - (self * 64.0 + 0.5) as FT_F26Dot6 - } -} - -impl ToFtF26Dot6 for f64 { - fn to_ft_f26dot6(self) -> FT_F26Dot6 { - (self * 64.0 + 0.5) as FT_F26Dot6 - } -} - -impl ToFtF26Dot6 for Au { - fn to_ft_f26dot6(self) -> FT_F26Dot6 { - self.to_f64_px().to_ft_f26dot6() - } -} - -#[inline] -pub fn floor(n: FT_F26Dot6) -> FT_F26Dot6 { - n & !0x3f -} diff --git a/font-renderer/src/freetype/mod.rs b/font-renderer/src/freetype/mod.rs deleted file mode 100644 index 22519b7d..00000000 --- a/font-renderer/src/freetype/mod.rs +++ /dev/null @@ -1,387 +0,0 @@ -// pathfinder/font-renderer/src/freetype/mod.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Font loading using FreeType. - -use euclid::{Point2D, Size2D, Vector2D}; -use freetype_sys::freetype::{FT_BBox, FT_Bitmap, FT_Done_Face, FT_F26Dot6, FT_Face, FT_Glyph_Format}; -use freetype_sys::freetype::{FT_GlyphSlot, FT_Init_FreeType, FT_Int32, FT_LcdFilter}; -use freetype_sys::freetype::{FT_LOAD_NO_HINTING, FT_Library, FT_Library_SetLcdFilter}; -use freetype_sys::freetype::{FT_Load_Glyph, FT_Long, FT_New_Face, FT_New_Memory_Face}; -use freetype_sys::freetype::{FT_Outline_Get_CBox, FT_Outline_Translate, FT_Pixel_Mode}; -use freetype_sys::freetype::{FT_Render_Glyph, FT_Render_Mode, FT_Set_Char_Size, FT_UInt}; -use std::collections::BTreeMap; -use std::collections::btree_map::Entry; -use std::ffi::CString; -use std::hash::Hash; -use std::mem; -use std::os::unix::ffi::OsStrExt; -use std::path::PathBuf; -use std::ptr; -use std::slice; -use std::sync::Arc; - -use self::fixed::{FromFtF26Dot6, ToFtF26Dot6}; -use self::outline::Outline; -use {FontInstance, GlyphDimensions, GlyphImage, GlyphKey}; - -mod fixed; -mod outline; - -pub type GlyphOutline<'a> = Outline<'a>; - -// Default to no hinting. -// -// TODO(pcwalton): Make this configurable. -const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_NO_HINTING as FT_Int32; - -const DPI: u32 = 72; - -const STEM_DARKENING_AMOUNT: f32 = 0.02; - -/// An object that loads and renders fonts using the FreeType library. -pub struct FontContext where FK: Clone + Hash + Eq + Ord { - library: FT_Library, - faces: BTreeMap, -} - -unsafe impl Send for FontContext where FK: Clone + Hash + Eq + Ord + Send {} - -impl FontContext where FK: Clone + Hash + Eq + Ord { - /// Creates a new font context instance. - pub fn new() -> Result, ()> { - let mut library: FT_Library = ptr::null_mut(); - unsafe { - let result = FT_Init_FreeType(&mut library); - if result != 0 { - return Err(()) - } - } - Ok(FontContext { - library: library, - faces: BTreeMap::new(), - }) - } - - /// Loads an OpenType font from memory. - /// - /// `font_key` is a handle that is used to refer to the font later. If this context has already - /// loaded a font with the same font key, nothing is done, and `Ok` is returned. - /// - /// `bytes` is the raw OpenType data (i.e. the contents of the `.otf` or `.ttf` file on disk). - /// - /// `font_index` is the index of the font within the collection, if `bytes` refers to a - /// collection (`.ttc`). - pub fn add_font_from_memory(&mut self, font_key: &FK, bytes: Arc>, font_index: u32) - -> Result<(), ()> { - match self.faces.entry((*font_key).clone()) { - Entry::Occupied(_) => Ok(()), - Entry::Vacant(entry) => { - unsafe { - let mut face_ptr = ptr::null_mut(); - let result = FT_New_Memory_Face(self.library, - bytes.as_ptr(), - bytes.len() as FT_Long, - font_index as FT_Long, - &mut face_ptr); - let mut face = Face { - face: face_ptr, - bytes: Some(bytes), - }; - if result == 0 && !face.face.is_null() { - entry.insert(face); - Ok(()) - } else { - Err(()) - } - } - } - } - } - - pub fn add_native_font(&mut self, font_key: &FK, handle: H) -> Result<(), ()> - where H: Into { - match self.faces.entry((*font_key).clone()) { - Entry::Occupied(_) => Ok(()), - Entry::Vacant(entry) => { - unsafe { - let descriptor: FontDescriptor = handle.into(); - let mut face_ptr = ptr::null_mut(); - let pathname = CString::new(descriptor.pathname - .as_os_str() - .as_bytes()).unwrap(); - let result = FT_New_Face(self.library, - pathname.as_ptr(), - descriptor.index as FT_Long, - &mut face_ptr); - let mut face = Face { - face: face_ptr, - bytes: None, - }; - if result == 0 && !face.face.is_null() { - entry.insert(face); - Ok(()) - } else { - Err(()) - } - } - } - } - } - - /// Unloads the font with the given font key from memory. - /// - /// If the font isn't loaded, does nothing. - pub fn delete_font(&mut self, font_key: &FK) { - self.faces.remove(font_key); - } - - /// Returns the dimensions of the given glyph in the given font. - /// - /// If `exact` is true, then the raw outline extents as specified by the font designer are - /// returned. These may differ from the extents when rendered on screen, because some font - /// libraries (including Pathfinder) apply modifications to the outlines: for example, to - /// dilate them for easier reading. To retrieve extents that account for these modifications, - /// set `exact` to false. - pub fn glyph_dimensions(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - exact: bool) - -> Result { - self.load_glyph(font_instance, glyph_key).ok_or(()).and_then(|glyph_slot| { - self.glyph_dimensions_from_slot(font_instance, glyph_key, glyph_slot, exact) - }) - } - - pub fn glyph_outline<'a>(&'a self, font_instance: &FontInstance, glyph_key: &GlyphKey) - -> Result, ()> { - self.load_glyph(font_instance, glyph_key).ok_or(()).map(|glyph_slot| { - unsafe { - GlyphOutline::new(&(*glyph_slot).outline) - } - }) - } - - /// Uses the FreeType library to rasterize a glyph on CPU. - /// - /// If `exact` is true, then the raw outline extents as specified by the font designer are - /// returned. These may differ from the extents when rendered on screen, because some font - /// libraries (including Pathfinder) apply modifications to the outlines: for example, to - /// dilate them for easier reading. To retrieve extents that account for these modifications, - /// set `exact` to false. - pub fn rasterize_glyph_with_native_rasterizer(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - _: bool) - -> Result { - // Load the glyph. - let slot = match self.load_glyph(font_instance, glyph_key) { - None => return Err(()), - Some(slot) => slot, - }; - - // Get the subpixel offset. - let subpixel_offset: Vector2D = - Vector2D::new(f32::to_ft_f26dot6(glyph_key.subpixel_offset.into()), 0); - - // Move the outline curves to be at the origin, taking the subpixel positioning into - // account. - unsafe { - let outline = &(*slot).outline; - let mut control_box: FT_BBox = mem::uninitialized(); - FT_Outline_Get_CBox(outline, &mut control_box); - FT_Outline_Translate( - outline, - subpixel_offset.x - fixed::floor(control_box.xMin + subpixel_offset.x), - subpixel_offset.y - fixed::floor(control_box.yMin + subpixel_offset.y)); - } - - // Set the LCD filter. - // - // TODO(pcwalton): Non-subpixel AA. - unsafe { - FT_Library_SetLcdFilter(self.library, FT_LcdFilter::FT_LCD_FILTER_DEFAULT); - } - - // Render the glyph. - // - // TODO(pcwalton): Non-subpixel AA. - unsafe { - FT_Render_Glyph(slot, FT_Render_Mode::FT_RENDER_MODE_LCD); - } - - unsafe { - // Make sure that the pixel mode is LCD. - // - // TODO(pcwalton): Non-subpixel AA. - let bitmap: *const FT_Bitmap = &(*slot).bitmap; - if (*bitmap).pixel_mode as u32 != FT_Pixel_Mode::FT_PIXEL_MODE_LCD as u32 { - return Err(()) - } - - debug_assert_eq!((*bitmap).width % 3, 0); - let pixel_size = Size2D::new((*bitmap).width as u32 / 3, (*bitmap).rows as u32); - let pixel_origin = Point2D::new((*slot).bitmap_left, (*slot).bitmap_top); - - // Allocate the RGBA8 buffer. - let src_stride = (*bitmap).pitch as usize; - let dest_stride = pixel_size.width as usize; - let src_area = src_stride * ((*bitmap).rows as usize); - let dest_area = pixel_size.area() as usize; - let mut dest_pixels: Vec = vec![0; dest_area]; - let src_pixels = slice::from_raw_parts((*bitmap).buffer, src_area); - - // Convert to RGBA8. - for y in 0..(pixel_size.height as usize) { - let dest_row = &mut dest_pixels[(y * dest_stride)..((y + 1) * dest_stride)]; - let src_row = &src_pixels[(y * src_stride)..((y + 1) * src_stride)]; - for (x, dest) in dest_row.iter_mut().enumerate() { - *dest = ((255 - src_row[x * 3 + 2]) as u32) | - (((255 - src_row[x * 3 + 1]) as u32) << 8) | - (((255 - src_row[x * 3 + 0]) as u32) << 16) | - (0xff << 24) - } - } - - // Return the result. - Ok(GlyphImage { - dimensions: GlyphDimensions { - origin: pixel_origin, - size: pixel_size, - advance: f32::from_ft_f26dot6((*slot).metrics.horiAdvance), - }, - pixels: convert_vec_u32_to_vec_u8(dest_pixels), - }) - } - } - - fn load_glyph(&self, font_instance: &FontInstance, glyph_key: &GlyphKey) - -> Option { - let face = match self.faces.get(&font_instance.font_key) { - None => return None, - Some(face) => face, - }; - - unsafe { - let point_size = font_instance.size.to_ft_f26dot6(); - FT_Set_Char_Size(face.face, point_size, 0, DPI, 0); - - if FT_Load_Glyph(face.face, glyph_key.glyph_index as FT_UInt, GLYPH_LOAD_FLAGS) != 0 { - return None - } - - let slot = (*face.face).glyph; - if (*slot).format != FT_Glyph_Format::FT_GLYPH_FORMAT_OUTLINE { - return None - } - - Some(slot) - } - } - - fn glyph_dimensions_from_slot(&self, - font_instance: &FontInstance, - glyph_key: &GlyphKey, - glyph_slot: FT_GlyphSlot, - exact: bool) - -> Result { - unsafe { - let metrics = &(*glyph_slot).metrics; - - // This matches what WebRender does. - if metrics.horiAdvance == 0 { - return Err(()) - } - - let bounding_box = self.bounding_box_from_slot(font_instance, glyph_key, glyph_slot); - - let mut lower_left = Point2D::new(f26dot6_to_i32_rounding_up(bounding_box.xMin), - f26dot6_to_i32_rounding_up(bounding_box.yMin)); - let mut upper_right = Point2D::new(f26dot6_to_i32_rounding_up(bounding_box.xMax), - f26dot6_to_i32_rounding_up(bounding_box.yMax)); - - // Account for stem darkening. Round up to be conservative. - if !exact { - let stem_darkening_radius = (font_instance.size.to_f32_px() * - STEM_DARKENING_AMOUNT * 0.5).ceil() as i32; - lower_left += Vector2D::new(-stem_darkening_radius, -stem_darkening_radius); - upper_right += Vector2D::new(stem_darkening_radius, stem_darkening_radius); - } - - Ok(GlyphDimensions { - origin: lower_left, - size: Size2D::new((upper_right.x - lower_left.x) as u32, - (upper_right.y - lower_left.y) as u32), - advance: f32::from_ft_f26dot6(metrics.horiAdvance) / - (*(*glyph_slot).face).units_per_EM as f32 * - font_instance.size.to_f32_px(), - }) - } - } - - // Returns the bounding box for a glyph, accounting for subpixel positioning as appropriate. - // - // TODO(pcwalton): Subpixel positioning. - fn bounding_box_from_slot(&self, _: &FontInstance, _: &GlyphKey, glyph_slot: FT_GlyphSlot) - -> FT_BBox { - let mut bounding_box: FT_BBox; - unsafe { - bounding_box = mem::zeroed(); - FT_Outline_Get_CBox(&(*glyph_slot).outline, &mut bounding_box); - }; - - // Outset the box to device pixel boundaries. This matches what WebRender does. - bounding_box.xMin = fixed::floor(bounding_box.xMin); - bounding_box.yMin = fixed::floor(bounding_box.yMin); - bounding_box.xMax = fixed::floor(bounding_box.xMax + 0x3f); - bounding_box.yMax = fixed::floor(bounding_box.yMax + 0x3f); - - bounding_box - } -} - -struct Face { - face: FT_Face, - #[allow(dead_code)] - bytes: Option>>, -} - -impl Drop for Face { - fn drop(&mut self) { - unsafe { - FT_Done_Face(self.face); - } - } -} - -pub struct FontDescriptor { - pub pathname: PathBuf, - pub index: u32, -} - -impl FontDescriptor { - #[inline] - pub fn new(pathname: PathBuf, index: u32) -> FontDescriptor { - FontDescriptor { - pathname: pathname, - index: index, - } - } -} - -unsafe fn convert_vec_u32_to_vec_u8(mut input: Vec) -> Vec { - let (ptr, len, cap) = (input.as_mut_ptr(), input.len(), input.capacity()); - mem::forget(input); - Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) -} - -fn f26dot6_to_i32_rounding_up(x: FT_F26Dot6) -> i32 { - ((x + (1 << 5) - 1) >> 6) as i32 -} diff --git a/font-renderer/src/freetype/outline.rs b/font-renderer/src/freetype/outline.rs deleted file mode 100644 index 87ff3baa..00000000 --- a/font-renderer/src/freetype/outline.rs +++ /dev/null @@ -1,147 +0,0 @@ -// pathfinder/font-renderer/src/freetype/outline.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use euclid::Point2D; -use freetype_sys::freetype::{FT_Outline, FT_Vector}; -use lyon_path::iterator::PathIterator; -use lyon_path::{PathEvent, PathState}; - -const FREETYPE_POINT_ON_CURVE: i8 = 0x01; - -#[derive(Clone)] -pub struct Outline<'a> { - outline: &'a FT_Outline, -} - -impl<'a> Outline<'a> { - #[inline] - pub unsafe fn new(outline: &FT_Outline) -> Outline { - Outline { - outline: outline, - } - } - - #[inline] - pub fn iter(&self) -> OutlineStream { - unsafe { - OutlineStream::new(self.outline) - } - } -} - -pub struct OutlineStream<'a> { - outline: &'a FT_Outline, - point_index: u16, - contour_index: u16, - state: PathState, - first_point_index_of_contour: bool, -} - -impl<'a> OutlineStream<'a> { - #[inline] - pub unsafe fn new(outline: &FT_Outline) -> OutlineStream { - OutlineStream { - outline: outline, - point_index: 0, - contour_index: 0, - state: PathState::new(), - first_point_index_of_contour: true, - } - } - - #[inline] - fn current_position_and_tag(&self) -> (Point2D, i8) { - unsafe { - let point_offset = self.point_index as isize; - let position = ft_vector_to_f32(*self.outline.points.offset(point_offset)); - let tag = *self.outline.tags.offset(point_offset); - (position, tag) - } - } -} - -impl<'a> Iterator for OutlineStream<'a> { - type Item = PathEvent; - - fn next(&mut self) -> Option { - unsafe { - let mut control_point_position: Option> = None; - loop { - if self.contour_index == self.outline.n_contours as u16 { - return None - } - - let last_point_index_in_current_contour = - *self.outline.contours.offset(self.contour_index as isize) as u16; - if self.point_index == last_point_index_in_current_contour + 1 { - if let Some(control_point_position) = control_point_position { - let event = PathEvent::QuadraticTo(control_point_position, - self.state.first); - self.state.path_event(event); - return Some(event) - } - - self.contour_index += 1; - self.first_point_index_of_contour = true; - self.state.close(); - return Some(PathEvent::Close) - } - - // FIXME(pcwalton): Approximate cubic curves with quadratics. - let (position, tag) = self.current_position_and_tag(); - let point_on_curve = (tag & FREETYPE_POINT_ON_CURVE) != 0; - - if self.first_point_index_of_contour { - self.first_point_index_of_contour = false; - self.point_index += 1; - self.state.move_to(position); - return Some(PathEvent::MoveTo(position)); - } - - match (control_point_position, point_on_curve) { - (Some(control_point_position), false) => { - let on_curve_position = control_point_position.lerp(position, 0.5); - let event = PathEvent::QuadraticTo(control_point_position, - on_curve_position); - self.state.path_event(event); - return Some(event) - } - (Some(control_point_position), true) => { - self.point_index += 1; - let event = PathEvent::QuadraticTo(control_point_position, position); - self.state.path_event(event); - return Some(event) - } - (None, false) => { - self.point_index += 1; - control_point_position = Some(position); - } - (None, true) => { - self.point_index += 1; - self.state.line_to(position); - return Some(PathEvent::LineTo(position)) - } - } - } - } - } -} - -impl<'a> PathIterator for OutlineStream<'a> { - #[inline] - fn get_state(&self) -> &PathState { - &self.state - } -} - -#[inline] -fn ft_vector_to_f32(ft_vector: FT_Vector) -> Point2D { - Point2D::new(ft_vector.x as f32 / 64.0, ft_vector.y as f32 / 64.0) -} diff --git a/font-renderer/src/lib.rs b/font-renderer/src/lib.rs deleted file mode 100644 index cf5124dc..00000000 --- a/font-renderer/src/lib.rs +++ /dev/null @@ -1,168 +0,0 @@ -// pathfinder/font-renderer/src/lib.rs -// -// Copyright © 2017 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Reads outlines from OpenType fonts into Pathfinder path formats. -//! -//! Use this crate in conjunction with `pathfinder_partitioner` in order to create meshes for -//! rendering. -//! -//! To reduce dependencies and to match the system as closely as possible, this crate uses the -//! native OS font rendering infrastructure as much as it can. Backends are available for FreeType, -//! Core Graphics/Quartz on macOS, and DirectWrite on Windows. - -extern crate app_units; -extern crate euclid; -extern crate libc; -extern crate lyon_path; -extern crate serde; - -#[allow(unused_imports)] -#[macro_use] -extern crate log; - -#[macro_use] -extern crate serde_derive; - -#[cfg(test)] -extern crate env_logger; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -extern crate core_graphics as core_graphics_sys; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -extern crate core_text; - -#[cfg(any(target_os = "linux", feature = "freetype-backend"))] -extern crate freetype as freetype_sys; - -#[cfg(target_os = "windows")] -extern crate dwrite; -#[cfg(target_os = "windows")] -extern crate kernel32; -#[cfg(target_os = "windows")] -extern crate uuid; -#[cfg(target_os = "windows")] -#[macro_use(DEFINE_GUID)] -extern crate winapi; - -#[cfg(target_os = "windows")] -pub use self::directwrite::PathfinderComPtr; -#[cfg(target_os = "windows")] -pub use winapi::IDWriteFontFace; - -use app_units::Au; -use euclid::{Point2D, Size2D}; - -#[cfg(test)] -mod tests; - -#[cfg(all(any(target_os = "macos", target_os = "ios"), not(feature = "freetype-backend")))] -pub use core_graphics::{FontContext, GlyphOutline}; -#[cfg(all(target_os = "windows", not(feature = "freetype-backend")))] -pub use directwrite::FontContext; -#[cfg(any(target_os = "linux", feature = "freetype-backend"))] -pub use freetype::FontContext; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub mod core_graphics; -#[cfg(all(target_os = "windows", not(feature = "freetype-backend")))] -mod directwrite; -#[cfg(any(target_os = "linux", feature = "freetype-backend"))] -pub mod freetype; - -/// The number of subpixels that each pixel is divided into for the purposes of subpixel glyph -/// positioning. -/// -/// Right now, each glyph is snapped to the nearest quarter-pixel. -pub const SUBPIXEL_GRANULARITY: u8 = 4; - -/// A font at one specific size. -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] -pub struct FontInstance where FK: Clone { - /// The opaque font key that this font instance represents. - pub font_key: FK, - - /// The size of the font. - /// - /// This is in app units (1/60 pixels) to eliminate floating point error. - pub size: Au, -} - -impl FontInstance where FK: Clone { - /// Creates a new instance of a font at the given size. - #[inline] - pub fn new(font_key: &FK, size: Au) -> FontInstance { - FontInstance { - font_key: (*font_key).clone(), - size: size, - } - } -} - -/// A subpixel offset, from 0 to `SUBPIXEL_GRANULARITY`. -#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] -pub struct SubpixelOffset(pub u8); - -impl Into for SubpixelOffset { - #[inline] - fn into(self) -> f32 { - self.0 as f32 / SUBPIXEL_GRANULARITY as f32 - } -} - -impl Into for SubpixelOffset { - #[inline] - fn into(self) -> f64 { - self.0 as f64 / SUBPIXEL_GRANULARITY as f64 - } -} - -/// A handle to the resolution-independent image of a single glyph in a single font. -#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)] -pub struct GlyphKey { - /// The OpenType glyph index. - pub glyph_index: u32, - /// The subpixel offset, from 0 to `SUBPIXEL_GRANULARITY`. - pub subpixel_offset: SubpixelOffset, -} - -impl GlyphKey { - /// Creates a new glyph key from the given index and subpixel offset. - #[inline] - pub fn new(glyph_index: u32, subpixel_offset: SubpixelOffset) -> GlyphKey { - GlyphKey { - glyph_index: glyph_index, - subpixel_offset: subpixel_offset, - } - } -} - -/// The resolution-independent dimensions of a glyph, in font units. -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] -pub struct GlyphDimensions { - /// The origin of the glyph. - pub origin: Point2D, - /// The total size of the glyph. - pub size: Size2D, - /// The advance of the glyph: that is, the distance from this glyph to the next one. - pub advance: f32, -} - -/// A bitmap image of a glyph. -pub struct GlyphImage { - /// The dimensions of this image. - pub dimensions: GlyphDimensions, - /// The actual pixels. - /// - /// This is 8 bits per pixel grayscale when grayscale antialiasing is in use and 24 bits per - /// pixel RGB when subpixel antialiasing is in use. - pub pixels: Vec, -} diff --git a/font-renderer/src/tests.rs b/font-renderer/src/tests.rs deleted file mode 100644 index 74057578..00000000 --- a/font-renderer/src/tests.rs +++ /dev/null @@ -1,166 +0,0 @@ -// pathfinder/font-renderer/src/tests.rs - -use app_units::Au; -use env_logger; -use euclid::Size2D; -use euclid::approxeq::ApproxEq; -use pathfinder_path_utils::{PathBuffer, Subpath}; -use std::fs::File; -use std::io::Read; -use std::sync::Arc; -use {FontContext, FontInstance, FontKey, GlyphDimensions, GlyphKey, SubpixelOffset}; - -static TEST_FONT_PATH: &'static str = "../resources/fonts/nimbus-sans/NimbusSanL-Regu.ttf"; -const TEST_FONT_SIZE: Au = Au(60 * 16); -const TEST_GLYPH_ID: u32 = 68; // 'a' - -const EXPECTED_GLYPH_ORIGIN: [i32; 2] = [0, 9]; -const EXPECTED_GLYPH_SIZE: [u32; 2] = [9, 9]; -const EXPECTED_GLYPH_ADVANCE: f32 = 9.0; - -static EXPECTED_GLYPH_ENDPOINTS: [[f32; 2]; 34] = [ - [ 548.0, 77.0 ], - [ 548.0, 10.0 ], - [ 490.0, 0.0 ], - [ 402.0, 82.0 ], - [ 323.0, 24.0 ], - [ 219.0, 0.0 ], - [ 89.0, 44.0 ], - [ 43.0, 158.0 ], - [ 138.0, 301.0 ], - [ 233.0, 324.0 ], - [ 310.0, 333.0 ], - [ 381.0, 353.0 ], - [ 399.0, 392.0 ], - [ 399.0, 414.0 ], - [ 362.0, 476.0 ], - [ 278.0, 494.0 ], - [ 153.0, 400.0 ], - [ 67.0, 400.0 ], - [ 104.0, 512.0 ], - [ 282.0, 576.0 ], - [ 444.0, 529.0 ], - [ 484.0, 430.0 ], - [ 484.0, 117.0 ], - [ 530.0, 75.0 ], - [ 399.0, 289.0 ], - [ 349.0, 273.0 ], - [ 261.0, 258.0 ], - [ 165.0, 228.0 ], - [ 132.0, 161.0 ], - [ 157.0, 101.0 ], - [ 238.0, 75.0 ], - [ 365.0, 124.0 ], - [ 396.0, 169.0 ], - [ 399.0, 193.0 ], -]; - -static EXPECTED_GLYPH_CONTROL_POINTS: [[f32; 2]; 29] = [ - [ 512.0, 0.0 ], - [ 410.0, 0.0 ], - [ 362.0, 43.0 ], - [ 276.0, 0.0 ], - [ 137.0, 0.0 ], - [ 43.0, 86.0 ], - [ 43.0, 262.0 ], - [ 169.0, 314.0 ], - [ 241.0, 325.0 ], - [ 365.0, 340.0 ], - [ 398.0, 366.0 ], - [ 399.0, 457.0 ], - [ 330.0, 494.0 ], - [ 163.0, 494.0 ], - [ 70.0, 474.0 ], - [ 160.0, 576.0 ], - [ 394.0, 576.0 ], - [ 484.0, 493.0 ], - [ 484.0, 75.0 ], - [ 537.0, 75.0 ], - [ 377.0, 278.0 ], - [ 325.0, 268.0 ], - [ 195.0, 249.0 ], - [ 132.0, 205.0 ], - [ 132.0, 125.0 ], - [ 183.0, 75.0 ], - [ 313.0, 75.0 ], - [ 390.0, 147.0 ], - [ 399.0, 177.0 ], -]; - -static EXPECTED_GLYPH_SUBPATHS: [Subpath; 2] = [ - Subpath { - first_endpoint_index: 0, - last_endpoint_index: 24, - }, - Subpath { - first_endpoint_index: 24, - last_endpoint_index: 34, - }, -]; - -#[test] -fn test_font_context_glyph_dimensions() { - let mut font_context = FontContext::new().unwrap(); - - let font_key = FontKey::new(); - let mut bytes = vec![]; - File::open(TEST_FONT_PATH).unwrap().read_to_end(&mut bytes).unwrap(); - font_context.add_font_from_memory(&font_key, Arc::new(bytes), 0).unwrap(); - - let font_instance = FontInstance::new(&font_key, TEST_FONT_SIZE); - let glyph_key = GlyphKey::new(TEST_GLYPH_ID, SubpixelOffset(0)); - let glyph_dimensions = font_context.glyph_dimensions(&font_instance, &glyph_key).unwrap(); - - assert_eq!(glyph_dimensions, GlyphDimensions { - origin: EXPECTED_GLYPH_ORIGIN.into(), - size: Size2D::new(EXPECTED_GLYPH_SIZE[0], EXPECTED_GLYPH_SIZE[1]), - advance: EXPECTED_GLYPH_ADVANCE, - }) -} - -#[test] -fn test_font_context_glyph_outline() { - drop(env_logger::init()); - - let mut font_context = FontContext::new().unwrap(); - - let font_key = FontKey::new(); - let mut bytes = vec![]; - File::open(TEST_FONT_PATH).unwrap().read_to_end(&mut bytes).unwrap(); - font_context.add_font_from_memory(&font_key, Arc::new(bytes), 0).unwrap(); - - let font_instance = FontInstance::new(&font_key, TEST_FONT_SIZE); - let glyph_key = GlyphKey::new(TEST_GLYPH_ID, SubpixelOffset(0)); - let glyph_outline = font_context.glyph_outline(&font_instance, &glyph_key).unwrap(); - let mut glyph_outline_buffer = PathBuffer::new(); - glyph_outline_buffer.add_stream(glyph_outline); - - info!("endpoints: {:#?}", glyph_outline_buffer.endpoints); - info!("control points: {:#?}", glyph_outline_buffer.control_points); - - assert_eq!(glyph_outline_buffer.endpoints.len(), EXPECTED_GLYPH_ENDPOINTS.len()); - for (expected_position, endpoint) in - EXPECTED_GLYPH_ENDPOINTS.iter().zip(glyph_outline_buffer.endpoints.iter()) { - let actual_position = endpoint.position; - info!("expected endpoint: {:?} actual endpoint: {:?}", expected_position, actual_position); - assert!(expected_position[0].approx_eq(&actual_position.x) && - expected_position[1].approx_eq(&actual_position.y)); - } - - assert_eq!(glyph_outline_buffer.control_points.len(), EXPECTED_GLYPH_CONTROL_POINTS.len()); - for (expected_position, actual_position) in - EXPECTED_GLYPH_CONTROL_POINTS.iter().zip(glyph_outline_buffer.control_points.iter()) { - info!("expected control point: {:?} actual control point: {:?}", - expected_position, - actual_position); - assert!(expected_position[0].approx_eq(&actual_position.x) && - expected_position[1].approx_eq(&actual_position.y)); - } - - assert_eq!(glyph_outline_buffer.subpaths.len(), EXPECTED_GLYPH_SUBPATHS.len()); - for (expected_subpath, actual_subpath) in - EXPECTED_GLYPH_SUBPATHS.iter().zip(glyph_outline_buffer.subpaths.iter()) { - assert_eq!(expected_subpath.first_endpoint_index, actual_subpath.first_endpoint_index); - assert_eq!(expected_subpath.last_endpoint_index, actual_subpath.last_endpoint_index); - } -} diff --git a/utils/frontend/Cargo.toml b/utils/frontend/Cargo.toml index 15998f1e..3795e482 100644 --- a/utils/frontend/Cargo.toml +++ b/utils/frontend/Cargo.toml @@ -4,14 +4,12 @@ version = "0.2.0" authors = ["Patrick Walton "] [dependencies] -app_units = "0.7" clap = "2.27" -freetype = "0.4" lyon_path = "0.12" -[dependencies.pathfinder_font_renderer] -path = "../../font-renderer" -features = ["freetype"] +[dependencies.font-kit] +git = "https://github.com/pcwalton/font-kit" +features = ["loader-freetype-default"] [dependencies.pathfinder_partitioner] path = "../../partitioner" diff --git a/utils/frontend/src/main.rs b/utils/frontend/src/main.rs index 92c52405..1d9f1833 100644 --- a/utils/frontend/src/main.rs +++ b/utils/frontend/src/main.rs @@ -23,77 +23,38 @@ //! simple storage format for VBOs. To render these paths, you can directly upload these VBOs to //! the GPU and render them using the shaders provided. -extern crate app_units; extern crate clap; -extern crate freetype; +extern crate font_kit; extern crate lyon_path; -extern crate pathfinder_font_renderer; extern crate pathfinder_partitioner; extern crate pathfinder_path_utils; -use app_units::Au; use clap::{App, Arg}; -use freetype::freetype::{FT_Init_FreeType, FT_New_Face}; +use font_kit::font::Font; +use font_kit::hinting::HintingOptions; use lyon_path::PathEvent; use lyon_path::builder::{FlatPathBuilder, PathBuilder}; -use pathfinder_font_renderer::{FontContext, FontInstance, GlyphKey, SubpixelOffset}; +use lyon_path::default::Path as LyonPath; use pathfinder_partitioner::FillRule; use pathfinder_partitioner::mesh_pack::MeshPack; use pathfinder_partitioner::partitioner::Partitioner; -use std::ffi::CString; use std::fs::File; -use std::io::Read; use std::path::{Path, PathBuf}; use std::process; -use std::ptr; -use std::sync::Arc; - -const FONT_SIZE: f64 = 72.0; fn convert_font(font_path: &Path, output_path: &Path) -> Result<(), ()> { - let mut freetype_library = ptr::null_mut(); - let glyph_count; - unsafe { - if FT_Init_FreeType(&mut freetype_library) != 0 { - return Err(()) - } - - // TODO(pcwalton): Allow the user to select a face by index. - let mut freetype_face = ptr::null_mut(); - let font_path = match font_path.to_str() { - None => return Err(()), - Some(font_path) => font_path, - }; - let font_path = try!(CString::new(font_path).map_err(drop)); - if FT_New_Face(freetype_library, font_path.as_ptr(), 0, &mut freetype_face) != 0 { - return Err(()) - } - - glyph_count = (*freetype_face).num_glyphs as u32; - } - - let mut font_data = vec![]; - let mut font_file = try!(File::open(font_path).map_err(drop)); - try!(font_file.read_to_end(&mut font_data).map_err(drop)); - - // TODO(pcwalton): Allow the user to select a face by index. - let mut font_context = try!(FontContext::new()); - try!(font_context.add_font_from_memory(&(), Arc::new(font_data), 0)); - let font_instance = FontInstance { - font_key: (), - size: Au::from_f64_px(FONT_SIZE), - }; + let font = try!(Font::from_path(font_path, 0).map_err(drop)); + let glyph_count = font.glyph_count(); let mut paths: Vec<(u16, Vec)> = vec![]; let mut mesh_pack = MeshPack::new(); for glyph_index in 0..glyph_count { - let glyph_key = GlyphKey::new(glyph_index, SubpixelOffset(0)); - - let path = match font_context.glyph_outline(&font_instance, &glyph_key) { - Ok(path) => path, - Err(_) => continue, - }; + let mut path_builder = LyonPath::builder(); + if font.outline(glyph_index, HintingOptions::None, &mut path_builder).is_err() { + continue + } + let path = path_builder.build(); let mut partitioner = Partitioner::new();