diff --git a/Cargo.lock b/Cargo.lock index 8873b47b..d5a5ced7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,6 +170,20 @@ dependencies = [ "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "canvas_text" +version = "0.1.0" +dependencies = [ + "gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pathfinder_canvas 0.1.0", + "pathfinder_geometry 0.3.0", + "pathfinder_gl 0.1.0", + "pathfinder_gpu 0.1.0", + "pathfinder_renderer 0.1.0", + "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.29" @@ -226,6 +240,14 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cocoa" version = "0.18.4" @@ -296,6 +318,17 @@ dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-text" +version = "13.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc32fast" version = "1.1.2" @@ -403,6 +436,18 @@ name = "downcast-rs" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dwrote" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "egl" version = "0.2.7" @@ -468,6 +513,15 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "expat-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "failure" version = "0.1.5" @@ -501,6 +555,40 @@ dependencies = [ "num-traits 0.2.6 (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 = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (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 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (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.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -514,6 +602,15 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "freetype" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fs_extra" version = "1.1.0" @@ -615,6 +712,27 @@ dependencies = [ "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "harfbuzz" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "harfbuzz-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "harfbuzz-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.1.8" @@ -672,6 +790,14 @@ dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.7.11" +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.3" @@ -827,6 +953,14 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lyon_path" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lzw" version = "0.10.0" @@ -853,6 +987,15 @@ name = "memchr" version = "2.2.0" source = "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.48 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memmap" version = "0.7.0" @@ -1031,8 +1174,11 @@ dependencies = [ name = "pathfinder_canvas" version = "0.1.0" dependencies = [ + "font-kit 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_renderer 0.1.0", + "pathfinder_text 0.1.0", + "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)", ] [[package]] @@ -1149,6 +1295,18 @@ dependencies = [ "usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pathfinder_text" +version = "0.1.0" +dependencies = [ + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.1.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_geometry 0.3.0", + "pathfinder_renderer 0.1.0", + "skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)", +] + [[package]] name = "pathfinder_ui" version = "0.1.0" @@ -1601,6 +1759,34 @@ dependencies = [ "serde 1.0.88 (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.48 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-fontconfig-sys 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "servo-fontconfig-sys" +version = "4.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "servo-freetype-sys" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shared_library" version = "0.1.9" @@ -1620,6 +1806,18 @@ name = "siphasher" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "skribo" +version = "0.0.1" +source = "git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e#f759c2d2c188b668bce998179f03b6319835353e" +dependencies = [ + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "font-kit 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "harfbuzz-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.2" @@ -1789,6 +1987,14 @@ name = "ucd-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-normalization" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-segmentation" version = "1.2.1" @@ -2038,6 +2244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" "checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b" "checksum color-backtrace 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "90242aff9b6439332beb77ee416126367adcd6376b0dc80b39250e7debdd913d" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" @@ -2046,6 +2253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" +"checksum core-text 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d95a72b5e50e549969dd88eff3047495fe5b8c6f028635442c2b708be707e669" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" @@ -2056,6 +2264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f" +"checksum dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30a998e9ff70cd208ccdc4f864e998688bf61d7b897dccec8e17a884d17358bf" "checksum egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a373bc9844200b1ff15bd1b245931d1c20d09d06e4ec09f361171f29a4b0752d" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" @@ -2063,12 +2272,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea" "checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15" +"checksum expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "134a8fa843d80a51a5b77d36d42bc2def9edcb0262c914861d08129fd1926600" +"checksum float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +"checksum font-kit 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5be0133b580e2920076afd5bd4b81dc172d10e5653bd1c516476718d52347859" "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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "11926b2b410b469d0e9399eca4cbbe237a9ef02176c485803b29216307e8e028" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" @@ -2079,11 +2292,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gl_generator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "75d69f914b49d9ff32fdf394cbd798f8c716d74fd19f9cc29da3e99797b2a78d" "checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5" "checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3" +"checksum harfbuzz 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46f7426266a5ece3e49eae6f48e602c0f8c39917354a847eac9c06437dcde8da" +"checksum harfbuzz-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e1042ab0b3e7bc1ff64f7f5935778b644ff2194a1cae5ec52167127d3fd23961" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" "checksum image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "52fb0666a1273dac46f9725aa4859bcd5595fc3554cf3495051b4de8db745e7d" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" @@ -2104,10 +2320,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2b60eaa9061c87affcd671e88289ce6971324269ec6548b677e02624ef3ef63c" +"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 memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98" @@ -2180,9 +2398,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4" "checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9" +"checksum servo-fontconfig-sys 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b46d201addcfbd25c1798ad1281d98c40743824e0b0f1e611bd3d5d0d31a7b8d" +"checksum servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4ccb6d0d32d277d3ef7dea86203d8210945eb7a45fba89dd445b3595dd0dfc" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum skribo 0.0.1 (git+https://github.com/linebender/skribo.git?rev=f759c2d2c188b668bce998179f03b6319835353e)" = "" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum smithay-client-toolkit 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4899558362a65589b53313935099835acf999740915e134dff20cca7c6a28b" @@ -2202,6 +2424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Cargo.toml b/Cargo.toml index 260b6cb8..c7f5b16c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,12 +6,14 @@ members = [ "demo/magicleap", "demo/native", "examples/canvas_minimal", + "examples/canvas_text", "geometry", "gl", "gpu", "renderer", "simd", "svg", + "text", "ui", "utils/area-lut", "utils/gamma-lut", diff --git a/canvas/Cargo.toml b/canvas/Cargo.toml index fac9e346..0bd17dcb 100644 --- a/canvas/Cargo.toml +++ b/canvas/Cargo.toml @@ -5,9 +5,17 @@ authors = ["Patrick Walton "] edition = "2018" [dependencies] +font-kit = "0.1" [dependencies.pathfinder_geometry] path = "../geometry" [dependencies.pathfinder_renderer] path = "../renderer" + +[dependencies.pathfinder_text] +path = "../text" + +[dependencies.skribo] +git = "https://github.com/linebender/skribo.git" +rev = "f759c2d2c188b668bce998179f03b6319835353e" diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 3d0bf508..6e751cb6 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -10,21 +10,35 @@ //! A simple API for Pathfinder that mirrors a subset of HTML canvas. +use font_kit::family_name::FamilyName; +use font_kit::hinting::HintingOptions; +use font_kit::properties::Properties; +use font_kit::source::SystemSource; use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::rect::RectF32; +use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::color::ColorU; use pathfinder_geometry::outline::{Contour, Outline}; use pathfinder_geometry::stroke::OutlineStrokeToFill; use pathfinder_renderer::scene::{Paint, PathObject, Scene}; +use pathfinder_text::{SceneExt, TextRenderMode}; +use skribo::{FontCollection, FontFamily, TextStyle}; use std::default::Default; use std::mem; +use std::sync::Arc; const HAIRLINE_STROKE_WIDTH: f32 = 0.0333; +const DEFAULT_FONT_SIZE: f32 = 10.0; pub struct CanvasRenderingContext2D { scene: Scene, current_state: State, saved_states: Vec, + + #[allow(dead_code)] + font_source: SystemSource, + #[allow(dead_code)] + default_font_collection: Arc, } impl CanvasRenderingContext2D { @@ -35,9 +49,27 @@ impl CanvasRenderingContext2D { CanvasRenderingContext2D::from_scene(scene) } - #[inline] pub fn from_scene(scene: Scene) -> CanvasRenderingContext2D { - CanvasRenderingContext2D { scene, current_state: State::default(), saved_states: vec![] } + // TODO(pcwalton): Allow the user to cache this? + let font_source = SystemSource::new(); + + let mut default_font_collection = FontCollection::new(); + let default_font = + font_source.select_best_match(&[FamilyName::SansSerif], &Properties::new()) + .expect("Failed to select the default font!") + .load() + .expect("Failed to load the default font!"); + default_font_collection.add_family(FontFamily::new_from_font(default_font)); + let default_font_collection = Arc::new(default_font_collection); + + CanvasRenderingContext2D { + scene, + current_state: State::default(default_font_collection.clone()), + saved_states: vec![], + + font_source, + default_font_collection, + } } #[inline] @@ -59,6 +91,32 @@ impl CanvasRenderingContext2D { self.stroke_path(path); } + pub fn fill_text(&mut self, string: &str, position: Point2DF32) { + // TODO(pcwalton): Report errors. + let paint_id = self.scene.push_paint(&self.current_state.fill_paint); + drop(self.scene.push_text(string, + &TextStyle { size: self.current_state.font_size }, + &self.current_state.font_collection, + &Transform2DF32::from_translation(&position), + TextRenderMode::Fill, + HintingOptions::None, + paint_id)); + } + + pub fn stroke_text(&mut self, string: &str, position: Point2DF32) { + // TODO(pcwalton): Report errors. + let paint_id = self.scene.push_paint(&self.current_state.stroke_paint); + drop(self.scene.push_text(string, + &TextStyle { size: self.current_state.font_size }, + &self.current_state.font_collection, + &Transform2DF32::from_translation(&position), + TextRenderMode::Stroke(self.current_state.line_width), + HintingOptions::None, + paint_id)); + } + + // Line styles + #[inline] pub fn set_line_width(&mut self, new_line_width: f32) { self.current_state.line_width = new_line_width @@ -74,6 +132,15 @@ impl CanvasRenderingContext2D { self.current_state.stroke_paint = new_stroke_style.to_paint(); } + // Text styles + + #[inline] + pub fn set_font_size(&mut self, new_font_size: f32) { + self.current_state.font_size = new_font_size; + } + + // Paths + #[inline] pub fn fill_path(&mut self, path: Path2D) { let paint_id = self.scene.push_paint(&self.current_state.fill_paint); @@ -91,7 +158,7 @@ impl CanvasRenderingContext2D { #[inline] pub fn save(&mut self) { - self.saved_states.push(self.current_state); + self.saved_states.push(self.current_state.clone()); } #[inline] @@ -102,17 +169,20 @@ impl CanvasRenderingContext2D { } } -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct State { + font_collection: Arc, + font_size: f32, fill_paint: Paint, stroke_paint: Paint, line_width: f32, } -impl Default for State { - #[inline] - fn default() -> State { +impl State { + fn default(default_font_collection: Arc) -> State { State { + font_collection: default_font_collection, + font_size: DEFAULT_FONT_SIZE, fill_paint: Paint { color: ColorU::black() }, stroke_paint: Paint { color: ColorU::black() }, line_width: 1.0, diff --git a/examples/canvas_text/Cargo.toml b/examples/canvas_text/Cargo.toml new file mode 100644 index 00000000..174d4c96 --- /dev/null +++ b/examples/canvas_text/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "canvas_text" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[dependencies] +gl = "0.6" +sdl2 = "0.32" +sdl2-sys = "0.32" + +[dependencies.pathfinder_canvas] +path = "../../canvas" + +[dependencies.pathfinder_geometry] +path = "../../geometry" + +[dependencies.pathfinder_gl] +path = "../../gl" + +[dependencies.pathfinder_gpu] +path = "../../gpu" + +[dependencies.pathfinder_renderer] +path = "../../renderer" diff --git a/examples/canvas_text/src/main.rs b/examples/canvas_text/src/main.rs new file mode 100644 index 00000000..a4f3118a --- /dev/null +++ b/examples/canvas_text/src/main.rs @@ -0,0 +1,77 @@ +// pathfinder/canvas_text/src/main.rs +// +// Copyright © 2019 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 pathfinder_canvas::{CanvasRenderingContext2D, Path2D}; +use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; +use pathfinder_geometry::basic::rect::RectF32; +use pathfinder_geometry::color::ColorF; +use pathfinder_gl::{GLDevice, GLVersion}; +use pathfinder_gpu::resources::FilesystemResourceLoader; +use pathfinder_gpu::{ClearParams, Device}; +use pathfinder_renderer::concurrent::rayon::RayonExecutor; +use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; +use pathfinder_renderer::gpu::renderer::{DestFramebuffer, Renderer}; +use pathfinder_renderer::options::RenderOptions; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::video::GLProfile; + +fn main() { + // Set up SDL2. + let sdl_context = sdl2::init().unwrap(); + let video = sdl_context.video().unwrap(); + + // Make sure we have at least a GL 3.0 context. Pathfinder requires this. + let gl_attributes = video.gl_attr(); + gl_attributes.set_context_profile(GLProfile::Core); + gl_attributes.set_context_version(3, 3); + + // Open a window. + let window_size = Point2DI32::new(640, 480); + let window = video.window("Text example", window_size.x() as u32, window_size.y() as u32) + .opengl() + .build() + .unwrap(); + + // Create the GL context, and make it current. + let gl_context = window.gl_create_context().unwrap(); + gl::load_with(|name| video.gl_get_proc_address(name) as *const _); + window.gl_make_current(&gl_context).unwrap(); + + // Create a Pathfinder renderer. + let mut renderer = Renderer::new(GLDevice::new(GLVersion::GL3, 0), + &FilesystemResourceLoader::locate(), + DestFramebuffer::full_window(window_size)); + + // Clear to white. + renderer.device.clear(&ClearParams { color: Some(ColorF::white()), ..ClearParams::default() }); + + // Make a canvas. We're going to draw some text. + let mut canvas = CanvasRenderingContext2D::new(window_size.to_f32()); + + // Draw the text. + canvas.set_font_size(32.0); + canvas.fill_text("Hello Pathfinder!", Point2DF32::new(32.0, 48.0)); + canvas.stroke_text("Goodbye Pathfinder!", Point2DF32::new(32.0, 96.0)); + + // Render the canvas to screen. + let scene = SceneProxy::new(canvas.into_scene(), RayonExecutor); + scene.build_and_render(&mut renderer, RenderOptions::default()); + window.gl_swap_window(); + + // Wait for a keypress. + let mut event_pump = sdl_context.event_pump().unwrap(); + loop { + match event_pump.wait_event() { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return, + _ => {} + } + } +} diff --git a/geometry/src/segment.rs b/geometry/src/segment.rs index ffb5ac18..3334d1b0 100644 --- a/geometry/src/segment.rs +++ b/geometry/src/segment.rs @@ -51,7 +51,7 @@ impl Segment { Segment { baseline: *baseline, ctrl: LineSegmentF32::new(ctrl, &Point2DF32::default()), - kind: SegmentKind::Cubic, + kind: SegmentKind::Quadratic, flags: SegmentFlags::empty(), } } @@ -111,6 +111,7 @@ impl Segment { new_segment.ctrl = LineSegmentF32::new(&(self.baseline.from() + p1_2), &(p1_2 + self.baseline.to())) .scale(1.0 / 3.0); + new_segment.kind = SegmentKind::Cubic; new_segment } diff --git a/geometry/src/stroke.rs b/geometry/src/stroke.rs index fe891b65..1a1959a8 100644 --- a/geometry/src/stroke.rs +++ b/geometry/src/stroke.rs @@ -13,7 +13,7 @@ use crate::basic::line_segment::LineSegmentF32; use crate::basic::rect::RectF32; use crate::outline::{Contour, Outline}; -use crate::segment::Segment as SegmentPF3; +use crate::segment::Segment; use std::mem; const TOLERANCE: f32 = 0.01; @@ -88,10 +88,10 @@ impl ContourStrokeToFill { trait Offset { fn offset(&self, distance: f32, contour: &mut Contour); fn offset_once(&self, distance: f32) -> Self; - fn error_is_within_tolerance(&self, other: &SegmentPF3, distance: f32) -> bool; + fn error_is_within_tolerance(&self, other: &Segment, distance: f32) -> bool; } -impl Offset for SegmentPF3 { +impl Offset for Segment { fn offset(&self, distance: f32, contour: &mut Contour) { if self.baseline.square_length() < TOLERANCE * TOLERANCE { contour.push_full_segment(self, true); @@ -112,9 +112,9 @@ impl Offset for SegmentPF3 { after.offset(distance, contour); } - fn offset_once(&self, distance: f32) -> SegmentPF3 { + fn offset_once(&self, distance: f32) -> Segment { if self.is_line() { - return SegmentPF3::line(&self.baseline.offset(distance)); + return Segment::line(&self.baseline.offset(distance)); } if self.is_quadratic() { @@ -127,7 +127,7 @@ impl Offset for SegmentPF3 { None => segment_0.to().lerp(segment_1.from(), 0.5), }; let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); - return SegmentPF3::quadratic(&baseline, &ctrl); + return Segment::quadratic(&baseline, &ctrl); } debug_assert!(self.is_cubic()); @@ -143,7 +143,7 @@ impl Offset for SegmentPF3 { }; let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); let ctrl = LineSegmentF32::new(&segment_0.from(), &ctrl); - return SegmentPF3::cubic(&baseline, &ctrl); + return Segment::cubic(&baseline, &ctrl); } if self.ctrl.to() == self.baseline.to() { @@ -157,7 +157,7 @@ impl Offset for SegmentPF3 { }; let baseline = LineSegmentF32::new(&segment_0.from(), &segment_1.to()); let ctrl = LineSegmentF32::new(&ctrl, &segment_1.to()); - return SegmentPF3::cubic(&baseline, &ctrl); + return Segment::cubic(&baseline, &ctrl); } let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from()); @@ -178,10 +178,10 @@ impl Offset for SegmentPF3 { }; let baseline = LineSegmentF32::new(&segment_0.from(), &segment_2.to()); let ctrl = LineSegmentF32::new(&ctrl_0, &ctrl_1); - SegmentPF3::cubic(&baseline, &ctrl) + Segment::cubic(&baseline, &ctrl) } - fn error_is_within_tolerance(&self, other: &SegmentPF3, distance: f32) -> bool { + fn error_is_within_tolerance(&self, other: &Segment, distance: f32) -> bool { let (mut min, mut max) = ( f32::abs(distance) - TOLERANCE, f32::abs(distance) + TOLERANCE, diff --git a/text/Cargo.toml b/text/Cargo.toml new file mode 100644 index 00000000..5661db29 --- /dev/null +++ b/text/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "pathfinder_text" +version = "0.1.0" +authors = ["Patrick Walton "] +edition = "2018" + +[dependencies] +euclid = "0.19" +font-kit = "0.1" +lyon_path = "0.12" + +[dependencies.pathfinder_geometry] +path = "../geometry" + +[dependencies.pathfinder_renderer] +path = "../renderer" + +[dependencies.skribo] +git = "https://github.com/linebender/skribo.git" +rev = "f759c2d2c188b668bce998179f03b6319835353e" diff --git a/text/src/lib.rs b/text/src/lib.rs new file mode 100644 index 00000000..9a8cb5b8 --- /dev/null +++ b/text/src/lib.rs @@ -0,0 +1,217 @@ +// pathfinder/text/src/lib.rs +// +// Copyright © 2019 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::{Angle, Point2D, Vector2D}; +use font_kit::error::GlyphLoadingError; +use font_kit::hinting::HintingOptions; +use font_kit::loader::Loader; +use lyon_path::builder::{FlatPathBuilder, PathBuilder}; +use pathfinder_geometry::basic::point::Point2DF32; +use pathfinder_geometry::basic::transform2d::Transform2DF32; +use pathfinder_geometry::outline::{Contour, Outline}; +use pathfinder_geometry::stroke::OutlineStrokeToFill; +use pathfinder_renderer::scene::{PaintId, PathObject, Scene}; +use skribo::{FontCollection, Layout, TextStyle}; +use std::mem; + +pub trait SceneExt { + // TODO(pcwalton): Support stroked glyphs. + fn push_glyph(&mut self, + font: &F, + glyph_id: u32, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError> + where F: Loader; + + fn push_layout(&mut self, + layout: &Layout, + style: &TextStyle, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError>; + + fn push_text(&mut self, + text: &str, + style: &TextStyle, + collection: &FontCollection, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError>; +} + +impl SceneExt for Scene { + #[inline] + fn push_glyph(&mut self, + font: &F, + glyph_id: u32, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError> + where F: Loader { + let mut outline_builder = OutlinePathBuilder::new(transform); + font.outline(glyph_id, hinting_options, &mut outline_builder)?; + let mut outline = outline_builder.build(); + + if let TextRenderMode::Stroke(stroke_width) = render_mode { + let mut stroke_to_fill = OutlineStrokeToFill::new(outline, stroke_width); + stroke_to_fill.offset(); + outline = stroke_to_fill.outline; + } + + self.push_object(PathObject::new(outline, paint_id, String::new())); + Ok(()) + } + + fn push_layout(&mut self, + layout: &Layout, + style: &TextStyle, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError> { + for glyph in &layout.glyphs { + let offset = Point2DF32::new(glyph.offset.x, glyph.offset.y); + let font = &*glyph.font.font; + // FIXME(pcwalton): Cache this! + let scale = style.size / (font.metrics().units_per_em as f32); + let scale = Point2DF32::new(scale, -scale); + let transform = + Transform2DF32::from_scale(&scale).post_mul(transform).post_translate(offset); + self.push_glyph(font, + glyph.glyph_id, + &transform, + render_mode, + hinting_options, + paint_id)?; + } + Ok(()) + } + + #[inline] + fn push_text(&mut self, + text: &str, + style: &TextStyle, + collection: &FontCollection, + transform: &Transform2DF32, + render_mode: TextRenderMode, + hinting_options: HintingOptions, + paint_id: PaintId) + -> Result<(), GlyphLoadingError> { + let layout = skribo::layout(style, collection, text); + self.push_layout(&layout, style, &transform, render_mode, hinting_options, paint_id) + } +} + +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum TextRenderMode { + Fill, + Stroke(f32), +} + +struct OutlinePathBuilder { + outline: Outline, + current_contour: Contour, + transform: Transform2DF32, +} + +impl OutlinePathBuilder { + fn new(transform: &Transform2DF32) -> OutlinePathBuilder { + OutlinePathBuilder { + outline: Outline::new(), + current_contour: Contour::new(), + transform: *transform, + } + } + + fn flush_current_contour(&mut self) { + if !self.current_contour.is_empty() { + self.outline.push_contour(mem::replace(&mut self.current_contour, Contour::new())); + } + } + + fn convert_point(&self, point: Point2D) -> Point2DF32 { + self.transform.transform_point(&Point2DF32::new(point.x, point.y)) + } +} + +impl PathBuilder for OutlinePathBuilder { + fn quadratic_bezier_to(&mut self, ctrl: Point2D, to: Point2D) { + let (ctrl, to) = (self.convert_point(ctrl), self.convert_point(to)); + self.current_contour.push_quadratic(ctrl, to); + } + + fn cubic_bezier_to(&mut self, ctrl0: Point2D, ctrl1: Point2D, to: Point2D) { + let (ctrl0, ctrl1) = (self.convert_point(ctrl0), self.convert_point(ctrl1)); + let to = self.convert_point(to); + self.current_contour.push_cubic(ctrl0, ctrl1, to); + } + + fn arc(&mut self, + _center: Point2D, + _radii: Vector2D, + _sweep_angle: Angle, + _x_rotation: Angle) { + // TODO(pcwalton): Arcs. + } +} + +impl FlatPathBuilder for OutlinePathBuilder { + type PathType = Outline; + + fn move_to(&mut self, to: Point2D) { + self.flush_current_contour(); + let to = self.convert_point(to); + self.current_contour.push_endpoint(to); + } + + fn line_to(&mut self, to: Point2D) { + let to = self.convert_point(to); + self.current_contour.push_endpoint(to); + } + + fn close(&mut self) { + self.current_contour.close(); + } + + fn current_position(&self) -> Point2D { + if self.current_contour.is_empty() { + return Point2D::new(0.0, 0.0) + } + + let point_index = if self.current_contour.is_closed() { + 0 + } else { + self.current_contour.len() - 1 + }; + + let point = self.current_contour.position_of(point_index); + Point2D::new(point.x(), point.y()) + } + + fn build(mut self) -> Outline { + self.flush_current_contour(); + self.outline + } + + fn build_and_reset(&mut self) -> Outline { + self.flush_current_contour(); + mem::replace(&mut self.outline, Outline::new()) + } +}