diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c25a9c68dc..419a06b700 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,6 +55,33 @@ jobs: - run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev - run: cargo build --workspace + # The text backend features: Parley (the default), winkin alone, both (Parley wins), + # and neither, which must fail to compile. + check-text-backends: + name: "Check text backends" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev + - name: Parley (default) + run: cargo check -p blitz-dom -p blitz-paint -p blitz -p wpt + - name: winkin alone + run: | + cargo check -p blitz-dom --no-default-features --features winkin,system-fonts,svg + cargo check -p blitz-paint --no-default-features --features winkin,svg + cargo check -p blitz --no-default-features --features winkin,net + cargo check -p browser --no-default-features --features winkin,hybrid + cargo check -p wpt --no-default-features --features winkin,cpu + - name: Both (Parley is used) + run: cargo test -p blitz-dom --features winkin --lib text::tests + - name: Neither fails to compile + run: | + if cargo check -p blitz-dom --no-default-features --features svg 2> neither.log; then + echo "blitz-dom built without a text backend"; exit 1 + fi + grep -q "Enable one of the \`parley\` or \`winkin\` features" neither.log + # wasm_hello is a standalone workspace; seven_guis and todomvc are workspace # members with a [lib] crate-type = ["cdylib"] target for wasm. build-wasm-examples: @@ -70,9 +97,9 @@ jobs: run: cargo build --target wasm32-unknown-unknown working-directory: examples/wasm_hello - name: Build seven_guis (wasm) - run: cargo build -p seven_guis --lib --target wasm32-unknown-unknown --no-default-features --features hybrid + run: cargo build -p seven_guis --lib --target wasm32-unknown-unknown --no-default-features --features hybrid,parley - name: Build todomvc (wasm) - run: cargo build -p todomvc --lib --target wasm32-unknown-unknown --no-default-features --features hybrid + run: cargo build -p todomvc --lib --target wasm32-unknown-unknown --no-default-features --features hybrid,parley fmt: name: Rustfmt @@ -96,7 +123,7 @@ jobs: components: clippy - run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev - run: cargo clippy --workspace -- -D warnings - - run: cargo clippy -p blitz-dom --no-default-features --features svg,woff,accessibility,system-fonts,file-input,custom-widget --all-targets -- -D warnings + - run: cargo clippy -p blitz-dom --no-default-features --features parley,svg,woff,accessibility,system-fonts,file-input,custom-widget --all-targets -- -D warnings ci-scripts: name: "Test CI scripts" diff --git a/.github/workflows/wpt.yml b/.github/workflows/wpt.yml index 9183f4776c..d377253c93 100644 --- a/.github/workflows/wpt.yml +++ b/.github/workflows/wpt.yml @@ -24,7 +24,7 @@ jobs: wpt: name: "Run WPT Tests" runs-on: warp-ubuntu-latest-arm64-16x - timeout-minutes: 15 + timeout-minutes: 25 steps: - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable @@ -43,9 +43,9 @@ jobs: - name: Clone WPT tests run: git clone --depth 1 --revision "$(cat ./wpt/WPT_COMMIT)" https://github.com/web-platform-tests/wpt ./wpt/tests - name: Build WPT runner - run: cargo build -rp wpt + run: cargo build -rp wpt --no-default-features --features cpu,winkin - name: Run WPT tests - run: cargo run -rp wpt css svg + run: cargo run -rp wpt --no-default-features --features cpu,winkin css svg - name: Compress report (zstd) run: zstd -22 --ultra -o ./wpt/output/wptreport.json.zst ./wpt/output/wptreport.json - uses: actions/upload-artifact@v7 diff --git a/Cargo.lock b/Cargo.lock index 7474b5a316..70510e071b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,7 +272,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -283,7 +283,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -314,7 +314,7 @@ dependencies = [ "anyrender", "image", "peniko", - "read-fonts", + "read-fonts 0.41.0", "serde", "serde_json", "sha2", @@ -910,6 +910,7 @@ dependencies = [ "cursor-icon", "debug_timer 0.1.3", "euclid", + "fontwich", "html-escape", "icu_casemap", "icu_locale_core", @@ -921,6 +922,7 @@ dependencies = [ "linebender_resource_handle", "markup5ever", "objc2 0.6.5", + "parlance", "parley", "percent-encoding", "rayon", @@ -941,6 +943,7 @@ dependencies = [ "url", "usvg", "web-time", + "winkin", "writeable", "wuff", ] @@ -1021,7 +1024,6 @@ dependencies = [ "color", "euclid", "kurbo", - "parley", "peniko", "skrifa", "smallvec", @@ -1085,6 +1087,7 @@ dependencies = [ "dioxus-core", "dioxus-native-dom", "keyboard-types 0.7.0", + "kurbo", "markup5ever", "stylo", "taffy", @@ -1784,7 +1787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2783,7 +2786,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3077,7 +3080,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3305,7 +3308,7 @@ dependencies = [ "objc2-core-text", "objc2-foundation 0.3.2", "parlance", - "read-fonts", + "read-fonts 0.41.0", "roxmltree 0.21.1", "smallvec", "windows", @@ -3313,6 +3316,24 @@ dependencies = [ "yeslogic-fontconfig-sys", ] +[[package]] +name = "fontwich" +version = "0.0.1" +source = "git+https://github.com/dfrg/winkin?rev=11bc928c7cf92e1155ac4a0cd14773ae801b42fc#11bc928c7cf92e1155ac4a0cd14773ae801b42fc" +dependencies = [ + "hashbrown 0.17.1", + "memmap2 0.9.11", + "objc2-core-foundation", + "objc2-core-text", + "parlance", + "read-fonts 0.45.0", + "roxmltree 0.21.1", + "spin", + "windows", + "windows-core", + "yeslogic-fontconfig-sys", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -3808,8 +3829,22 @@ checksum = "c03d949a14aa089bbb282f7dd76a498a7f684428e4257202efc119ec010376f9" dependencies = [ "bitflags 2.13.2", "bytemuck", - "read-fonts", + "read-fonts 0.41.0", + "smallvec", +] + +[[package]] +name = "harfrust" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86aa776d6d32b072119e1f1650f4db843ff4382a4aaa6a2c9c4e35703cd377cb" +dependencies = [ + "bitflags 2.13.2", + "bytemuck", + "core_maths", + "read-fonts 0.45.0", "smallvec", + "spin", ] [[package]] @@ -5415,7 +5450,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -6080,7 +6115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b74c0d373e462e504ad4436710a39f099e18e848e1ee711f70cd2dcd5a69b290" dependencies = [ "fontique", - "harfrust", + "harfrust 0.12.0", "hashbrown 0.17.1", "icu_locale_core", "icu_normalizer", @@ -6538,13 +6573,24 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "rand_chacha", + "rand_chacha 0.9.0", "rand_core 0.9.5", ] @@ -6559,6 +6605,16 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_chacha" version = "0.9.0" @@ -6569,6 +6625,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + [[package]] name = "rand_core" version = "0.9.5" @@ -6618,7 +6683,7 @@ dependencies = [ "paste", "profiling", "rand 0.9.5", - "rand_chacha", + "rand_chacha 0.9.0", "simd_helpers", "thiserror 2.0.21", "v_frame", @@ -6725,6 +6790,19 @@ dependencies = [ "once_cell", ] +[[package]] +name = "read-fonts" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5b7bed3d16ab428d8fa533640ab805ff50e7ad8a4d00649de1259e70023282" +dependencies = [ + "bytemuck", + "core_maths", + "font-types 0.12.6", + "once_cell", + "yoke", +] + [[package]] name = "redox_event" version = "0.4.8" @@ -6993,7 +7071,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -7006,7 +7084,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -7138,12 +7216,12 @@ dependencies = [ [[package]] name = "selectors" version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8322aebea94a6cc288ff884e8a49bdbceef60206c400c6c46d22e62fc4fd91a6" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "bitflags 2.13.2", "cssparser", "derive_more", + "hashbrown 0.17.1", "log", "new_debug_unreachable", "precomputed-hash", @@ -7278,8 +7356,7 @@ dependencies = [ [[package]] name = "servo_arc" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eceb519ec34d8290aaf6e46f435102f2bfa63f22b05a144fb16ab266d3b198" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "serde", "stable_deref_trait", @@ -7463,7 +7540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68" dependencies = [ "bytemuck", - "read-fonts", + "read-fonts 0.41.0", ] [[package]] @@ -7577,7 +7654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -7625,6 +7702,12 @@ dependencies = [ "softbuffer", ] +[[package]] +name = "spin" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0134f9043ed38b087ac4f7d4af44c79e2c9e5094421fe3164f435ce585953b10" + [[package]] name = "spirv" version = "0.4.0+sdk-1.4.341.0" @@ -7739,8 +7822,7 @@ dependencies = [ [[package]] name = "stylo" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a255e46af2478628c48daab3774090caabd7812b1dd3ca98801c2b9c53491ed" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "app_units", "arrayvec", @@ -7751,6 +7833,7 @@ dependencies = [ "derive_more", "encoding_rs", "euclid", + "hashbrown 0.17.1", "icu_segmenter", "indexmap", "itertools 0.14.0", @@ -7765,6 +7848,7 @@ dependencies = [ "num_cpus", "parking_lot", "precomputed-hash", + "rand 0.8.8", "rayon", "rayon-core", "rustc-hash 2.1.3", @@ -7796,8 +7880,7 @@ dependencies = [ [[package]] name = "stylo_atoms" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1771588fd747ef16f8b1990061b6f37c7d3251a0f9b74f405a44c0c5fb8966" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "string_cache 0.11.0", "string_cache_codegen", @@ -7806,8 +7889,7 @@ dependencies = [ [[package]] name = "stylo_derive" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee5c550c2e00a0b3c046bef84a9ee217e04e7c014142eeb96f9e48781c5cfd3" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "darling 0.20.11", "proc-macro2", @@ -7819,8 +7901,7 @@ dependencies = [ [[package]] name = "stylo_dom" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9febcb03f2b669ef06b3e8a5209e6280971ed55cecf83fbf3c0562fcf2aa2ec6" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "bitflags 2.13.2", "stylo_malloc_size_of", @@ -7829,12 +7910,12 @@ dependencies = [ [[package]] name = "stylo_malloc_size_of" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ed69d55ee907599f093221004a28371925236f09f20961963020abf38bab6a" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "app_units", "cssparser", "euclid", + "hashbrown 0.17.1", "parking_lot", "selectors", "servo_arc", @@ -7848,8 +7929,7 @@ dependencies = [ [[package]] name = "stylo_static_prefs" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6767c48a1590461db79f8b434ccc5a2d65600a3b716751f7999b35ccead1e024" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "toml", ] @@ -7867,8 +7947,7 @@ dependencies = [ [[package]] name = "stylo_traits" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645d6bfe40eb6e86ebe9f2d2adadcbced41bfa96175de7cb13d4d178d27bc83d" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "app_units", "bitflags 2.13.2", @@ -8057,7 +8136,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix 1.1.5", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -8092,7 +8171,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -8136,6 +8215,9 @@ name = "thin-vec" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6a4b9ba8738cb4a4f399d37e266becfd475e75eb73425b87a05a2f2039ba63e" +dependencies = [ + "serde", +] [[package]] name = "thiserror" @@ -8288,10 +8370,10 @@ checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "to_shmem" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf077da8dd01cc18453bd7d9bc3a945c262f5f344562e5f6deb3914b4dd6f14" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "cssparser", + "hashbrown 0.17.1", "servo_arc", "smallbitvec", "smallvec", @@ -8302,8 +8384,7 @@ dependencies = [ [[package]] name = "to_shmem_derive" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e91a023810fd2019648410d00eea13a71f21d849e71d6d9ed936fb8061174" +source = "git+https://github.com/dfrg/stylo?branch=style-more#58490d7b0b50cf915b510383512f1ce062dbd17b" dependencies = [ "darling 0.20.11", "proc-macro2", @@ -8662,7 +8743,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -8775,7 +8856,7 @@ dependencies = [ "data-url", "flate2", "fontdb", - "harfrust", + "harfrust 0.12.0", "imagesize", "kurbo", "log", @@ -9777,7 +9858,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9899,15 +9980,6 @@ 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-sys" version = "0.60.2" @@ -10354,6 +10426,23 @@ dependencies = [ "xkbcommon-dl", ] +[[package]] +name = "winkin" +version = "0.0.1" +source = "git+https://github.com/dfrg/winkin?rev=11bc928c7cf92e1155ac4a0cd14773ae801b42fc#11bc928c7cf92e1155ac4a0cd14773ae801b42fc" +dependencies = [ + "fontwich", + "harfrust 0.14.0", + "hashbrown 0.17.1", + "icu_casemap", + "icu_locale_core", + "icu_segmenter", + "parlance", + "read-fonts 0.45.0", + "spin", + "writeable", +] + [[package]] name = "winnow" version = "0.7.15" @@ -10403,7 +10492,6 @@ dependencies = [ "markup5ever", "os_info", "owo-colors", - "parley", "peniko", "png 0.17.16", "pollster", @@ -10442,7 +10530,7 @@ checksum = "cae90d1d9f6d1d36ef116b0b1e651a6d7c12ba925439d4d06ff9adc94662a3d8" dependencies = [ "font-types 0.12.6", "log", - "read-fonts", + "read-fonts 0.41.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9c084b32f2..5dab13f700 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ dioxus-native-dom = { version = "0.7.0", path = "./packages/dioxus-native-dom", debug_timer = { version = "0.1.2", path = "./packages/debug_timer" } accesskit_xplat = { version = "0.2", path = "./packages/accesskit_xplat", default-features = false } browser-persistence = { path = "./apps/browser/persistence" } -blitz-test-harness = { path = "./packages/blitz-test-harness" } +blitz-test-harness = { path = "./packages/blitz-test-harness", default-features = false } # Servo dependencies style = { version = "0.22.0", package = "stylo" } @@ -108,7 +108,15 @@ taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "6c2106e3df79493d30 "calc", "detailed_layout_info", ] } +# The font value types shared by the text backends, from Parley's release +parlance = { version = "0.1.1", default-features = false, features = ["std"] } parley = { version = "0.12", default-features = false, features = ["std"] } +# Its `dictionaries` feature, ICU's line and word dictionaries, is blitz-dom's +# `complex-scripts`. +winkin = { git = "https://github.com/dfrg/winkin", rev = "11bc928c7cf92e1155ac4a0cd14773ae801b42fc", default-features = false, features = ["std"] } +# The fonts winkin chooses from. Its `system` feature, the platform's font +# APIs, is blitz-dom's `system-fonts`. +fontwich = { git = "https://github.com/dfrg/winkin", rev = "11bc928c7cf92e1155ac4a0cd14773ae801b42fc", default-features = false, features = ["std"] } skrifa = { version = "0.44", default-features = false, features = [ "std", ] } # Should match parley and vello versions @@ -257,13 +265,17 @@ publish = false log-times = ["log-frame-times", "log-phase-times"] log-frame-times = ["dioxus-native/log-frame-times"] log-phase-times = ["dioxus-native/log-phase-times"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +default = ["parley"] +parley = ["blitz-dom/parley", "blitz-paint/parley", "dioxus-native/parley"] +winkin = ["blitz-dom/winkin", "blitz-paint/winkin", "dioxus-native/winkin"] [dev-dependencies] anyrender = { workspace = true } anyrender_vello = { workspace = true } anyrender_vello_cpu = { workspace = true, features = ["multithreading"] } anyrender_vello_hybrid = { workspace = true } -blitz-dom = { workspace = true, features = ["default"] } +blitz-dom = { workspace = true, features = ["svg", "woff", "accessibility", "system-fonts", "file-input", "custom-widget", "text-transform-icu"] } blitz-html = { workspace = true } blitz-traits = { workspace = true } blitz-paint = { workspace = true } @@ -296,6 +308,26 @@ wgpu = { workspace = true } wgpu_context = { workspace = true } rustc-hash = { workspace = true } +# The stylo fork with the gates relaxed on properties its servo build +# declines to compute. They are gated because servo's layout does not +# implement them, not because they need gecko: the values are plain Rust. +# Un-gating them is what lets winkin lay out, and the WPT suites reach, +# writing modes, ruby, emphasis marks, line clamping and the rest of the +# text properties winkin implements. Every crate of the stylo family is +# patched together, or Blitz would see two `Atom` types. +[patch.crates-io] +stylo = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_traits = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_atoms = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_dom = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_static_prefs = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_derive = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +stylo_malloc_size_of = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +selectors = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +servo_arc = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +to_shmem = { git = "https://github.com/dfrg/stylo", branch = "style-more" } +to_shmem_derive = { git = "https://github.com/dfrg/stylo", branch = "style-more" } + # [patch.crates-io] # anyrender = { path = "../anyrender/crates/anyrender" } # anyrender_skia = { path = "../anyrender/crates/anyrender_skia" } diff --git a/apps/browser/Cargo.toml b/apps/browser/Cargo.toml index b72608c4e5..bf02a468aa 100644 --- a/apps/browser/Cargo.toml +++ b/apps/browser/Cargo.toml @@ -10,7 +10,7 @@ name = "blitz" path = "src/main.rs" [features] -default = ["hybrid", "cookies", "cache", "screenshot", "apple-font-embolden", "scrollbars"] +default = ["hybrid", "cookies", "cache", "screenshot", "apple-font-embolden", "scrollbars", "parley"] android-defaults = ["skia", "cookies"] screenshot = ["dep:anyrender_vello_cpu", "dep:blitz-paint", "dep:png", "dep:peniko", "dep:rfd"] @@ -41,6 +41,9 @@ mimalloc = ["dep:mimalloc"] font-embolden = ["dioxus-native/font-embolden"] apple-font-embolden = ["dioxus-native/apple-font-embolden"] writing-mode = ["blitz-dom/writing-mode", "dioxus-native/writing-mode"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley", "blitz-dom/parley", "blitz-html/parley", "blitz-paint?/parley", "blitz-vibey-script?/parley"] +winkin = ["dioxus-native/winkin", "blitz-dom/winkin", "blitz-html/winkin", "blitz-paint?/winkin", "blitz-vibey-script?/winkin"] [dependencies] dioxus-native = { workspace = true, features = [ diff --git a/apps/browser/src/document_loader.rs b/apps/browser/src/document_loader.rs index 2a6a9e6b32..4deee72b31 100644 --- a/apps/browser/src/document_loader.rs +++ b/apps/browser/src/document_loader.rs @@ -1,5 +1,6 @@ use std::sync::{Arc, Mutex}; +use blitz_dom::text::TextFonts as _; use blitz_dom::{DocumentConfig, FontContext}; use blitz_html::{HtmlDocument, HtmlProvider}; use blitz_traits::{ @@ -7,7 +8,6 @@ use blitz_traits::{ shell::ShellProvider, }; use dioxus_native::{SubDocumentAttr, prelude::*}; -use linebender_resource_handle::Blob; use crate::StdNetProvider; use crate::favicon::favicon_candidate; @@ -34,6 +34,8 @@ pub struct LoadedDocument { } pub struct DocumentLoader { + /// The fonts the tab's documents lay out text with, listed once and shared by every + /// document the tab loads. pub font_ctx: FontContext, pub net_provider: Arc, pub status: Signal, @@ -42,33 +44,10 @@ pub struct DocumentLoader { current_abort: Mutex>, } -pub fn make_doc_config( - base_url: Option, - net_provider: Arc, - history: SyncStore, - font_ctx: FontContext, - abort_signal: Option, -) -> DocumentConfig { - DocumentConfig { - viewport: None, - base_url, - net_provider: Some(net_provider as _), - navigation_provider: Some(Arc::new(BrowserNavProvider { history })), - shell_provider: Some(consume_context::>()), - html_parser_provider: Some(Arc::new(HtmlProvider)), - font_ctx: Some(font_ctx), - media_type: None, - abort_signal, - ..Default::default() - } -} - impl DocumentLoader { pub fn new(net_provider: Arc, history: SyncStore) -> Self { let mut font_ctx = FontContext::default(); - font_ctx - .collection - .register_fonts(Blob::new(Arc::new(blitz_dom::BULLET_FONT) as _), None); + font_ctx.add_fonts(blitz_dom::BULLET_FONT); Self { font_ctx, @@ -80,6 +59,27 @@ impl DocumentLoader { } } + pub fn make_doc_config( + &self, + base_url: Option, + abort_signal: Option, + ) -> DocumentConfig { + DocumentConfig { + viewport: None, + base_url, + net_provider: Some(Arc::clone(&self.net_provider) as _), + navigation_provider: Some(Arc::new(BrowserNavProvider { + history: self.history, + })), + shell_provider: Some(consume_context::>()), + html_parser_provider: Some(Arc::new(HtmlProvider)), + font_ctx: Some(self.font_ctx.clone()), + media_type: None, + abort_signal, + ..Default::default() + } + } + pub fn reload(&self) { self.abort_current(); let mut reload_generation = self.reload_generation; @@ -98,8 +98,6 @@ impl DocumentLoader { pub async fn load_document(&self, req: Request) -> LoadedDocument { let net_provider = Arc::clone(&self.net_provider); - let font_ctx = self.font_ctx.clone(); - let history = self.history; let controller = AbortController::default(); let signal = controller.signal.clone(); @@ -119,13 +117,7 @@ impl DocumentLoader { Ok((resolved_url, bytes)) => { tracing::info!("Loaded {}", resolved_url); let base_url = resolved_url.clone(); - let config = make_doc_config( - Some(resolved_url), - Arc::clone(&net_provider), - history, - font_ctx, - Some(signal.clone()), - ); + let config = self.make_doc_config(Some(resolved_url), Some(signal.clone())); let body_text; let (html, is_error) = if bytes.is_empty() { @@ -151,8 +143,7 @@ impl DocumentLoader { tracing::error!("Error loading document: {:?}", err); let error_msg = format!("{err:?}"); - let config = - make_doc_config(None, net_provider, history, font_ctx, Some(signal.clone())); + let config = self.make_doc_config(None, Some(signal.clone())); let error_html = include_str!("../assets/error.html"); let mut document = HtmlDocument::from_html(error_html, config).into_inner(); diff --git a/apps/readme/Cargo.toml b/apps/readme/Cargo.toml index 08572c0238..0919ebdbbb 100644 --- a/apps/readme/Cargo.toml +++ b/apps/readme/Cargo.toml @@ -10,7 +10,10 @@ repository.workspace = true publish = true [features] -default = ["hybrid", "comrak", "floats", "scrollbars"] +default = ["hybrid", "comrak", "floats", "scrollbars", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["blitz-dom/parley", "blitz-html/parley", "blitz-paint/parley", "blitz-shell/parley"] +winkin = ["blitz-dom/winkin", "blitz-html/winkin", "blitz-paint/winkin", "blitz-shell/winkin"] # Renderers gpu = ["dep:anyrender_vello"] @@ -43,11 +46,11 @@ tracing = ["dep:tracing-subscriber", "blitz-shell/tracing", "blitz-net/tracing", [dependencies] blitz-traits = { workspace = true } -blitz-dom = { workspace = true, features = ["default", "parallel-construct"] } +blitz-dom = { workspace = true, features = ["svg", "woff", "accessibility", "system-fonts", "file-input", "custom-widget", "text-transform-icu", "parallel-construct"] } blitz-html = { workspace = true } -blitz-paint = { workspace = true, features = ["default"] } +blitz-paint = { workspace = true, features = ["svg"] } blitz-net = { workspace = true, features = ["cookies"] } -blitz-shell = { workspace = true, features = ["default"] } +blitz-shell = { workspace = true, features = ["accessibility", "clipboard", "file-dialog"] } anyrender_vello = { workspace = true, optional = true } anyrender_skia = { workspace = true, optional = true } anyrender_vello_cpu = { workspace = true, features = ["multithreading"], optional = true } diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index c314bd0ee2..963584e44e 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -9,7 +9,10 @@ publish = false crate-type = ["cdylib"] [features] -default = ["hybrid"] +default = ["hybrid", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley", "blitz-dom/parley", "blitz-paint/parley"] +winkin = ["dioxus-native/winkin", "blitz-dom/winkin", "blitz-paint/winkin"] system-fonts = ["blitz-dom/system-fonts"] vello = ["dioxus-native/vello"] cpu = ["cpu-pixels"] diff --git a/examples/screenshot.rs b/examples/screenshot.rs index 16cefd9808..ac54ae7a91 100644 --- a/examples/screenshot.rs +++ b/examples/screenshot.rs @@ -1,4 +1,7 @@ //! Load first CLI argument as a url. Fallback to google.com if no CLI argument is provided. +//! +//! The second argument is the viewport's width in CSS pixels, and the third the +//! path to write the PNG to. use anyrender::{PaintScene as _, render_to_buffer}; use anyrender_vello_cpu::VelloCpuImageRenderer; @@ -102,7 +105,7 @@ async fn main() { // Determine height to render let computed_height = document.as_ref().root_element().final_layout().size.height; let render_width = (width as f64 * scale) as u32; - let render_height = ((computed_height as f64).max(height as f64).min(4000.0) * scale) as u32; + let render_height = ((computed_height as f64).max(1.0).min(4000.0) * scale) as u32; // Render document to RGBA buffer let buffer = render_to_buffer::( @@ -133,8 +136,12 @@ async fn main() { timer.time("Rendered to buffer"); - // Determine output path, and open a file at that path. TODO: make configurable. - let out_path = compute_filename(&url_string); + // Determine output path, and open a file at that path: the third + // argument where there is one. + let out_path = std::env::args() + .nth(3) + .map(PathBuf::from) + .unwrap_or_else(|| compute_filename(&url_string)); let mut file = File::create(&out_path).unwrap(); // Encode buffer as PNG and write it to a file diff --git a/examples/seven_guis/Cargo.toml b/examples/seven_guis/Cargo.toml index 68951c8b19..05c8d2159c 100644 --- a/examples/seven_guis/Cargo.toml +++ b/examples/seven_guis/Cargo.toml @@ -13,7 +13,10 @@ path = "src/main.rs" crate-type = ["cdylib", "rlib"] [features] -default = ["hybrid"] +default = ["hybrid", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley"] +winkin = ["dioxus-native/winkin"] vello = ["dioxus-native/vello"] hybrid = ["dioxus-native/vello-hybrid"] skia = ["dioxus-native/skia"] diff --git a/examples/todomvc/Cargo.toml b/examples/todomvc/Cargo.toml index 08be7ee3e2..e25cdc2cd4 100644 --- a/examples/todomvc/Cargo.toml +++ b/examples/todomvc/Cargo.toml @@ -13,7 +13,10 @@ path = "src/main.rs" crate-type = ["cdylib"] [features] -default = ["hybrid"] +default = ["hybrid", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley"] +winkin = ["dioxus-native/winkin"] vello = ["dioxus-native/vello"] hybrid = ["dioxus-native/vello-hybrid"] skia = ["dioxus-native/skia"] diff --git a/examples/transparent/Cargo.toml b/examples/transparent/Cargo.toml index d7b34abbeb..fc3395ee5f 100644 --- a/examples/transparent/Cargo.toml +++ b/examples/transparent/Cargo.toml @@ -6,7 +6,10 @@ license.workspace = true publish = false [features] -default = ["hybrid"] +default = ["hybrid", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley", "blitz-dom/parley", "blitz-paint/parley"] +winkin = ["dioxus-native/winkin", "blitz-dom/winkin", "blitz-paint/winkin"] system-fonts = ["blitz-dom/system-fonts"] vello = ["dioxus-native/vello"] cpu = ["cpu-pixels"] diff --git a/examples/wasm_hello/Cargo.toml b/examples/wasm_hello/Cargo.toml index d556bf01c9..040c990bbf 100644 --- a/examples/wasm_hello/Cargo.toml +++ b/examples/wasm_hello/Cargo.toml @@ -10,7 +10,8 @@ crate-type = ["cdylib"] [dependencies] anyrender_vello_hybrid = { workspace = true, features = ["webgl"] } -blitz-dom = { workspace = true, features = ["woff"] } +# This example builds Parley's font context itself. +blitz-dom = { workspace = true, features = ["woff", "parley"] } blitz-html = { workspace = true } blitz-shell = { workspace = true, default-features = false, features = ["tracing"]} diff --git a/examples/wgpu_texture/Cargo.toml b/examples/wgpu_texture/Cargo.toml index 7560c6d6cd..2cbbc4b96f 100644 --- a/examples/wgpu_texture/Cargo.toml +++ b/examples/wgpu_texture/Cargo.toml @@ -9,7 +9,10 @@ license = "MIT" publish = false [features] -default = ["vello-hybrid"] +default = ["vello-hybrid", "parley"] +# The text backend: Parley (the default) or winkin. With both, Parley is used. +parley = ["dioxus-native/parley", "blitz-dom/parley", "blitz-paint/parley", "blitz-html/parley", "blitz-shell/parley"] +winkin = ["dioxus-native/winkin", "blitz-dom/winkin", "blitz-paint/winkin", "blitz-html/winkin", "blitz-shell/winkin"] vello = ["dep:anyrender_vello", "dioxus-native/vello"] vello-hybrid = ["dep:anyrender_vello_hybrid", "dioxus-native/vello-hybrid"] diff --git a/justfile b/justfile index 123fba584e..342d18eeff 100644 --- a/justfile +++ b/justfile @@ -21,6 +21,9 @@ wpt *ARGS: browser *ARGS: cargo run --release --package browser --features log-frame-times,log-phase-times {{ARGS}} +browink *ARGS: + cargo run --release --package browser --no-default-features --features winkin,hybrid,cookies,cache,screenshot,apple-font-embolden,scrollbars,log-frame-times,log-phase-times {{ARGS}} + browser-with-perf: cargo run --release --package browser --features log-frame-times,log-phase-times diff --git a/packages/blitz-dom/Cargo.toml b/packages/blitz-dom/Cargo.toml index a36fdfa3d7..966b611d01 100644 --- a/packages/blitz-dom/Cargo.toml +++ b/packages/blitz-dom/Cargo.toml @@ -18,17 +18,22 @@ default = [ "system-fonts", "file-input", "custom-widget", - "text-transform-icu" + "text-transform-icu", + "parley", ] +# The text backend that lays out, edits and reads back text: Parley or winkin. +# One of them must be enabled; with both, Parley is used. +parley = ["dep:parley"] +winkin = ["dep:winkin", "dep:fontwich"] custom-widget = ["dep:anyrender", "accessibility"] tracing = ["dep:tracing"] svg = ["dep:usvg", "dep:svgtypes"] # WOFF decoding (using the "wuff" crate which is pure Rust) woff = ["dep:wuff"] accessibility = ["accesskit"] -system-fonts = ["parley/system"] +system-fonts = ["parley?/system", "fontwich?/system", "fontwich?/mmap"] # complex-scripts: enable dictionary-based line-breaking -complex-scripts = ["parley/complex-scripts"] +complex-scripts = ["parley?/complex-scripts", "winkin?/dictionaries"] # text-transform-icu: language-aware, Unicode-complete case mapping for `text-transform` # (otherwise falls back to the standard library's case mapping) text-transform-icu = ["dep:icu_casemap", "dep:writeable"] @@ -69,7 +74,11 @@ anyrender = { workspace = true, optional = true } # Linebender/Fontations dependencies accesskit = { workspace = true, optional = true } -parley = { workspace = true } +parlance = { workspace = true } +# blitz-paint casts Parley's glyph coordinates with bytemuck. +parley = { workspace = true, optional = true, features = ["bytemuck"] } +winkin = { workspace = true, optional = true } +fontwich = { workspace = true, optional = true } skrifa = { workspace = true } linebender_resource_handle = { workspace = true } color = { workspace = true } diff --git a/packages/blitz-dom/assets/default.css b/packages/blitz-dom/assets/default.css index ad76a976be..0b96c202e5 100644 --- a/packages/blitz-dom/assets/default.css +++ b/packages/blitz-dom/assets/default.css @@ -17,8 +17,8 @@ * spec's bidi rendering section rather than Gecko's internal pseudo-classes * (:-moz-dir-attr-rtl and friends), which this engine's selector parser * does not know: it dropped these rules, and the dir attribute did nothing. - * dir=auto keeps its isolation but not the content-based direction, which - * needs bidi analysis no selector can express. + * dir=auto takes its content-based direction from a presentational hint, + * which needs bidi analysis no selector can express. */ [dir="ltr" i] { @@ -59,6 +59,11 @@ input[type="hidden" i] { display: none !important; } +/* Password fields draw a disc for each character, as Chrome's UA sheet has them. */ +input[type="password" i] { + -webkit-text-security: disc !important; +} + input[type="checkbox"] { width: 14px; height: 14px; @@ -101,7 +106,8 @@ input[type="reset"], input[type="button"] { border: 1px solid #999; border-radius: 1px; - padding: 1px 6px; + padding-block: 1px; + padding-inline: 6px; color: black; background-color: #EFEFEF; text-align: center; @@ -116,6 +122,55 @@ input[type="submit"], input[type="reset"], input[type="button"] { overflow: clip !important; + white-space: pre; +} + +/* Form controls draw their platform look unless `appearance: none` asks for + * the look their CSS gives them, as Chrome's UA stylesheet sets it. */ +input, +textarea, +select, +button, +progress, +meter { + appearance: auto; +} + +input[type="file"] { + appearance: none; +} + +/* A color well is 50px by 27px along the inline and block axes, as in Chrome. */ +input[type="color"] { + box-sizing: border-box; + inline-size: 50px; + block-size: 27px; + padding: 1px 2px; + background-color: #EFEFEF; +} + +input[type="range"] { + border: none; + padding: 0; + margin: 2px; +} + +/* https://html.spec.whatwg.org/#the-progress-element-2 and + * https://html.spec.whatwg.org/#the-meter-element-2, with Chrome's sizes */ +progress, +meter { + display: inline-block; + box-sizing: border-box; + block-size: 1em; + vertical-align: -0.2em; +} + +progress { + inline-size: 10em; +} + +meter { + inline-size: 5em; } input[type="file"] { @@ -147,6 +202,26 @@ option { display: none; } +/* A list box shows its options, one to a row along its block axis, and + * scrolls through them: https://html.spec.whatwg.org/#the-select-element-2. + * Its block size is its display size in rows of 1.2em, a presentational + * hint. */ +select:is([multiple], [size]:not([size="0"], [size="1"])) { + display: inline-block; + overflow: auto; + border: 1px solid #767676; + border-radius: 2px; + background-color: white; + vertical-align: text-bottom; + white-space: nowrap; +} + +select:is([multiple], [size]:not([size="0"], [size="1"])) option { + display: block; + padding-inline: 2px; + line-height: 1.2; +} + picture { display: contents; } @@ -234,11 +309,28 @@ bdo:-moz-has-dir-attr { unicode-bidi: isolate-override; } -textarea:-moz-dir-attr-like-auto, -pre:-moz-dir-attr-like-auto { +/* The rule above is dropped where `:-moz-has-dir-attr` does not parse, and + "bdo[dir]" outweighs the "[dir]" rules the way that selector did. */ +bdo, +bdo[dir] { + unicode-bidi: isolate-override; +} + +/* The HTML spec's form: `:-moz-dir-attr-like-auto` does not parse here. */ +textarea[dir="auto" i], +pre[dir="auto" i] { unicode-bidi: plaintext; } +/* CSS Text 4's default style sheet: no autospace in code. */ +pre, +code, +kbd, +samp, +tt { + text-autospace: no-autospace; +} + /* blocks */ article, @@ -1060,13 +1152,6 @@ rtc>rt { font-size: unset; } -ruby, -rb, -rt, -rtc { - unicode-bidi: isolate; -} - /* Shadow DOM v1 * https://drafts.csswg.org/css-scoping/#slots-in-shadow-tree */ slot { diff --git a/packages/blitz-dom/build.rs b/packages/blitz-dom/build.rs new file mode 100644 index 0000000000..8742182334 --- /dev/null +++ b/packages/blitz-dom/build.rs @@ -0,0 +1,12 @@ +//! Picks the text backend, as the `text_parley` or `text_winkin` cfg, which the +//! code reads in place of the features. With both features, Parley is used. + +fn main() { + println!("cargo::rustc-check-cfg=cfg(text_parley)"); + println!("cargo::rustc-check-cfg=cfg(text_winkin)"); + if std::env::var_os("CARGO_FEATURE_PARLEY").is_some() { + println!("cargo::rustc-cfg=text_parley"); + } else if std::env::var_os("CARGO_FEATURE_WINKIN").is_some() { + println!("cargo::rustc-cfg=text_winkin"); + } +} diff --git a/packages/blitz-dom/src/accessibility.rs b/packages/blitz-dom/src/accessibility.rs index 06ef05745e..a1795659b2 100644 --- a/packages/blitz-dom/src/accessibility.rs +++ b/packages/blitz-dom/src/accessibility.rs @@ -91,7 +91,7 @@ impl BlitzDomNode { .and_then(|s| s.get()) .map(|s| { s.styles.is_display_none() - || s.styles.primary().clone_visibility() + || s.styles.primary().slow_clone_visibility() == visibility::computed_value::T::Hidden }) .unwrap_or(false) diff --git a/packages/blitz-dom/src/config.rs b/packages/blitz-dom/src/config.rs index 4686b1285a..04dc6c50dd 100644 --- a/packages/blitz-dom/src/config.rs +++ b/packages/blitz-dom/src/config.rs @@ -1,10 +1,10 @@ +use crate::text::FontContext; use crate::{HtmlParserProvider, UserAgentStylesheet}; use blitz_traits::{ navigation::NavigationProvider, net::{AbortSignal, NetProvider}, shell::{ShellProvider, Viewport}, }; -use parley::FontContext; use std::sync::Arc; use style::media_queries::MediaType; @@ -47,7 +47,10 @@ pub struct DocumentConfig { pub shell_provider: Option>, /// HTML parser provider. Used to parse HTML for setInnerHTML pub html_parser_provider: Option>, - /// Parley `FontContext` + /// The fonts the document lays out text with. Defaults to the platform's fonts, where Blitz + /// is built to read them (`system-fonts`), and Blitz's bullet font. Clones share loaded + /// fonts, so hand a clone of one to every document rather than listing the platform's fonts + /// for each. pub font_ctx: Option, /// The CSS media type used to evaluate `@media` rules. /// Defaults to [`MediaType::screen`]. @@ -68,6 +71,14 @@ pub struct DocumentConfig { /// How deeply this document is nested within other documents /// (0 for a root document). Used to limit `