tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a9f1bab0067638a8ffdbf85258ddb0062e9c5b9c
parent 1dd6f80bb061b1016ccf09faca2ab738d30cb0a6
Author: Jonathan Kew <jkew@mozilla.com>
Date:   Sat, 15 Nov 2025 14:59:18 +0000

Bug 2000190 - Update dwrote dependency to version 0.11.5. r=gfx-reviewers,supply-chain-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D272628

Diffstat:
MCargo.lock | 4++--
Mgfx/webrender_bindings/Cargo.toml | 2+-
Mgfx/wr/Cargo.lock | 4++--
Mgfx/wr/wr_glyph_rasterizer/Cargo.toml | 2+-
Mgfx/wr/wrench/Cargo.toml | 2+-
Msupply-chain/audits.toml | 5+++++
Mthird_party/rust/dwrote/.cargo-checksum.json | 4++--
Athird_party/rust/dwrote/Cargo.lock | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthird_party/rust/dwrote/Cargo.toml | 49+++++++++++++++++++++++++++++++++++++------------
Dthird_party/rust/dwrote/appveyor.yml | 122-------------------------------------------------------------------------------
Mthird_party/rust/dwrote/src/com_helpers.rs | 2+-
Mthird_party/rust/dwrote/src/font.rs | 38+++++++++++++++++++++++++++++++++++++-
Mthird_party/rust/dwrote/src/font_collection.rs | 76++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mthird_party/rust/dwrote/src/font_collection_impl.rs | 14+++++++-------
Mthird_party/rust/dwrote/src/font_face.rs | 328++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mthird_party/rust/dwrote/src/font_family.rs | 58+++++++++++++++++++++++++++++++++++++++++++++-------------
Mthird_party/rust/dwrote/src/font_file.rs | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mthird_party/rust/dwrote/src/font_file_loader_impl.rs | 23++++++++++++-----------
Mthird_party/rust/dwrote/src/geometry_sink_impl.rs | 8++++----
Mthird_party/rust/dwrote/src/helpers.rs | 6+-----
Mthird_party/rust/dwrote/src/lib.rs | 6+++---
Mthird_party/rust/dwrote/src/test.rs | 21++++++++++++---------
Mthird_party/rust/dwrote/src/text_analysis_source.rs | 16+++++++++++-----
Mthird_party/rust/dwrote/src/text_analysis_source_impl.rs | 18+++++++++++-------
Mthird_party/rust/dwrote/src/types.rs | 2+-
25 files changed, 703 insertions(+), 305 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1755,9 +1755,9 @@ dependencies = [ [[package]] name = "dwrote" -version = "0.11.0" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" dependencies = [ "lazy_static", "libc", diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml @@ -34,7 +34,7 @@ features = ["capture", "serialize_program", "gecko", "sw_compositor"] debugger = ["webrender/debugger"] [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.11" +dwrote = "0.11.5" winapi = "0.3" [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock @@ -903,9 +903,9 @@ checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" [[package]] name = "dwrote" -version = "0.11.0" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" dependencies = [ "lazy_static", "libc", diff --git a/gfx/wr/wr_glyph_rasterizer/Cargo.toml b/gfx/wr/wr_glyph_rasterizer/Cargo.toml @@ -42,7 +42,7 @@ freetype = { version = "0.7", default-features = false } libc = "0.2" [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.11" +dwrote = "0.11.5" [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] core-foundation = "0.9.2" diff --git a/gfx/wr/wrench/Cargo.toml b/gfx/wr/wrench/Cargo.toml @@ -49,7 +49,7 @@ software = [ "swgl" ] debugger = [ "webrender/debugger" ] [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.11" +dwrote = "0.11.5" mozangle = { version = "0.5.2", features = ["egl"] } [target.'cfg(target_os = "android")'.dependencies] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml @@ -2238,6 +2238,11 @@ criteria = "safe-to-deploy" version = "0.11.0" notes = "All code written or reviewed by Mozilla staff." +[[audits.dwrote]] +who = "Jonathan Kew <jfkthame@gmail.com>" +criteria = "safe-to-deploy" +delta = "0.11.0 -> 0.11.5" + [[audits.either]] who = "Mike Hommey <mh+mozilla@glandium.org>" criteria = "safe-to-deploy" diff --git a/third_party/rust/dwrote/.cargo-checksum.json b/third_party/rust/dwrote/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"2475bea1fc2ab1cb052f254fb2bcf1bfcaba5aafe8b9acea297db498d8ec81fd","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","appveyor.yml":"6a91cdfbcc8c363ead82321b3be509bb7bf9cf8b90c63518d6484371abcfed48","src/bitmap_render_target.rs":"f677fa828e7466b7e8f9e5feaba7e97bd7512a2f8ee8920e5a4afad9984a9050","src/com_helpers.rs":"b3c7c545646b86b00bcf355da5ed6672596aa050b68f0b62020d8f89839267ab","src/font.rs":"295dbf78b75df4cb8a009fe381892dd00a3ef3ab49e64f9bef0477f46444d134","src/font_collection.rs":"187474bbca4845ffeb52a7535f6ff476e2cf9dd7310849ed801763e7220bdcc2","src/font_collection_impl.rs":"b27b0ae87b09e131eb807e1dee4521bff3cef66964e5494b965f12f40986d3a9","src/font_face.rs":"f5ad21c5814a094647e96cc4d08762d5da04c051344d51aa7c243d3bd86e6e11","src/font_fallback.rs":"c0c39fffdcc6747ed7513e60cbc16510515bf5b6e38d90ca9f5647bfe7c9471c","src/font_family.rs":"5abb5064933042fb5023c5f223ae4ca1942fa6f26d326279257b33a6fdb9a89c","src/font_file.rs":"d6e371f59635d908c8181bcdd3aca3ec1f4690fb7f66f7672b21fae4631a86aa","src/font_file_loader_impl.rs":"db7f93e52f4f071e5face8e8ed9d34c061d928da376b5de4c461b33d217a68ac","src/gdi_interop.rs":"7d33373f8b5af1e0ffac035b0093d72857624a5ab8696658172cd5c8b11edb2a","src/geometry_sink_impl.rs":"447fdc3179b738d981bad86052eb5820bc4d3a1f6fdd811b25617dd0847b1519","src/glyph_run_analysis.rs":"c3ad300f601f50a6b7fc8534e8b5a15c36f99c8ac495310d5e7d804e573d9c95","src/helpers.rs":"0d854b4fe40b80e9ab681a705e32bf430a16ed2f86f472b5a21243d3bb8ef242","src/lib.rs":"54b0e94f800d9c6fb8dff6e6d57f11aa9d6f78b8a63a6c5e9458bd16b2880991","src/outline_builder.rs":"0f5c842b2ffe75e21d68f93be6a3834c120bd43303d4e490fdfee9f4f964cdc4","src/rendering_params.rs":"b04db3a35fb762d8d7b2a2d660a2fd452597b3b7c522b09279d93ce889c117cd","src/test.rs":"43e8b213119c2a48d0ab252da9944c28aeaf693cedb1d69a19c8427cd474eaf9","src/text_analysis_source.rs":"8ff78ccb1271caf06aabcac6ce707685e470a7aaca0c743bf33565f85fc0ecb1","src/text_analysis_source_impl.rs":"2c435ee312b3196c17493c2ba6407a2ceae3a860a5eb83b6279ad929329d0de8","src/types.rs":"9374d8c5bac80e5e0b66188c5ff4f5f49264e15db837049932d4fd703c33746e"},"package":"439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b"} -\ No newline at end of file +{"files":{"Cargo.lock":"f3c8dc38ffeedb9df5409b6aa89df9e188859be4787ca6633a7b14138f5bf4da","Cargo.toml":"f5f002712c93e06fe939d826188415c75532d52d1b84520f1530f21052cb1d28","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","src/bitmap_render_target.rs":"f677fa828e7466b7e8f9e5feaba7e97bd7512a2f8ee8920e5a4afad9984a9050","src/com_helpers.rs":"8137ddcd7e3bd02a4daafd054c802d957f8ed38379e5b0aaf6d500412bce53b8","src/font.rs":"0bdf750d94a99b197a35d0ebff80760542b6047e3af6f9be91cf79664d35fcb7","src/font_collection.rs":"0fce4cc6271169030a2cf56cff5c725c9486791f0fc4008f929e549d77cfec4b","src/font_collection_impl.rs":"3e7d5ecf3139c118024946ac5067d22fbf2ec3770de745c18728e095b37507ae","src/font_face.rs":"445948cbc973c389264883db224347b5dabffccedc711cef8c7feeb9d978a898","src/font_fallback.rs":"c0c39fffdcc6747ed7513e60cbc16510515bf5b6e38d90ca9f5647bfe7c9471c","src/font_family.rs":"85e703cc1c8dc9f8e1f684928c0d2ecdd978eb8fd00d016a7811b168136dac1f","src/font_file.rs":"c6ae3f4a9ddeece3095ef35c3b1382e29b974e93ad40c45fa65d3e10f886a672","src/font_file_loader_impl.rs":"aeff7813785af3a16a0a6f7f29a3a400fa6c186bd62679b57090f5ff82d40b7c","src/gdi_interop.rs":"7d33373f8b5af1e0ffac035b0093d72857624a5ab8696658172cd5c8b11edb2a","src/geometry_sink_impl.rs":"03aed59304d9bdd44d2b06128b52697d722ea8af3130b378bb7255fb6053f204","src/glyph_run_analysis.rs":"c3ad300f601f50a6b7fc8534e8b5a15c36f99c8ac495310d5e7d804e573d9c95","src/helpers.rs":"0a701ad3ffece42ecc0a4371683471d982473de0f34b964987911b429f0b1bd3","src/lib.rs":"766d05ab96b05bf60a8aeb4fba86ffa05e87a8954dec23e4b52f7eaa6f92eb50","src/outline_builder.rs":"0f5c842b2ffe75e21d68f93be6a3834c120bd43303d4e490fdfee9f4f964cdc4","src/rendering_params.rs":"b04db3a35fb762d8d7b2a2d660a2fd452597b3b7c522b09279d93ce889c117cd","src/test.rs":"d76c49720469936d0cf93dcc805349b7980072cd3c2e7db3f5ecdc219fc90bc3","src/text_analysis_source.rs":"11e86056a2d4d74810758e59e70862ca624bfb84739334f099ccb567c8b41d01","src/text_analysis_source_impl.rs":"caf8018faf505ea2f9f4af609eb82cc2baaf43fc3ccba1e20d6ff724cdd04431","src/types.rs":"fedbb2227d11655d2399015b3132b523be5aff80efa1ee6928491afc3bbf5a8b"},"package":"9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02"} +\ No newline at end of file diff --git a/third_party/rust/dwrote/Cargo.lock b/third_party/rust/dwrote/Cargo.lock @@ -0,0 +1,122 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "dwrote" +version = "0.11.5" +dependencies = [ + "lazy_static", + "libc", + "serde", + "serde_derive", + "winapi", + "wio", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.176" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] diff --git a/third_party/rust/dwrote/Cargo.toml b/third_party/rust/dwrote/Cargo.toml @@ -3,24 +3,45 @@ # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies +# to registry (e.g., crates.io) dependencies. # -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "dwrote" -version = "0.11.0" -authors = ["The Servo Project Developers", "Vladimir Vukicevic <vladimir@pobox.com>"] +version = "0.11.5" +authors = [ + "The Servo Project Developers", + "Vladimir Vukicevic <vladimir@pobox.com>", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "Lightweight binding to DirectWrite." +readme = "README.md" license = "MPL-2.0" repository = "https://github.com/servo/dwrote-rs" +[package.metadata.docs.rs] +targets = ["x86_64-pc-windows-msvc"] + +[features] +default = ["serde_serialization"] +serde_serialization = [ + "serde", + "serde_derive", +] + [lib] name = "dwrote" +path = "src/lib.rs" + [dependencies.lazy_static] version = "1" @@ -37,11 +58,15 @@ optional = true [dependencies.winapi] version = "0.3.6" -features = ["dwrite", "dwrite_1", "dwrite_3", "winnt", "unknwnbase", "libloaderapi", "winnls"] +features = [ + "dwrite", + "dwrite_1", + "dwrite_3", + "winnt", + "unknwnbase", + "libloaderapi", + "winnls", +] [dependencies.wio] version = "0.2" - -[features] -default = ["serde_serialization"] -serde_serialization = ["serde", "serde_derive"] diff --git a/third_party/rust/dwrote/appveyor.yml b/third_party/rust/dwrote/appveyor.yml @@ -1,122 +0,0 @@ -# Appveyor configuration template for Rust using rustup for Rust installation -# https://github.com/starkat99/appveyor-rust - -## Operating System (VM environment) ## - -# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. -os: Visual Studio 2015 - -## Build Matrix ## - -# This configuration will setup a build for each channel & target combination (12 windows -# combinations in all). -# -# There are 3 channels: stable, beta, and nightly. -# -# Alternatively, the full version may be specified for the channel to build using that specific -# version (e.g. channel: 1.5.0) -# -# The values for target are the set of windows Rust build targets. Each value is of the form -# -# ARCH-pc-windows-TOOLCHAIN -# -# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker -# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for -# a description of the toolchain differences. -# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of -# toolchains and host triples. -# -# Comment out channel/target combos you do not wish to build in CI. -# -# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands -# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly -# channels to enable unstable features when building for nightly. Or you could add additional -# matrix entries to test different combinations of features. -environment: - matrix: - -### MSVC Toolchains ### - - # Stable 64-bit MSVC - - channel: stable - target: x86_64-pc-windows-msvc - # Stable 32-bit MSVC - # - channel: stable - # target: i686-pc-windows-msvc - # Beta 64-bit MSVC - # - channel: beta - # target: x86_64-pc-windows-msvc - # Beta 32-bit MSVC - # - channel: beta - # target: i686-pc-windows-msvc - # Nightly 64-bit MSVC - # - channel: nightly - # target: x86_64-pc-windows-msvc - #cargoflags: --features "unstable" - # Nightly 32-bit MSVC - # - channel: nightly - # target: i686-pc-windows-msvc - #cargoflags: --features "unstable" - -### GNU Toolchains ### - - # Stable 64-bit GNU - # - channel: stable - # target: x86_64-pc-windows-gnu - # Stable 32-bit GNU - # - channel: stable - # target: i686-pc-windows-gnu - # Beta 64-bit GNU - # - channel: beta - # target: x86_64-pc-windows-gnu - # Beta 32-bit GNU - # - channel: beta - # target: i686-pc-windows-gnu - # Nightly 64-bit GNU - # - channel: nightly - # target: x86_64-pc-windows-gnu - # #cargoflags: --features "unstable" - # Nightly 32-bit GNU - # - channel: nightly - # target: i686-pc-windows-gnu - #cargoflags: --features "unstable" - -### Allowed failures ### - -# See Appveyor documentation for specific details. In short, place any channel or targets you wish -# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build -# or test failure in the matching channels/targets from failing the entire build. -matrix: - allow_failures: - - channel: nightly - -# If you only care about stable channel build failures, uncomment the following line: - #- channel: beta - -## Install Script ## - -# This is the most important part of the Appveyor configuration. This installs the version of Rust -# specified by the 'channel' and 'target' environment variables from the build matrix. This uses -# rustup to install Rust. -# -# For simple configurations, instead of using the build matrix, you can simply set the -# default-toolchain and default-host manually here. -install: - - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init -yv --default-toolchain %channel% --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - - rustc -vV - - cargo -vV - -## Build Script ## - -# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents -# the "directory does not contain a project or solution file" error. -build: false - -# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs -#directly or perform other testing commands. Rust will automatically be placed in the PATH -# environment variable. -test_script: - - cargo check --no-default-features - - cargo test --verbose %cargoflags% diff --git a/third_party/rust/dwrote/src/com_helpers.rs b/third_party/rust/dwrote/src/com_helpers.rs @@ -122,6 +122,6 @@ where } unsafe fn destroy(thing: *mut Interface) { - Box::from_raw(thing as *mut ComRepr<Self, Self::Vtbl>); + let _ = Box::from_raw(thing as *mut ComRepr<Self, Self::Vtbl>); } } diff --git a/third_party/rust/dwrote/src/font.rs b/third_party/rust/dwrote/src/font.rs @@ -12,10 +12,28 @@ use winapi::um::dwrite::IDWriteFontFace; use winapi::um::dwrite::IDWriteFontFamily; use winapi::um::dwrite::IDWriteLocalizedStrings; use winapi::um::dwrite::DWRITE_FONT_METRICS; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESCRIPTION; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGNER; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGNER_URL; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL; use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FULL_NAME; use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_ID; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_MANUFACTURER; use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME; use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_TRADEMARK; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME; use winapi::um::dwrite_1::{IDWriteFont1, DWRITE_FONT_METRICS1}; use wio::com::ComPtr; @@ -150,6 +168,24 @@ pub enum InformationalStringId { FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, PostscriptName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, PostscriptCidName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, + CopyrightNotice = DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, + Description = DWRITE_INFORMATIONAL_STRING_DESCRIPTION, + Designer = DWRITE_INFORMATIONAL_STRING_DESIGNER, + DesignerUrl = DWRITE_INFORMATIONAL_STRING_DESIGNER_URL, + DesignScriptLanguageTag = DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG, + VendorUrl = DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL, + LicenseDescription = DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION, + LicenseInfoUrl = DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL, + Manufacturer = DWRITE_INFORMATIONAL_STRING_MANUFACTURER, + PreferredFamilyNames = DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES, + PreferredSubfamilyNames = DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES, + SampleText = DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT, + SupportedScriptLanguageTag = DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG, + Trademark = DWRITE_INFORMATIONAL_STRING_TRADEMARK, + Version = DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS, + Win32FamilyNames = DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, + Win32SubfamilyNames = DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, + WwsFamilyName = DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME, } /// A wrapper around the `DWRITE_FONT_METRICS` and `DWRITE_FONT_METRICS1` types. @@ -176,7 +212,7 @@ impl FontMetrics { underlineThickness: metrics.underlineThickness, strikethroughPosition: metrics.strikethroughPosition, strikethroughThickness: metrics.strikethroughThickness, - } + }, } } } diff --git a/third_party/rust/dwrote/src/font_collection.rs b/third_party/rust/dwrote/src/font_collection.rs @@ -10,10 +10,11 @@ use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; use winapi::shared::winerror::S_OK; use winapi::um::dwrite::IDWriteFontCollectionLoader; use winapi::um::dwrite::{IDWriteFont, IDWriteFontCollection, IDWriteFontFamily}; +use winapi::um::winnt::HRESULT; use wio::com::ComPtr; -use crate::helpers::*; use super::{DWriteFactory, Font, FontDescriptor, FontFace, FontFamily}; +use crate::helpers::*; static NEXT_ID: AtomicUsize = AtomicUsize::new(0); @@ -48,10 +49,8 @@ impl FontCollection { pub fn get_system(update: bool) -> FontCollection { unsafe { let mut native: *mut IDWriteFontCollection = ptr::null_mut(); - let hr = (*DWriteFactory()).GetSystemFontCollection( - &mut native, - if update { TRUE } else { FALSE }, - ); + let hr = (*DWriteFactory()) + .GetSystemFontCollection(&mut native, if update { TRUE } else { FALSE }); assert!(hr == 0); FontCollection { @@ -110,62 +109,91 @@ impl FontCollection { unsafe { (*self.native.get()).GetFontFamilyCount() } } + #[deprecated(note = "Use `font_family` instead.")] pub fn get_font_family(&self, index: u32) -> FontFamily { + self.font_family(index).unwrap() + } + + /// Returns the [`FontFamily`] at the given index. + pub fn font_family(&self, index: u32) -> Result<FontFamily, HRESULT> { + let mut family: *mut IDWriteFontFamily = ptr::null_mut(); unsafe { - let mut family: *mut IDWriteFontFamily = ptr::null_mut(); let hr = (*self.native.get()).GetFontFamily(index, &mut family); - assert!(hr == 0); - FontFamily::take(ComPtr::from_raw(family)) + if hr != S_OK { + return Err(hr); + } + Ok(FontFamily::take(ComPtr::from_raw(family))) } } - // Find a font matching the given font descriptor in this - // font collection. + #[deprecated(note = "Use `font_from_descriptor` instead.")] pub fn get_font_from_descriptor(&self, desc: &FontDescriptor) -> Option<Font> { - if let Some(family) = self.get_font_family_by_name(&desc.family_name) { - let font = family.get_first_matching_font(desc.weight, desc.stretch, desc.style); + self.font_from_descriptor(desc).unwrap() + } + + /// Find a font matching the given font descriptor in this [`FontCollection`]. + pub fn font_from_descriptor(&self, desc: &FontDescriptor) -> Result<Option<Font>, HRESULT> { + if let Some(family) = self.font_family_by_name(&desc.family_name)? { + let font = family.first_matching_font(desc.weight, desc.stretch, desc.style)?; // Exact matches only here if font.weight() == desc.weight && font.stretch() == desc.stretch && font.style() == desc.style { - return Some(font); + return Ok(Some(font)); } } - None + Ok(None) } + #[deprecated(note = "Use `font_from_face` instead.")] pub fn get_font_from_face(&self, face: &FontFace) -> Option<Font> { + self.font_from_face(face).ok() + } + + /// Get a [`Font`] from the given [`FontFace`]. + pub fn font_from_face(&self, face: &FontFace) -> Result<Font, HRESULT> { + let mut font: *mut IDWriteFont = ptr::null_mut(); unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); let hr = (*self.native.get()).GetFontFromFontFace(face.as_ptr(), &mut font); - if hr != 0 { - return None; + if hr != S_OK { + return Err(hr); } - Some(Font::take(ComPtr::from_raw(font))) + Ok(Font::take(ComPtr::from_raw(font))) } } + #[deprecated(note = "Use `font_family_by_name` instead.")] pub fn get_font_family_by_name(&self, family_name: &str) -> Option<FontFamily> { + self.font_family_by_name(family_name).unwrap() + } + + /// Find a [`FontFamily`] with the given name. Returns `None` if no family + /// with that name is found. + pub fn font_family_by_name(&self, family_name: &str) -> Result<Option<FontFamily>, HRESULT> { + let mut index: u32 = 0; + let mut exists: BOOL = FALSE; unsafe { - let mut index: u32 = 0; - let mut exists: BOOL = FALSE; let hr = (*self.native.get()).FindFamilyName( family_name.to_wide_null().as_ptr(), &mut index, &mut exists, ); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } if exists == FALSE { - return None; + return Ok(None); } let mut family: *mut IDWriteFontFamily = ptr::null_mut(); let hr = (*self.native.get()).GetFontFamily(index, &mut family); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } - Some(FontFamily::take(ComPtr::from_raw(family))) + Ok(Some(FontFamily::take(ComPtr::from_raw(family)))) } } } diff --git a/third_party/rust/dwrote/src/font_collection_impl.rs b/third_party/rust/dwrote/src/font_collection_impl.rs @@ -76,7 +76,7 @@ unsafe extern "system" fn CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey out_enumerator: *mut *mut IDWriteFontFileEnumerator, ) -> HRESULT { let this = CustomFontCollectionLoaderImpl::from_interface(this); - let enumerator = CustomFontFileEnumeratorImpl::new((*this).font_files.clone()); + let enumerator = CustomFontFileEnumeratorImpl::new(this.font_files.clone()); let enumerator = ComPtr::<IDWriteFontFileEnumerator>::from_raw(enumerator.into_interface()); *out_enumerator = enumerator.as_raw(); mem::forget(enumerator); @@ -129,10 +129,10 @@ unsafe extern "system" fn CustomFontFileEnumeratorImpl_GetCurrentFontFile( out_font_file: *mut *mut IDWriteFontFile, ) -> HRESULT { let this = CustomFontFileEnumeratorImpl::from_interface(this); - if (*this).index < 0 || (*this).index >= (*this).font_files.len() as isize { + if this.index < 0 || this.index >= this.font_files.len() as isize { return E_INVALIDARG; } - let new_font_file = (*this).font_files[(*this).index as usize].clone(); + let new_font_file = this.font_files[this.index as usize].clone(); *out_font_file = new_font_file.as_raw(); mem::forget(new_font_file); S_OK @@ -144,11 +144,11 @@ unsafe extern "system" fn CustomFontFileEnumeratorImpl_MoveNext( has_current_file: *mut BOOL, ) -> HRESULT { let this = CustomFontFileEnumeratorImpl::from_interface(this); - let font_file_count = (*this).font_files.len() as isize; - if (*this).index < font_file_count { - (*this).index += 1 + let font_file_count = this.font_files.len() as isize; + if this.index < font_file_count { + this.index += 1 } - *has_current_file = if (*this).index >= 0 && (*this).index < font_file_count { + *has_current_file = if this.index >= 0 && this.index < font_file_count { TRUE } else { FALSE diff --git a/third_party/rust/dwrote/src/font_face.rs b/third_party/rust/dwrote/src/font_face.rs @@ -4,8 +4,8 @@ use std::cell::UnsafeCell; use std::mem::{self, zeroed}; -use std::ptr; use std::slice; +use std::{error, fmt, ptr}; use winapi::ctypes::c_void; use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; use winapi::shared::winerror::S_OK; @@ -20,16 +20,23 @@ use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS, DWRITE_GLYPH_METRICS}; use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MODE}; use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC}; use winapi::um::dwrite_1::IDWriteFontFace1; -use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE}; +use winapi::um::dwrite_3::{ + IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE, + DWRITE_FONT_AXIS_VALUE, +}; +use winapi::um::winnt::HRESULT; +use winapi::Interface; use wio::com::ComPtr; use super::{DWriteFactory, DefaultDWriteRenderParams, FontFile, FontMetrics}; use crate::com_helpers::Com; use crate::geometry_sink_impl::GeometrySinkImpl; use crate::outline_builder::OutlineBuilder; +use crate::FontSimulations; pub struct FontFace { native: UnsafeCell<ComPtr<IDWriteFontFace>>, + face1: UnsafeCell<Option<ComPtr<IDWriteFontFace1>>>, face5: UnsafeCell<Option<ComPtr<IDWriteFontFace5>>>, } @@ -38,6 +45,7 @@ impl FontFace { let cell = UnsafeCell::new(native); FontFace { native: cell, + face1: UnsafeCell::new(None), face5: UnsafeCell::new(None), } } @@ -46,25 +54,35 @@ impl FontFace { (*self.native.get()).as_raw() } - unsafe fn get_raw_files(&self) -> Vec<*mut IDWriteFontFile> { + unsafe fn raw_files(&self) -> Result<Vec<*mut IDWriteFontFile>, HRESULT> { let mut number_of_files: u32 = 0; let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut()); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let mut file_ptrs: Vec<*mut IDWriteFontFile> = vec![ptr::null_mut(); number_of_files as usize]; let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr()); - assert!(hr == 0); - file_ptrs + if hr != S_OK { + return Err(hr); + } + Ok(file_ptrs) } + #[deprecated(note = "Use `files` instead.")] pub fn get_files(&self) -> Vec<FontFile> { + self.files().unwrap() + } + + pub fn files(&self) -> Result<Vec<FontFile>, HRESULT> { unsafe { - let file_ptrs = self.get_raw_files(); - file_ptrs - .iter() - .map(|p| FontFile::take(ComPtr::from_raw(*p))) - .collect() + self.raw_files().map(|file_ptrs| { + file_ptrs + .iter() + .map(|p| FontFile::take(ComPtr::from_raw(*p))) + .collect() + }) } } @@ -73,7 +91,7 @@ impl FontFace { simulations: DWRITE_FONT_SIMULATIONS, ) -> FontFace { unsafe { - let file_ptrs = self.get_raw_files(); + let file_ptrs = self.raw_files().unwrap(); let face_type = (*self.native.get()).GetType(); let face_index = (*self.native.get()).GetIndex(); let mut face: *mut IDWriteFontFace = ptr::null_mut(); @@ -99,7 +117,7 @@ impl FontFace { pub fn metrics(&self) -> FontMetrics { unsafe { - let font_1: Option<ComPtr<IDWriteFontFace1>> = (*self.native.get()).cast().ok(); + let font_1 = self.get_face1(); match font_1 { None => { let mut metrics = mem::zeroed(); @@ -115,24 +133,41 @@ impl FontFace { } } + #[deprecated(note = "Use `glyph_indices` instead.")] pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16> { + self.glyph_indices(code_points).unwrap() + } + + pub fn glyph_indices(&self, code_points: &[u32]) -> Result<Vec<u16>, HRESULT> { + let mut glyph_indices: Vec<u16> = vec![0; code_points.len()]; unsafe { - let mut glyph_indices: Vec<u16> = vec![0; code_points.len()]; let hr = (*self.native.get()).GetGlyphIndices( code_points.as_ptr(), code_points.len() as u32, glyph_indices.as_mut_ptr(), ); - assert!(hr == 0); - glyph_indices + if hr != S_OK { + return Err(hr); + } + Ok(glyph_indices) } } + #[deprecated(note = "Use `design_glyph_metrics` instead.")] pub fn get_design_glyph_metrics( &self, glyph_indices: &[u16], is_sideways: bool, ) -> Vec<DWRITE_GLYPH_METRICS> { + self.design_glyph_metrics(glyph_indices, is_sideways) + .unwrap() + } + + pub fn design_glyph_metrics( + &self, + glyph_indices: &[u16], + is_sideways: bool, + ) -> Result<Vec<DWRITE_GLYPH_METRICS>, HRESULT> { unsafe { let mut metrics: Vec<DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()]; let hr = (*self.native.get()).GetDesignGlyphMetrics( @@ -141,11 +176,14 @@ impl FontFace { metrics.as_mut_ptr(), is_sideways as BOOL, ); - assert!(hr == 0); - metrics + if hr != S_OK { + return Err(hr); + } + Ok(metrics) } } + #[deprecated(note = "Use `gdi_compatible_glyph_metrics` instead.")] pub fn get_gdi_compatible_glyph_metrics( &self, em_size: f32, @@ -155,6 +193,26 @@ impl FontFace { glyph_indices: &[u16], is_sideways: bool, ) -> Vec<DWRITE_GLYPH_METRICS> { + self.gdi_compatible_glyph_metrics( + em_size, + pixels_per_dip, + transform, + use_gdi_natural, + glyph_indices, + is_sideways, + ) + .unwrap() + } + + pub fn gdi_compatible_glyph_metrics( + &self, + em_size: f32, + pixels_per_dip: f32, + transform: *const DWRITE_MATRIX, + use_gdi_natural: bool, + glyph_indices: &[u16], + is_sideways: bool, + ) -> Result<Vec<DWRITE_GLYPH_METRICS>, HRESULT> { unsafe { let mut metrics: Vec<DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()]; let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics( @@ -167,22 +225,28 @@ impl FontFace { metrics.as_mut_ptr(), is_sideways as BOOL, ); - assert!(hr == 0); - metrics + if hr != S_OK { + return Err(hr); + } + Ok(metrics) } } + #[deprecated(note = "Use `font_table` instead.")] + pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> { + self.font_table(opentype_table_tag).unwrap() + } + /// Returns the contents of the OpenType table with the given tag. /// /// NB: The bytes of the tag are reversed! You probably want to use the `u32::swap_bytes()` /// method on the tag value before calling this method. - pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> { + pub fn font_table(&self, opentype_table_tag: u32) -> Result<Option<Vec<u8>>, HRESULT> { + let mut table_data_ptr: *const u8 = ptr::null_mut(); + let mut table_size: u32 = 0; + let mut table_context: *mut c_void = ptr::null_mut(); + let mut exists: BOOL = FALSE; unsafe { - let mut table_data_ptr: *const u8 = ptr::null_mut(); - let mut table_size: u32 = 0; - let mut table_context: *mut c_void = ptr::null_mut(); - let mut exists: BOOL = FALSE; - let hr = (*self.native.get()).TryGetFontTable( opentype_table_tag, &mut table_data_ptr as *mut *const _ as *mut *const c_void, @@ -190,17 +254,19 @@ impl FontFace { &mut table_context, &mut exists, ); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } if exists == FALSE { - return None; + return Ok(None); } let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec(); (*self.native.get()).ReleaseFontTable(table_context); - Some(table_bytes) + Ok(Some(table_bytes)) } } @@ -221,7 +287,7 @@ impl FontFace { &mut render_mode, ); - if hr != 0 { + if hr != S_OK { return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; } @@ -243,6 +309,7 @@ impl FontFace { ) } + #[deprecated(note = "Use `glyph_run_outline` instead.")] pub fn get_glyph_run_outline( &self, em_size: f32, @@ -253,25 +320,51 @@ impl FontFace { is_right_to_left: bool, outline_builder: Box<dyn OutlineBuilder>, ) { - unsafe { - let glyph_advances = match glyph_advances { - None => ptr::null(), - Some(glyph_advances) => { - assert_eq!(glyph_advances.len(), glyph_indices.len()); - glyph_advances.as_ptr() + self.glyph_run_outline( + em_size, + glyph_indices, + glyph_advances, + glyph_offsets, + is_sideways, + is_right_to_left, + outline_builder, + ) + .unwrap() + } + + pub fn glyph_run_outline( + &self, + em_size: f32, + glyph_indices: &[u16], + glyph_advances: Option<&[f32]>, + glyph_offsets: Option<&[DWRITE_GLYPH_OFFSET]>, + is_sideways: bool, + is_right_to_left: bool, + outline_builder: Box<dyn OutlineBuilder>, + ) -> Result<(), GlyphRunOutlineError> { + let glyph_advances = match glyph_advances { + None => ptr::null(), + Some(glyph_advances) => { + if glyph_advances.len() != glyph_indices.len() { + return Err(GlyphRunOutlineError::InvalidInput); } - }; - let glyph_offsets = match glyph_offsets { - None => ptr::null(), - Some(glyph_offsets) => { - assert_eq!(glyph_offsets.len(), glyph_indices.len()); - glyph_offsets.as_ptr() + glyph_advances.as_ptr() + } + }; + let glyph_offsets = match glyph_offsets { + None => ptr::null(), + Some(glyph_offsets) => { + if glyph_offsets.len() != glyph_indices.len() { + return Err(GlyphRunOutlineError::InvalidInput); } - }; - let is_sideways = if is_sideways { TRUE } else { FALSE }; - let is_right_to_left = if is_right_to_left { TRUE } else { FALSE }; - let geometry_sink = GeometrySinkImpl::new(outline_builder); - let geometry_sink = geometry_sink.into_interface(); + glyph_offsets.as_ptr() + } + }; + let is_sideways = if is_sideways { TRUE } else { FALSE }; + let is_right_to_left = if is_right_to_left { TRUE } else { FALSE }; + let geometry_sink = GeometrySinkImpl::new(outline_builder); + let geometry_sink = geometry_sink.into_interface(); + unsafe { let hr = (*self.native.get()).GetGlyphRunOutline( em_size, glyph_indices.as_ptr(), @@ -282,7 +375,50 @@ impl FontFace { is_right_to_left, geometry_sink, ); - assert_eq!(hr, S_OK); + if hr != S_OK { + return Err(GlyphRunOutlineError::Win32Error(hr)); + } + } + Ok(()) + } + + pub fn has_kerning_pairs(&self) -> bool { + unsafe { + match self.get_face1() { + Some(face1) => face1.HasKerningPairs() == TRUE, + None => false, + } + } + } + + #[deprecated(note = "Use `glyph_pair_kerning_adjustment` instead.")] + pub fn get_glyph_pair_kerning_adjustment(&self, first_glyph: u16, second_glyph: u16) -> i32 { + self.glyph_pair_kerning_adjustment(first_glyph, second_glyph) + .unwrap() + } + + pub fn glyph_pair_kerning_adjustment( + &self, + first_glyph: u16, + second_glyph: u16, + ) -> Result<i32, HRESULT> { + unsafe { + match self.get_face1() { + Some(face1) => { + let mut adjustments = [0; 2]; + let hr = face1.GetKerningPairAdjustments( + 2, + [first_glyph, second_glyph].as_ptr(), + adjustments.as_mut_ptr(), + ); + if hr != S_OK { + return Err(hr); + } + + Ok(adjustments[0]) + } + None => Ok(0), + } } } @@ -308,11 +444,24 @@ impl FontFace { } #[inline] + unsafe fn get_face1(&self) -> Option<ComPtr<IDWriteFontFace1>> { + self.get_interface(&self.face1) + } + + #[inline] unsafe fn get_face5(&self) -> Option<ComPtr<IDWriteFontFace5>> { - if (*self.face5.get()).is_none() { - *self.face5.get() = (*self.native.get()).cast().ok() + self.get_interface(&self.face5) + } + + #[inline] + unsafe fn get_interface<I: Interface>( + &self, + interface: &UnsafeCell<Option<ComPtr<I>>>, + ) -> Option<ComPtr<I>> { + if (*interface.get()).is_none() { + *interface.get() = (*self.native.get()).cast().ok() } - (*self.face5.get()).clone() + (*interface.get()).clone() } pub fn has_variations(&self) -> bool { @@ -324,6 +473,57 @@ impl FontFace { } } + /// If this font has variations, return a [`Vec<DWRITE_FONT_AXIS_VALUE`] of the + /// variation axes and their values. If the font does not have variations, + /// return an empty `Vec`. + pub fn variations(&self) -> Result<Vec<DWRITE_FONT_AXIS_VALUE>, HRESULT> { + let face5 = unsafe { self.get_face5() }; + let Some(face5) = face5 else { + return Ok(vec![]); + }; + if unsafe { face5.HasVariations() != TRUE } { + return Ok(vec![]); + } + let axis_count = unsafe { face5.GetFontAxisValueCount() as usize }; + if axis_count == 0 { + return Ok(vec![]); + } + + let mut resource: *mut IDWriteFontResource = ptr::null_mut(); + let hr = unsafe { face5.GetFontResource(&mut resource) }; + if hr != S_OK || resource.is_null() { + return Err(hr); + } + + let mut axis_values = Vec::with_capacity(axis_count); + axis_values.resize( + axis_count, + DWRITE_FONT_AXIS_VALUE { + axisTag: 0, + value: 0., + }, + ); + + let hr = unsafe { face5.GetFontAxisValues(axis_values.as_mut_ptr(), axis_count as u32) }; + if hr != S_OK { + return Err(hr); + } + + let resource = unsafe { &*resource }; + Ok(axis_values + .iter() + .enumerate() + .filter_map(|(index, axis_value)| { + let attributes = unsafe { resource.GetFontAxisAttributes(index as u32) }; + if attributes & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE == 0 { + None + } else { + Some(*axis_value) + } + }) + .collect()) + } + pub fn create_font_face_with_variations( &self, simulations: DWRITE_FONT_SIMULATIONS, @@ -351,6 +551,14 @@ impl FontFace { None } } + + pub fn simulations(&self) -> FontSimulations { + unsafe { + std::mem::transmute::<DWRITE_FONT_SIMULATIONS, FontSimulations>( + (*self.native.get()).GetSimulations(), + ) + } + } } impl Clone for FontFace { @@ -358,6 +566,7 @@ impl Clone for FontFace { unsafe { FontFace { native: UnsafeCell::new((*self.native.get()).clone()), + face1: UnsafeCell::new(None), face5: UnsafeCell::new(None), } } @@ -375,3 +584,20 @@ pub enum FontFaceType { Vector, Bitmap, } + +#[derive(Debug)] +pub enum GlyphRunOutlineError { + InvalidInput, + Win32Error(HRESULT), +} + +impl fmt::Display for GlyphRunOutlineError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidInput => write!(f, "Invalid input"), + Self::Win32Error(code) => write!(f, "{:#x}", code), + } + } +} + +impl error::Error for GlyphRunOutlineError {} diff --git a/third_party/rust/dwrote/src/font_family.rs b/third_party/rust/dwrote/src/font_family.rs @@ -26,41 +26,66 @@ impl FontFamily { (*self.native.get()).as_raw() } + #[deprecated(note = "Use `family_name` instead.")] pub fn name(&self) -> String { + self.family_name().unwrap() + } + + pub fn family_name(&self) -> Result<String, HRESULT> { + let mut family_names: *mut IDWriteLocalizedStrings = ptr::null_mut(); unsafe { - let mut family_names: *mut IDWriteLocalizedStrings = ptr::null_mut(); let hr = (*self.native.get()).GetFamilyNames(&mut family_names); - assert!(hr == 0); - - get_locale_string(&mut ComPtr::from_raw(family_names)) + if hr != 0 { + return Err(hr); + } + Ok(get_locale_string(&mut ComPtr::from_raw(family_names))) } } + #[deprecated(note = "Use `first_matching_font` instead.")] pub fn get_first_matching_font( &self, weight: FontWeight, stretch: FontStretch, style: FontStyle, ) -> Font { + self.first_matching_font(weight, stretch, style).unwrap() + } + + pub fn first_matching_font( + &self, + weight: FontWeight, + stretch: FontStretch, + style: FontStyle, + ) -> Result<Font, HRESULT> { + let mut font: *mut IDWriteFont = ptr::null_mut(); unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); let hr = (*self.native.get()).GetFirstMatchingFont( weight.t(), stretch.t(), style.t(), &mut font, ); - assert!(hr == 0); - Font::take(ComPtr::from_raw(font)) + if hr != 0 { + return Err(hr); + } + Ok(Font::take(ComPtr::from_raw(font))) } } + #[deprecated(note = "Use `font_collection` instead.")] pub fn get_font_collection(&self) -> FontCollection { + self.font_collection().unwrap() + } + + pub fn font_collection(&self) -> Result<FontCollection, HRESULT> { + let mut collection: *mut IDWriteFontCollection = ptr::null_mut(); unsafe { - let mut collection: *mut IDWriteFontCollection = ptr::null_mut(); let hr = (*self.native.get()).GetFontCollection(&mut collection); - assert!(hr == 0); - FontCollection::take(ComPtr::from_raw(collection)) + if hr != 0 { + return Err(hr); + } + Ok(FontCollection::take(ComPtr::from_raw(collection))) } } @@ -68,12 +93,19 @@ impl FontFamily { unsafe { (*self.native.get()).GetFontCount() } } + #[deprecated(note = "Use `font` instead.")] pub fn get_font(&self, index: u32) -> Font { + self.font(index).unwrap() + } + + pub fn font(&self, index: u32) -> Result<Font, HRESULT> { + let mut font: *mut IDWriteFont = ptr::null_mut(); unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); let hr = (*self.native.get()).GetFont(index, &mut font); - assert!(hr == 0); - Font::take(ComPtr::from_raw(font)) + if hr != 0 { + return Err(hr); + } + Ok(Font::take(ComPtr::from_raw(font))) } } } diff --git a/third_party/rust/dwrote/src/font_file.rs b/third_party/rust/dwrote/src/font_file.rs @@ -11,6 +11,7 @@ use std::ptr; use std::slice; use std::sync::Arc; use winapi::ctypes::c_void; +use winapi::shared::winerror::S_OK; use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile, IDWriteFontFileStream}; use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteLocalFontFileLoader}; use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE, DWRITE_FONT_FILE_TYPE_UNKNOWN}; @@ -63,8 +64,13 @@ impl FontFile { } } + #[deprecated(since = "0.11.2", note = "please use `new_from_buffer` instead")] pub fn new_from_data(data: Arc<Vec<u8>>) -> Option<FontFile> { - let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); + Self::new_from_buffer(data) + } + + pub fn new_from_buffer(data: Arc<dyn AsRef<[u8]> + Sync + Send>) -> Option<FontFile> { + let (font_file, font_file_stream, key) = DataFontHelper::register_font_buffer(data); let mut ff = FontFile { native: UnsafeCell::new(font_file), @@ -80,8 +86,13 @@ impl FontFile { } } + #[deprecated(since = "0.11.2", note = "please use `analyze_buffer` instead")] pub fn analyze_data(data: Arc<Vec<u8>>) -> u32 { - let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); + Self::analyze_buffer(data) + } + + pub fn analyze_buffer(buffer: Arc<dyn AsRef<[u8]> + Sync + Send>) -> u32 { + let (font_file, font_file_stream, key) = DataFontHelper::register_font_buffer(buffer); let mut ff = FontFile { native: UnsafeCell::new(font_file), @@ -111,7 +122,7 @@ impl FontFile { } } self.face_type = face_type; - num_faces as u32 + num_faces } pub fn take(native: ComPtr<IDWriteFontFile>) -> FontFile { @@ -137,68 +148,91 @@ impl FontFile { (*self.native.get()).clone() } + #[deprecated(note = "Use `font_file_bytes` instead.")] + pub fn get_font_file_bytes(&self) -> Vec<u8> { + self.font_file_bytes().unwrap() + } + // This is a helper to read the contents of this FontFile, // without requiring callers to deal with loaders, keys, // or streams. - pub fn get_font_file_bytes(&self) -> Vec<u8> { + pub fn font_file_bytes(&self) -> Result<Vec<u8>, HRESULT> { unsafe { let mut ref_key: *const c_void = ptr::null(); let mut ref_key_size: u32 = 0; let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut(); let hr = (*self.native.get()).GetLoader(&mut loader); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let loader = ComPtr::from_raw(loader); let mut stream: *mut IDWriteFontFileStream = ptr::null_mut(); let hr = loader.CreateStreamFromKey(ref_key, ref_key_size, &mut stream); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let stream = ComPtr::from_raw(stream); let mut file_size: u64 = 0; let hr = stream.GetFileSize(&mut file_size); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let mut fragment_start: *const c_void = ptr::null(); let mut fragment_context: *mut c_void = ptr::null_mut(); let hr = stream.ReadFileFragment(&mut fragment_start, 0, file_size, &mut fragment_context); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let in_ptr = slice::from_raw_parts(fragment_start as *const u8, file_size as usize); let bytes = in_ptr.to_vec(); stream.ReleaseFileFragment(fragment_context); - bytes + Ok(bytes) } } + #[deprecated(note = "Use `font_file_path` instead.")] + pub fn get_font_file_path(&self) -> Option<PathBuf> { + self.font_file_path().ok() + } + // This is a helper to get the path of a font file, // without requiring callers to deal with loaders. - pub fn get_font_file_path(&self) -> Option<PathBuf> { + pub fn font_file_path(&self) -> Result<PathBuf, HRESULT> { unsafe { let mut ref_key: *const c_void = ptr::null(); let mut ref_key_size: u32 = 0; let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut(); let hr = (*self.native.get()).GetLoader(&mut loader); - assert!(hr == 0); + if hr != S_OK { + return Err(hr); + } let loader = ComPtr::from_raw(loader); - let local_loader: ComPtr<IDWriteLocalFontFileLoader> = match loader.cast() { - Ok(local_loader) => local_loader, - Err(_) => return None, - }; + let local_loader: ComPtr<IDWriteLocalFontFileLoader> = loader.cast()?; let mut file_path_len = 0; let hr = local_loader.GetFilePathLengthFromKey(ref_key, ref_key_size, &mut file_path_len); - assert_eq!(hr, 0); + if hr != S_OK { + return Err(hr); + } let mut file_path_buf = vec![0; file_path_len as usize + 1]; let hr = local_loader.GetFilePathFromKey( @@ -207,13 +241,15 @@ impl FontFile { file_path_buf.as_mut_ptr(), file_path_len + 1, ); - assert_eq!(hr, 0); + if hr != S_OK { + return Err(hr); + } if let Some(&0) = file_path_buf.last() { file_path_buf.pop(); } - Some(PathBuf::from(OsString::from_wide(&file_path_buf))) + Ok(PathBuf::from(OsString::from_wide(&file_path_buf))) } } diff --git a/third_party/rust/dwrote/src/font_file_loader_impl.rs b/third_party/rust/dwrote/src/font_file_loader_impl.rs @@ -22,7 +22,7 @@ use crate::com_helpers::*; struct FontFileLoader; -const FontFileLoaderVtbl: &'static IDWriteFontFileLoaderVtbl = &IDWriteFontFileLoaderVtbl { +const FontFileLoaderVtbl: &IDWriteFontFileLoaderVtbl = &IDWriteFontFileLoaderVtbl { parent: implement_iunknown!(static IDWriteFontFileLoader, FontFileLoader), CreateStreamFromKey: { unsafe extern "system" fn CreateStreamFromKey( @@ -80,10 +80,10 @@ unsafe impl Sync for FontFileLoader {} struct FontFileStream { refcount: atomic::AtomicUsize, key: usize, - data: Arc<Vec<u8>>, + data: Arc<dyn AsRef<[u8]> + Sync + Send>, } -const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileStreamVtbl { +const FontFileStreamVtbl: &IDWriteFontFileStreamVtbl = &IDWriteFontFileStreamVtbl { parent: implement_iunknown!(IDWriteFontFileStream, FontFileStream), ReadFileFragment: { unsafe extern "system" fn ReadFileFragment( @@ -95,11 +95,12 @@ const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileS ) -> HRESULT { let this = FontFileStream::from_interface(This); *fragmentContext = ptr::null_mut(); - if (fileOffset + fragmentSize) as usize > this.data.len() { + let data = (*this.data).as_ref(); + if (fileOffset + fragmentSize) as usize > data.len() { return E_INVALIDARG; } let index = fileOffset as usize; - *fragmentStart = this.data[index..].as_ptr() as *const c_void; + *fragmentStart = data[index..].as_ptr() as *const c_void; S_OK } ReadFileFragment @@ -118,7 +119,7 @@ const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileS fileSize: *mut UINT64, ) -> HRESULT { let this = FontFileStream::from_interface(This); - *fileSize = this.data.len() as UINT64; + *fileSize = (*this.data).as_ref().len() as UINT64; S_OK } GetFileSize @@ -135,7 +136,7 @@ const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileS }; impl FontFileStream { - pub fn new(key: usize, data: Arc<Vec<u8>>) -> FontFileStream { + pub fn new(key: usize, data: Arc<dyn AsRef<[u8]> + Sync + Send>) -> FontFileStream { FontFileStream { refcount: AtomicUsize::new(1), key, @@ -178,7 +179,7 @@ unsafe impl Sync for FontFileLoaderWrapper {} lazy_static! { static ref FONT_FILE_STREAM_MAP: Mutex<HashMap<usize, FontFileStreamPtr>> = - { Mutex::new(HashMap::new()) }; + Mutex::new(HashMap::new()); static ref FONT_FILE_LOADER: Mutex<FontFileLoaderWrapper> = { unsafe { let ffl_native = FontFileLoader::new(); @@ -190,11 +191,11 @@ lazy_static! { }; } -pub struct DataFontHelper; +pub(crate) struct DataFontHelper; impl DataFontHelper { - pub fn register_font_data( - font_data: Arc<Vec<u8>>, + pub(crate) fn register_font_buffer( + font_data: Arc<dyn AsRef<[u8]> + Sync + Send>, ) -> ( ComPtr<IDWriteFontFile>, ComPtr<IDWriteFontFileStream>, diff --git a/third_party/rust/dwrote/src/geometry_sink_impl.rs b/third_party/rust/dwrote/src/geometry_sink_impl.rs @@ -64,7 +64,7 @@ unsafe extern "system" fn GeometrySinkImpl_BeginFigure( _: D2D1_FIGURE_BEGIN, ) { let this = GeometrySinkImpl::from_interface(this); - (*this) + this .outline_builder .move_to(start_point.x, start_point.y) } @@ -75,7 +75,7 @@ unsafe extern "system" fn GeometrySinkImpl_EndFigure( ) { let this = GeometrySinkImpl::from_interface(this); if figure_end == D2D1_FIGURE_END_CLOSED { - (*this).outline_builder.close() + this.outline_builder.close() } } @@ -87,7 +87,7 @@ unsafe extern "system" fn GeometrySinkImpl_AddLines( let this = GeometrySinkImpl::from_interface(this); let points = slice::from_raw_parts(points, points_count as usize); for point in points { - (*this).outline_builder.line_to(point.x, point.y) + this.outline_builder.line_to(point.x, point.y) } } @@ -99,7 +99,7 @@ unsafe extern "system" fn GeometrySinkImpl_AddBeziers( let this = GeometrySinkImpl::from_interface(this); let beziers = slice::from_raw_parts(beziers, beziers_count as usize); for bezier in beziers { - (*this).outline_builder.curve_to( + this.outline_builder.curve_to( bezier.point1.x, bezier.point1.y, bezier.point2.x, diff --git a/third_party/rust/dwrote/src/helpers.rs b/third_party/rust/dwrote/src/helpers.rs @@ -19,7 +19,7 @@ lazy_static! { locale } }; - static ref EN_US_LOCALE: Vec<wchar_t> = { OsStr::new("en-us").to_wide_null() }; + static ref EN_US_LOCALE: Vec<wchar_t> = OsStr::new("en-us").to_wide_null(); } pub fn get_locale_string(strings: &mut ComPtr<IDWriteLocalizedStrings>) -> String { @@ -51,7 +51,6 @@ pub fn get_locale_string(strings: &mut ComPtr<IDWriteLocalizedStrings>) -> Strin // ToWide from https://github.com/retep998/wio-rs/blob/master/src/wide.rs pub trait ToWide { - fn to_wide(&self) -> Vec<u16>; fn to_wide_null(&self) -> Vec<u16>; } @@ -59,9 +58,6 @@ impl<T> ToWide for T where T: AsRef<OsStr>, { - fn to_wide(&self) -> Vec<u16> { - self.as_ref().encode_wide().collect() - } fn to_wide_null(&self) -> Vec<u16> { self.as_ref().encode_wide().chain(Some(0)).collect() } diff --git a/third_party/rust/dwrote/src/lib.rs b/third_party/rust/dwrote/src/lib.rs @@ -19,15 +19,15 @@ include!("types.rs"); use std::ffi::CString; use std::ptr; -use winapi::Interface; use winapi::shared::guiddef::REFIID; use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE_SHARED; use winapi::um::dwrite::IDWriteFactory; use winapi::um::dwrite::IDWriteRenderingParams; +use winapi::um::dwrite::DWRITE_FACTORY_TYPE; +use winapi::um::dwrite::DWRITE_FACTORY_TYPE_SHARED; use winapi::um::unknwnbase::IUnknown; use winapi::um::winnt::LPCSTR; +use winapi::Interface; pub use winapi::um::winnt::HRESULT; diff --git a/third_party/rust/dwrote/src/test.rs b/third_party/rust/dwrote/src/test.rs @@ -12,8 +12,7 @@ fn test_system_family_iter() { assert!(count > 0); assert!(system_fc .families_iter() - .find(|f| f.name() == "Arial") - .is_some()); + .any(|f| f.name() == "Arial")); } #[test] @@ -47,10 +46,10 @@ fn test_get_font_file_bytes() { ); let face = arial_font.create_font_face(); let files = face.get_files(); - assert!(files.len() > 0); + assert!(!files.is_empty()); let bytes = files[0].get_font_file_bytes(); - assert!(bytes.len() > 0); + assert!(!bytes.is_empty()); } #[test] @@ -86,13 +85,17 @@ fn test_create_font_file_from_bytes() { ); let face = arial_font.create_font_face(); let files = face.get_files(); - assert!(files.len() > 0); + assert!(!files.is_empty()); let bytes = files[0].get_font_file_bytes(); - assert!(bytes.len() > 0); + assert!(!bytes.is_empty()); // now go back - let new_font = FontFile::new_from_data(Arc::new(bytes)); + #[allow(deprecated)] + let new_font = FontFile::new_from_data(Arc::new(bytes.clone())); + assert!(new_font.is_some()); + + let new_font = FontFile::new_from_buffer(Arc::new(bytes)); assert!(new_font.is_some()); let _new_font = new_font.unwrap(); @@ -148,8 +151,8 @@ fn test_glyph_image() { let rp = RenderingParams::create_for_primary_monitor(); rt.set_pixels_per_dip(device_pixel_ratio); rt.draw_glyph_run( - x as f32, - y as f32, + x, + y, DWRITE_MEASURING_MODE_NATURAL, &face, em_size, diff --git a/third_party/rust/dwrote/src/text_analysis_source.rs b/third_party/rust/dwrote/src/text_analysis_source.rs @@ -13,7 +13,7 @@ use crate::com_helpers::Com; pub struct TextAnalysisSource<'a> { native: ComPtr<IDWriteTextAnalysisSource>, - phantom: PhantomData<CustomTextAnalysisSourceImpl<'a>> + phantom: PhantomData<CustomTextAnalysisSourceImpl<'a>>, } impl<'a> TextAnalysisSource<'a> { @@ -28,10 +28,13 @@ impl<'a> TextAnalysisSource<'a> { ) -> TextAnalysisSource<'a> { let native = unsafe { ComPtr::from_raw( - CustomTextAnalysisSourceImpl::from_text_native(inner, text).into_interface() + CustomTextAnalysisSourceImpl::from_text_native(inner, text).into_interface(), ) }; - TextAnalysisSource { native, phantom: PhantomData } + TextAnalysisSource { + native, + phantom: PhantomData, + } } /// Create a new custom TextAnalysisSource for the given text and a trait @@ -51,10 +54,13 @@ impl<'a> TextAnalysisSource<'a> { text, number_subst, ) - .into_interface() + .into_interface(), ) }; - TextAnalysisSource { native, phantom: PhantomData } + TextAnalysisSource { + native, + phantom: PhantomData, + } } pub fn as_ptr(&self) -> *mut IDWriteTextAnalysisSource { diff --git a/third_party/rust/dwrote/src/text_analysis_source_impl.rs b/third_party/rust/dwrote/src/text_analysis_source_impl.rs @@ -38,7 +38,7 @@ pub trait TextAnalysisSourceMethods { /// /// Return locale and length of text (in utf-16 code units) for which the /// locale is valid. - fn get_locale_name<'a>(&'a self, text_position: u32) -> (Cow<'a, str>, u32); + fn get_locale_name(&self, text_position: u32) -> (Cow<'_, str>, u32); /// Get the text direction for the paragraph. fn get_paragraph_reading_direction(&self) -> DWRITE_READING_DIRECTION; @@ -80,7 +80,7 @@ impl<'a> CustomTextAnalysisSourceImpl<'a> { inner: Box<dyn TextAnalysisSourceMethods + 'a>, text: Cow<'a, [wchar_t]>, ) -> CustomTextAnalysisSourceImpl<'a> { - assert!(text.len() <= (std::u32::MAX as usize)); + assert!(text.len() <= (u32::MAX as usize)); CustomTextAnalysisSourceImpl { _refcount: AtomicUsize::new(1), inner, @@ -100,7 +100,7 @@ impl<'a> CustomTextAnalysisSourceImpl<'a> { text: Cow<'a, [wchar_t]>, number_subst: NumberSubstitution, ) -> CustomTextAnalysisSourceImpl<'a> { - assert!(text.len() <= (std::u32::MAX as usize)); + assert!(text.len() <= (u32::MAX as usize)); CustomTextAnalysisSourceImpl { _refcount: AtomicUsize::new(1), inner, @@ -137,11 +137,15 @@ unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetLocaleName( let (locale, text_len) = this.inner.get_locale_name(text_position); // Copy the locale data into the buffer - for (i, c) in OsStr::new(&*locale).encode_wide().chain(Some(0)).enumerate() { + for (i, c) in OsStr::new(&*locale) + .encode_wide() + .chain(Some(0)) + .enumerate() + { // -1 here is deliberate: it ensures that we never write to the last character in // this.locale_buf, so that the buffer is always null-terminated. if i >= this.locale_buf.len() - 1 { - break + break; } *this.locale_buf.get_unchecked_mut(i) = c; @@ -169,8 +173,8 @@ unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetNumberSubstitution( let com_ptr = &number_subst.native; com_ptr.AddRef(); com_ptr.as_raw() - }, - None => std::ptr::null_mut() + } + None => std::ptr::null_mut(), }; S_OK diff --git a/third_party/rust/dwrote/src/types.rs b/third_party/rust/dwrote/src/types.rs @@ -41,7 +41,7 @@ impl FontWeight { FontWeight::ExtraBold=> 800, FontWeight::Black=> 900, FontWeight::ExtraBlack=> 950, - FontWeight::Unknown(v) => *v as u32 + FontWeight::Unknown(v) => { *v } } } pub fn from_u32(v: u32) -> FontWeight {