diff --git a/Cargo.lock b/Cargo.lock index 596dd228d6..483998b26e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "adler32" version = "1.0.4" @@ -74,9 +80,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii-canvas" @@ -140,7 +146,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.9.2", "cexpr", "clang-sys", "itertools", @@ -178,9 +184,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" dependencies = [ "serde", ] @@ -222,9 +228,23 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "bytemuck" -version = "1.2.0" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431" +checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] [[package]] name = "byteorder" @@ -393,6 +413,15 @@ dependencies = [ "objc", ] +[[package]] +name = "color" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae467d04a8a8aea5d9a49018a6ade2e4221d92968e8ce55a48c0b1164e5f698" +dependencies = [ + "bytemuck", +] + [[package]] name = "compositor" version = "0.1.0" @@ -714,6 +743,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "dlib" version = "0.5.0" @@ -767,6 +807,12 @@ dependencies = [ "log", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.9" @@ -808,6 +854,23 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fearless_simd" +version = "0.2.0" +source = "git+https://github.com/linebender/fearless_simd?rev=3d1a77c#3d1a77cfb4515c0da307d50dc782c08840b90c70" +dependencies = [ + "bytemuck", +] + [[package]] name = "firefox-on-glean" version = "0.1.0" @@ -827,7 +890,7 @@ dependencies = [ "cfg-if 1.0.0", "crc32fast", "libc", - "miniz_oxide", + "miniz_oxide 0.5.1", ] [[package]] @@ -836,6 +899,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "font-loader" version = "0.11.0" @@ -849,6 +918,48 @@ dependencies = [ "winapi", ] +[[package]] +name = "font-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-cache-parser" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f8afb20c8069fd676d27b214559a337cc619a605d25a87baa90b49a06f3b18" +dependencies = [ + "bytemuck", + "thiserror", +] + +[[package]] +name = "fontique" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39f97079e1293b8c1e9fb03a2875d328bd2ee8f3b95ce62959c0acc04049c708" +dependencies = [ + "bytemuck", + "fontconfig-cache-parser", + "hashbrown 0.15.5", + "icu_locid", + "memmap2 0.9.7", + "objc2", + "objc2-core-foundation", + "objc2-core-text", + "objc2-foundation", + "peniko", + "read-fonts", + "roxmltree", + "smallvec", + "windows", + "windows-core", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -1197,6 +1308,17 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -1221,6 +1343,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", +] + [[package]] name = "id-arena" version = "2.2.1" @@ -1255,7 +1389,7 @@ dependencies = [ "num-iter", "num-rational", "num-traits", - "png", + "png 0.16.2", ] [[package]] @@ -1345,6 +1479,17 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "kurbo" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + [[package]] name = "lalrpop" version = "0.19.8" @@ -1544,6 +1689,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + [[package]] name = "lock_api" version = "0.4.7" @@ -1556,9 +1707,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "mach2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] [[package]] name = "malloc_buf" @@ -1607,6 +1767,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -1653,6 +1822,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "0.8.2" @@ -1874,6 +2053,50 @@ dependencies = [ "malloc_buf", ] +[[package]] +name = "objc2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ba833d4a1cb1aac330f8c973fd92b6ff1858e4aef5cdd00a255eefb28022fb5" +dependencies = [ + "bitflags 2.9.2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.9.2", + "objc2", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -1992,6 +2215,18 @@ dependencies = [ "synstructure 0.13.1", ] +[[package]] +name = "peniko" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f9529efd019889b2a205193c14ffb6e2839b54ed9d2720674f10f4b04d87ac9" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "smallvec", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -2068,6 +2303,19 @@ dependencies = [ "inflate", ] +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2215,6 +2463,16 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "read-fonts" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d" +dependencies = [ + "bytemuck", + "font-types", +] + [[package]] name = "redox_syscall" version = "0.2.13" @@ -2317,7 +2575,7 @@ checksum = "2c6d906922d99c677624d2042a93f89b2b7df0f6411032237d5d99a602c2487c" dependencies = [ "arrayref", "bincode", - "bitflags 2.4.2", + "bitflags 2.9.2", "byteorder", "id-arena", "lazy_static", @@ -2338,7 +2596,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beceb6f7bf81c73e73aeef6dd1356d9a1b2b4909e1f0fc3e59b034f9572d7b7f" dependencies = [ "base64", - "bitflags 2.4.2", + "bitflags 2.9.2", "serde", "serde_derive", "unicode-ident", @@ -2357,6 +2615,12 @@ dependencies = [ "text-size", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2375,7 +2639,7 @@ version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.9.2", "errno", "libc", "linux-raw-sys", @@ -2518,17 +2782,33 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "siphasher" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +[[package]] +name = "skrifa" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607" +dependencies = [ + "bytemuck", + "read-fonts", +] + [[package]] name = "smallvec" -version = "1.10.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] @@ -2550,7 +2830,7 @@ dependencies = [ "dlib", "lazy_static", "log", - "memmap2", + "memmap2 0.3.1", "nix", "pkg-config", "wayland-client", @@ -2753,6 +3033,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", +] + [[package]] name = "tinyvec" version = "1.5.1" @@ -2962,6 +3251,29 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vello_common" +version = "0.0.1" +source = "git+https://github.com/linebender/vello?rev=931e6fdc135507486324adec019edffa2f70a203#931e6fdc135507486324adec019edffa2f70a203" +dependencies = [ + "bytemuck", + "fearless_simd", + "log", + "peniko", + "png 0.17.16", + "skrifa", + "smallvec", +] + +[[package]] +name = "vello_cpu" +version = "0.0.1" +source = "git+https://github.com/linebender/vello?rev=931e6fdc135507486324adec019edffa2f70a203#931e6fdc135507486324adec019edffa2f70a203" +dependencies = [ + "bytemuck", + "vello_common", +] + [[package]] name = "version_check" version = "0.9.1" @@ -3144,7 +3456,7 @@ version = "0.66.0" dependencies = [ "allocator-api2", "bincode", - "bitflags 2.4.2", + "bitflags 2.9.2", "build-parallel", "byteorder", "derive_more", @@ -3162,7 +3474,7 @@ dependencies = [ "num-traits", "peek-poke", "plane-split", - "png", + "png 0.16.2", "rand 0.4.6", "rayon", "ron", @@ -3170,7 +3482,6 @@ dependencies = [ "smallvec", "svg_fmt", "swgl", - "time", "topological-sort", "tracy-rs", "webrender_api", @@ -3199,16 +3510,18 @@ name = "webrender_api" version = "0.66.0" dependencies = [ "app_units", - "bitflags 2.4.2", + "bitflags 2.9.2", "byteorder", "crossbeam-channel", "euclid", + "libc", + "mach2", "malloc_size_of_derive", "peek-poke", "serde", "serde_bytes", "serde_derive", - "time", + "windows-sys 0.59.0", "wr_malloc_size_of", ] @@ -3216,7 +3529,7 @@ dependencies = [ name = "webrender_build" version = "0.0.2" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.9.2", "lazy_static", "serde", ] @@ -3284,6 +3597,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -3302,6 +3679,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -3476,6 +3862,7 @@ dependencies = [ "env_logger", "euclid", "firefox-on-glean", + "fontique", "freetype", "fxhash", "gleam", @@ -3485,11 +3872,14 @@ dependencies = [ "libc", "log", "malloc_size_of_derive", + "memmap2 0.9.7", "objc", "rayon", "serde", + "skrifa", "smallvec", "tracy-rs", + "vello_cpu", "webrender_api", "winit", "wr_malloc_size_of", @@ -3539,6 +3929,12 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.2.0" diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 87632a9b78..a8922a04e8 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -9,7 +9,7 @@ build = "build.rs" edition = "2018" [features] -default = ["static_freetype"] +default = ["fontations", "static_freetype"] profiler = ["tracy-rs/enable_profiler"] capture = ["api/serialize", "ron", "serde", "smallvec/serde", "etagere/serialization", "glyph_rasterizer/capture"] replay = ["api/deserialize", "ron", "serde", "smallvec/serde", "etagere/serialization", "glyph_rasterizer/replay"] @@ -17,6 +17,7 @@ display_list_stats = ["api/display_list_stats"] serialize_program = ["serde", "webrender_build/serialize_program"] dynamic_freetype = ["glyph_rasterizer/dynamic_freetype"] static_freetype = ["glyph_rasterizer/static_freetype"] +fontations = ["glyph_rasterizer/fontations"] leak_checks = [] gecko = ["firefox-on-glean", "glean", "glyph_rasterizer/gecko"] sw_compositor = ["swgl"] diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index 316aa8ebeb..7e0fb01947 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -12,6 +12,7 @@ nightly = ["euclid/unstable", "serde/unstable"] serialize = [] deserialize = [] display_list_stats = [] +fontations = [] [dependencies] app_units = "0.7.3" diff --git a/webrender_api/src/font.rs b/webrender_api/src/font.rs index 40807581f8..1b41402b36 100644 --- a/webrender_api/src/font.rs +++ b/webrender_api/src/font.rs @@ -5,8 +5,6 @@ use peek_poke::PeekPoke; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; -#[cfg(not(any(target_os = "macos", target_os = "ios")))] -use std::path::PathBuf; use std::sync::Arc; // local imports use crate::IdNamespace; @@ -55,7 +53,7 @@ impl FontSize { #[cfg(not(any(target_os = "macos", target_os = "ios")))] #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct NativeFontHandle { - pub path: PathBuf, + pub path: std::path::PathBuf, pub index: u32, } diff --git a/wr_glyph_rasterizer/Cargo.toml b/wr_glyph_rasterizer/Cargo.toml index dedf5a2188..48b98f7c8e 100644 --- a/wr_glyph_rasterizer/Cargo.toml +++ b/wr_glyph_rasterizer/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" default = ["static_freetype"] dynamic_freetype = [] static_freetype = ["freetype/freetype-sys"] +fontations = ["vello_cpu", "fontique", "skrifa", "memmap2", "api/fontations"] capture = ["api/serialize", "serde", "smallvec/serde"] replay = ["api/deserialize", "serde", "smallvec/serde"] gecko = ["firefox-on-glean", "glean"] @@ -28,6 +29,10 @@ fxhash = "0.2.1" glean = { workspace = true, optional = true } firefox-on-glean = { version = "0.1.0", optional = true } serde = { optional = true, version = "1.0", features = ["serde_derive"] } +vello_cpu = { git = "https://github.com/linebender/vello", rev = "931e6fdc135507486324adec019edffa2f70a203", optional = true } +fontique = { version = "0.5.0", optional = true } +skrifa = { version = "0.31", optional = true } +memmap2 = { version = "0.9", optional = true } [dev-dependencies] env_logger = { version = "0.10", default-features = false } diff --git a/wr_glyph_rasterizer/src/lib.rs b/wr_glyph_rasterizer/src/lib.rs index 3cf95d7c31..bdbf984f18 100644 --- a/wr_glyph_rasterizer/src/lib.rs +++ b/wr_glyph_rasterizer/src/lib.rs @@ -26,6 +26,7 @@ extern crate malloc_size_of_derive; extern crate tracy_rs; #[macro_use] extern crate log; +#[allow(unused_imports)] #[macro_use] extern crate lazy_static; #[macro_use] @@ -38,18 +39,26 @@ extern crate serde; extern crate malloc_size_of; pub mod platform { - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(all(any(target_os = "ios", target_os = "macos"), not(feature = "fontations")))] pub use crate::platform::macos::font; #[cfg(any(target_os = "android", all(unix, not(any(target_os = "ios", target_os = "macos")))))] pub use crate::platform::unix::font; #[cfg(target_os = "windows")] pub use crate::platform::windows::font; - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(feature = "fontations")] + pub use crate::platform::fontations::font; + + #[cfg(feature = "fontations")] + pub mod fontations { + pub mod font; + } + + #[cfg(all(any(target_os = "ios", target_os = "macos"), not(feature = "fontations")))] pub mod macos { pub mod font; } - #[cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios")))))] + #[cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios", feature = "fontations")))))] pub mod unix { pub mod font; } diff --git a/wr_glyph_rasterizer/src/platform/fontations/font.rs b/wr_glyph_rasterizer/src/platform/fontations/font.rs new file mode 100644 index 0000000000..f61a3c8688 --- /dev/null +++ b/wr_glyph_rasterizer/src/platform/fontations/font.rs @@ -0,0 +1,343 @@ +use std::{path::PathBuf, sync::Arc}; +use api::{FontInstanceKey, FontKey, GlyphDimensions, NativeFontHandle}; +use memmap2::Mmap; +use skrifa::charmap::Charmap; +use skrifa::instance::Location; +use skrifa::metrics::GlyphMetrics; +use skrifa::outline::{HintingInstance}; +use skrifa::prelude::{LocationRef, Size}; +use skrifa::raw::{FileRef}; +use skrifa::{GlyphId}; +use vello_cpu::peniko::{self, Blob}; +use vello_cpu::{Level, PaintType, Pixmap, RenderContext, RenderMode, RenderSettings}; + +use crate::{ + FastHashMap, FontInstance, GlyphFormat, GlyphKey, GlyphRasterError, GlyphRasterResult, + RasterizedGlyph, +}; + +type PenikoFont = vello_cpu::peniko::Font; + +// struct CachedFont { +// pub data: Arc + Send + Sync>, +// pub index: u32, +// pub settings: FontRenderSettings, +// } + +// #[derive(Default)] +// struct FontRenderSettings { +// pub font_size: f32, +// } + +#[cfg(any(target_os = "macos", target_os = "ios"))] +struct SimpleFontHandle { + pub path: PathBuf, + pub index: u32, + pub data: Mmap, +} + +impl SimpleFontHandle { + pub(crate) fn new(path: PathBuf, index: u32) -> Self { + let file = std::fs::File::open(&path).unwrap(); + let mapped = unsafe { Mmap::map(&file) }.unwrap(); + Self { + path, + index, + data: mapped, + } + } +} + +impl From for SimpleFontHandle { + #[cfg(not(any(target_os = "macos", target_os = "ios")))] + fn from(native: NativeFontHandle) -> Self { + let file = std::fs::File::open(&native.path).unwrap(); + let mapped = unsafe { Mmap::map(&file) }.unwrap(); + + SimpleFontHandle { + path: native.path, + index: native.index, + data: mapped, + } + } + + #[cfg(any(target_os = "macos", target_os = "ios"))] + fn from(native: NativeFontHandle) -> Self { + let file = std::fs::File::open(&native.path).unwrap(); + let mapped = unsafe { Mmap::map(&file) }.unwrap(); + let font_file = FileRef::new(&mapped).unwrap(); + let index = ttc_index_from_postscript_name(font_file, &native.name); + + SimpleFontHandle { + path: PathBuf::from(native.path), + index, + data: mapped, + } + } +} + +trait RasterContext { + // Static fns + fn distribute_across_threads() -> bool; + fn new() -> Self; + fn begin_rasterize(font: &FontInstance); + fn end_rasterize(font: &FontInstance); + fn prepare_font(font: &mut FontInstance); + + // Font registration + fn add_raw_font(&mut self, font_key: &FontKey, bytes: Arc>, index: u32); + fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: NativeFontHandle); + fn delete_font(&mut self, font_key: &FontKey); + fn delete_font_instance(&mut self, instance: &FontInstance); + + // Methods + fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option; + fn get_glyph_dimensions( + &mut self, + font: &FontInstance, + key: &GlyphKey, + ) -> Option; + fn rasterize_glyph(&mut self, font: &FontInstance, key: &GlyphKey) -> GlyphRasterResult; +} + +pub struct FontContext { + font_cache: FastHashMap, + hinting_instance_cache: FastHashMap, +} + +impl FontContext { + // Static fns + pub fn distribute_across_threads() -> bool { + true + } + pub fn new() -> FontContext { + FontContext { + font_cache: Default::default(), + hinting_instance_cache: Default::default(), + } + } + pub fn begin_rasterize(font: &FontInstance) { + // TODO: apply instance properties + } + pub fn end_rasterize(font: &FontInstance) { + // TODO: clear instance properties + } + + pub fn prepare_font(font: &mut FontInstance) { + // Perhaps not needed for fontations? + } + pub fn delete_font_instance(&mut self, instance: &FontInstance) { + self.hinting_instance_cache + .remove(&instance.base.instance_key); + } + + pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: Arc>, index: u32) { + let font = PenikoFont { + data: Blob::new(bytes), + index: index, + }; + self.font_cache.insert(*font_key, font); + } + pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: NativeFontHandle) { + let handle = SimpleFontHandle::from(native_font_handle); + let font = PenikoFont { + data: Blob::new(Arc::new(handle.data)), + index: handle.index, + }; + self.font_cache.insert(*font_key, font); + } + pub fn delete_font(&mut self, font_key: &FontKey) { + self.font_cache.remove(font_key); + } + + // Methods + pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option { + let font = self.font_cache.get(&font_key)?; + let data: &[u8] = font.data.as_ref().as_ref(); + let font_ref = skrifa::FontRef::from_index(data, font.index).ok()?; + + let char_map = Charmap::new(&font_ref); + let glyph_id = char_map.map(ch)?; + + Some(glyph_id.to_u32()) + } + + pub fn get_glyph_dimensions( + &mut self, + font_instance: &FontInstance, + key: &GlyphKey, + ) -> Option { + let font = self.font_cache.get(&font_instance.font_key)?; + let data: &[u8] = font.data.as_ref().as_ref(); + let font_ref = skrifa::FontRef::from_index(data, font.index).ok()?; + + // TODO: set variation axis + // + // let location = font_ref.axes().location( + // variations + // .iter() + // .map(|v| (Tag::new(&v.tag.to_le_bytes()), v.value)), + // ); + // let location_ref = LocationRef::from(&location); + let location = Location::new(0); + let location_ref = LocationRef::from(&location); + + let font_size = font_instance.size.to_f32_px(); + let (x_scale, y_scale) = font_instance + .transform + .compute_scale() + .unwrap_or((1.0, 1.0)); + let scale = ((x_scale + y_scale) / 2.0) as f32; + let font_size = font_size * scale; + + let glyph_metrics = GlyphMetrics::new(&font_ref, Size::new(font_size), location_ref); + let advance = glyph_metrics.advance_width(GlyphId::new(key.index()))?; + let bounds = glyph_metrics.bounds(GlyphId::new(key.index()))?; + + dbg!(font_size); + dbg!(bounds); + dbg!(x_scale, y_scale); + dbg!(font_instance.flags); + + Some(GlyphDimensions { + advance, + + // TODO: investigate why Skrifa provides f32 but WebRender expects i32 + // TODO: use hinted metrics + left: bounds.x_min.floor() as i32, + top: bounds.y_max.ceil() as i32, + width: (bounds.x_max - bounds.x_min).ceil() as i32, + height: (bounds.y_max - bounds.y_min).ceil() as i32, + }) + } + pub fn rasterize_glyph( + &mut self, + font_instance: &FontInstance, + key: &GlyphKey, + ) -> GlyphRasterResult { + let dimensions = self + .get_glyph_dimensions(font_instance, key) + .ok_or(GlyphRasterError::LoadFailed)?; + let font = self + .font_cache + .get(&font_instance.font_key) + .ok_or(GlyphRasterError::LoadFailed)?; + + // Handle zero-sized glyphs (e.g. space chars) + if dimensions.width == 0 || dimensions.height == 0 { + return Err(GlyphRasterError::LoadFailed); + } + + // let data: &[u8] = font.data.as_ref().as_ref(); + // let font_ref = skrifa::FontRef::from_index(data, font.index).ok().unwrap(); + + // let hinting_instance = self + // .hinting_instance_cache + // .entry(font_instance.instance_key) + // .or_insert_with(|| { + // let outline_glyphs = font_ref.outline_glyphs(); + // let size = skrifa::instance::Size::new(font_instance.size.to_f32_px()); + // let location_ref = LocationRef::default(); + // let options = HintingOptions::default(); + // HintingInstance::new(&outline_glyphs, size, location_ref, options).unwrap() + // }); + // let draw_settings = DrawSettings::hinted(hinting_instance, false); + + let width = (dimensions.left + dimensions.width) as u16; + let height = dimensions.height as u16; + + // TODO: reuse RenderContext between glyphs + let render_settings = RenderSettings { + render_mode: RenderMode::OptimizeSpeed, + num_threads: 1, + level: Level::new(), + }; + let mut render_context = RenderContext::new_with(width, height, render_settings); + let color = peniko::Color::from_rgba8( + font_instance.color.r, + font_instance.color.g, + font_instance.color.b, + font_instance.color.a, + ); + render_context.set_paint(PaintType::Solid(color)); + + let font_size = font_instance.size.to_f32_px(); + let (x_scale, y_scale) = font_instance + .transform + .compute_scale() + .unwrap_or((1.0, 1.0)); + let scale = ((x_scale + y_scale) / 2.0) as f32; + let font_size = font_size * scale; + + render_context + .glyph_run(&font) + .font_size(font_size) + .hint(true) + .fill_glyphs(std::iter::once(vello_cpu::Glyph { + x: 0.0, + y: dimensions.top as f32 + 1.0, + id: key.index(), + })); + render_context.flush(); + + let mut buffer = vec![0; width as usize * height as usize * 4]; + render_context.render_to_buffer(&mut buffer, width, height, RenderMode::OptimizeSpeed); + + // DEBUG: Write out PNG file of glyphs to $CWD/glyphs/glyph_id.png + // + // let mut pixmap = Pixmap::new(width, height); + // render_context.render_to_pixmap(&mut pixmap); + // let buffer = pixmap.data_as_u8_slice().to_vec(); + // let png = pixmap.into_png().unwrap(); + // std::fs::write(format!("./glyphs/{}.png", key.index()), png).unwrap(); + + Ok(RasterizedGlyph { + top: dimensions.top as f32, + left: dimensions.left as f32, + width: width as i32, + height: height as i32, + scale: 1.0 / scale, + format: GlyphFormat::Alpha, + bytes: buffer, + }) + } +} + +/// CoreText font enumaration gives us a postscript name rather than an index. +/// This functions maps from postscript name to index +#[cfg(any(target_os = "macos", target_os = "ios"))] +fn ttc_index_from_postscript_name(font_file: FileRef<'_>, postscript_name: &str) -> u32 { + use skrifa::raw::{FileRef, TableProvider as _}; + use skrifa::raw::types::NameId; + + let index = match font_file { + FileRef::Font(_) => 0, + FileRef::Collection(collection) => 'idx: { + for i in 0 .. collection.len() { + let font = collection.get(i).unwrap(); + let name_table = font.name().unwrap(); + if name_table + .name_record() + .iter() + .filter(|record| record.name_id() == NameId::POSTSCRIPT_NAME) + .any(|record| { + record + .string(name_table.string_data()) + .unwrap() + .chars() + .eq(postscript_name.chars()) + }) + { + break 'idx i; + } + } + + panic!( + "Font with postscript_name {} not found in collection", + postscript_name + ); + } + }; + + index +}