From 1fb081a1f098043bca869ca3577af59cd654d673 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 13 Aug 2026 13:40:50 +0200 Subject: [PATCH] chore(deps): move pf-console-ui from skia-safe 0.87 to 0.99 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Twelve skia-safe releases (0.88 … 0.99), carrying Skia milestones 140 through 150, every one of them breaking under 0.x semver. Only three of those changes actually reach this crate — the Vulkan surface/backend-texture path, the textlayout/paragraph typography and RuntimeEffect all came through untouched: * m143 (skia-safe 0.91) DELETED SkPath's mutating API. `Path::new()` followed by `move_to`/`line_to`/`arc_to`/`close` no longer compiles at all — geometry is built through `PathBuilder` now and frozen with `snapshot()`/`detach()`. That is the entire error list: 34 E0599s over eight call sites (the hint-bar triangles and the PlayStation triangle in `glyphs.rs`, the chevron / space / backspace / check icons in `widgets.rs`, the padlock shackle in `screens/home.rs`). Each becomes a `PathBuilder` detached at the draw call, so the path is still built and thrown away once per draw exactly as before. * 0.93 deprecated the `gradient_shader` module in favour of `gradient`. Only a warning, but the Format/clippy gate runs `-D warnings`, so it is a hard break for us. The three gradients — the panel stroke in `theme.rs`, the connect-overlay vignette in `shell/overlays.rs`, the host monogram in `screens/home.rs` — now build a `gradient::Gradient` from `gradient::Colors::new_evenly_spaced` plus `Interpolation::default()`. That default (unpremul interpolation, destination colour space, shorter hue) is what the old `flags: None` argument mapped to, so the pixels do not move. The new API takes `Color4f` directly, which drops the `.to_color()` 8-bit round-trip the old signature forced. * 0.98 deprecated `vk::BackendContext::new` in favour of a builder (upstream #1292). `skia_overlay.rs` now calls `BackendContext::new_builder(...)` + `build()`, passing `max_api_version: None` so Skia keeps deriving its cap from `vkEnumerateInstanceVersion()` — bit-for-bit what `new()` passed. `build()` is the unsafe half, so the SAFETY proof moved down onto it. `ash` is untouched and stays on the workspace's exact `=0.38.0+1.3.281` pin: skia-safe lists ash only as a DEV dependency, so the bump cannot reach it. The prebuilt-binary assumption still holds — verified from the build log, not from the release page: skia-bindings printed `DOWNLOAD AND INSTALL SUCCEEDED` for `skia-binaries-a25a0fdb7d90429aa2d1-x86_64-unknown-linux-gnu-jpegd-jpege-pdf-textlayout-vulkan`, so no CI leg compiles Skia from source. The asset name DID change: `jpeg` joined skia-safe's default feature set between 0.87 and 0.99, so `jpegd-jpege` is now in the name. We take defaults, so the JPEG codecs came along — which is a fix in disguise, since `screens/library.rs` hands host poster art straight to `Image::from_encoded`, and JPEG posters used to fall out as "undecodable". The Cargo.toml comment now records the verified asset names and the silent-source- build trap for the next bump. Verified on 192.168.1.21, x86_64-unknown-linux-gnu, toolchain 1.96.0: cargo build -p pf-console-ui exit 0 cargo clippy -p pf-console-ui --all-targets -- -D warnings exit 0 cargo test -p pf-console-ui 82 passed, 1 ignored cargo fmt --all --check exit 0 --- Cargo.lock | 71 +++------------------- crates/pf-console-ui/Cargo.toml | 13 +++- crates/pf-console-ui/src/glyphs.rs | 18 +++--- crates/pf-console-ui/src/screens/home.rs | 24 ++++---- crates/pf-console-ui/src/shell/overlays.rs | 22 +++---- crates/pf-console-ui/src/skia_overlay.rs | 28 +++++---- crates/pf-console-ui/src/theme.rs | 18 +++--- crates/pf-console-ui/src/widgets.rs | 18 +++--- 8 files changed, 86 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba9a7be0..e9e0a2f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3454,7 +3454,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.13+spec-1.1.0", + "toml_edit", ] [[package]] @@ -4524,15 +4524,6 @@ dependencies = [ "syn 3.0.3", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "serde_spanned" version = "1.1.1" @@ -4636,30 +4627,28 @@ checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "skia-bindings" -version = "0.87.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704242769235d2ffe66a2a0a3002661262fc4af08d32807c362d7b0160ee703c" +checksum = "3e2d1c3ebd697c0cbded0145e9204a38fa6b268446051b7196d0a096414ea7f3" dependencies = [ "bindgen", "cc", "flate2", "heck", - "lazy_static", "pkg-config", "regex", "serde_json", "tar", - "toml 0.8.23", + "toml 1.1.4+spec-1.1.0", ] [[package]] name = "skia-safe" -version = "0.87.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7d94f3e7537c71ad4cf132eb26e3be8c8a886ed3649c4525c089041fc312b2" +checksum = "9f512ac418a64194842dd05566320805dad1c957c521039db2486fd6368865bc" dependencies = [ "bitflags 2.13.1", - "lazy_static", "skia-bindings", ] @@ -5039,18 +5028,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - [[package]] name = "toml" version = "0.9.12+spec-1.1.0" @@ -5059,7 +5036,7 @@ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.1", + "serde_spanned", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", @@ -5074,22 +5051,13 @@ checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.1", + "serde_spanned", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", "winnow 1.0.4", ] -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -5108,20 +5076,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_write", - "winnow 0.7.15", -] - [[package]] name = "toml_edit" version = "0.25.13+spec-1.1.0" @@ -5143,12 +5097,6 @@ dependencies = [ "winnow 1.0.4", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "toml_writer" version = "1.1.2+spec-1.1.0" @@ -6169,9 +6117,6 @@ name = "winnow" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] [[package]] name = "winnow" diff --git a/crates/pf-console-ui/Cargo.toml b/crates/pf-console-ui/Cargo.toml index dc8b9911..284271e8 100644 --- a/crates/pf-console-ui/Cargo.toml +++ b/crates/pf-console-ui/Cargo.toml @@ -22,7 +22,18 @@ pf-client-core = { path = "../pf-client-core", default-features = false } # the typography the console library needs (~15 MB stripped, prebuilt binaries exist for # this feature set on x86_64-unknown-linux-gnu AND x86_64-pc-windows-msvc — a source # build is never triggered on either). -skia-safe = { version = "0.87", features = ["vulkan", "textlayout"] } +# +# The prebuilt-binary claim is the whole reason this dep is affordable, so re-verify it on +# EVERY bump: the build log must say `DOWNLOAD AND INSTALL SUCCEEDED`. skia-bindings does not +# fail when no matching asset exists — it silently falls back to a gn/ninja build of Skia from +# source, which turns a 2-minute CI leg into a multi-hour one. Verified at 0.99.0, both targets: +# skia-binaries-a25a0fdb7d90429aa2d1--jpegd-jpege-pdf-textlayout-vulkan.tar.gz +# ⚠ The asset name CHANGED across this bump — at 0.87 it was `-pdf-textlayout-vulkan`, +# because `jpeg` was not yet in skia-safe's DEFAULT feature set (0.87: binary-cache, embed-icudtl, +# pdf; 0.99: + jpeg). We take defaults, so the JPEG codecs came along with the bump. That is a +# feature here rather than bloat: `screens/library.rs` feeds host poster art straight to +# `Image::from_encoded`, which silently returned `None` for JPEG posters before. +skia-safe = { version = "0.99", features = ["vulkan", "textlayout"] } ash = { version = "0.38", features = ["loaded"] } anyhow = "1" diff --git a/crates/pf-console-ui/src/glyphs.rs b/crates/pf-console-ui/src/glyphs.rs index 89db0a83..a0a02138 100644 --- a/crates/pf-console-ui/src/glyphs.rs +++ b/crates/pf-console-ui/src/glyphs.rs @@ -7,7 +7,7 @@ use crate::theme::{fg, Fonts, W}; use punktfunk_core::config::GamepadPref; -use skia_safe::{Canvas, Paint, Path, Point, RRect, Rect}; +use skia_safe::{Canvas, Paint, PathBuilder, Point, RRect, Rect}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub(crate) enum GlyphStyle { @@ -294,12 +294,12 @@ fn draw_glyph( let r = BADGE_D * k / 2.0; let (cx, cyf) = ((x + r) as f32, cy as f32); let (tw, th) = ((5.5 * k) as f32, (4.5 * k) as f32); - let mut up = Path::new(); + let mut up = PathBuilder::new(); up.move_to((cx, cyf - th)); up.line_to((cx - tw, cyf + th)); up.line_to((cx + tw, cyf + th)); up.close(); - canvas.draw_path(&up, &Paint::new(fg(0.85), None)); + canvas.draw_path(&up.detach(), &Paint::new(fg(0.85), None)); } Resolved::Adjust => { // ◀ ▶ — two small solid triangles. @@ -308,18 +308,18 @@ fn draw_glyph( let (tw, th) = ((4.5 * k) as f32, (5.5 * k) as f32); let gap = (2.6 * k) as f32; let paint = Paint::new(fg(0.85), None); - let mut left = Path::new(); + let mut left = PathBuilder::new(); left.move_to((cx - gap, cyf - th)); left.line_to((cx - gap - tw, cyf)); left.line_to((cx - gap, cyf + th)); left.close(); - canvas.draw_path(&left, &paint); - let mut right = Path::new(); + canvas.draw_path(&left.detach(), &paint); + let mut right = PathBuilder::new(); right.move_to((cx + gap, cyf - th)); right.line_to((cx + gap + tw, cyf)); right.line_to((cx + gap, cyf + th)); right.close(); - canvas.draw_path(&right, &paint); + canvas.draw_path(&right.detach(), &paint); } Resolved::Key(text) => { let w = keycap_w(fonts, text, k); @@ -377,12 +377,12 @@ fn draw_ps_shape(canvas: &Canvas, face: Face, center: Point, r: f32, stroke: f32 } Face::Y => { // △ - let mut tri = Path::new(); + let mut tri = PathBuilder::new(); tri.move_to((cx, cy - r * 1.2)); tri.line_to((cx + r * 1.15, cy + r * 0.85)); tri.line_to((cx - r * 1.15, cy + r * 0.85)); tri.close(); - canvas.draw_path(&tri, &p); + canvas.draw_path(&tri.detach(), &p); } } } diff --git a/crates/pf-console-ui/src/screens/home.rs b/crates/pf-console-ui/src/screens/home.rs index 0a36ec1a..2600a40d 100644 --- a/crates/pf-console-ui/src/screens/home.rs +++ b/crates/pf-console-ui/src/screens/home.rs @@ -13,7 +13,7 @@ use crate::pointer::{Pointer, PointerKind}; use crate::screens::{ConnectIntent, Ctx, Outbox, Screen}; use crate::theme::{accent, fg, Fonts, PanelStroke, ONLINE_GREEN, W}; use pf_client_core::gamepad::{MenuDir, MenuEvent, MenuPulse}; -use skia_safe::{Canvas, Color4f, MaskFilter, Paint, Path, Point, RRect, Rect}; +use skia_safe::{Canvas, Color4f, MaskFilter, Paint, PathBuilder, Point, RRect, Rect}; const TILE_W: f64 = 340.0; const TILE_H: f64 = 224.0; @@ -526,18 +526,20 @@ fn draw_monogram(canvas: &Canvas, fonts: &Fonts, name: &str, filled: bool, x: f6 let rr = RRect::new_rect_xy(badge, (15.0 * k) as f32, (15.0 * k) as f32); if filled { let mut p = Paint::default(); - p.set_shader(skia_safe::gradient_shader::linear( + let colors = [accent(1.0), accent(0.68)]; + p.set_shader(skia_safe::gradient::shaders::linear_gradient( ( Point::new(badge.left, badge.top), Point::new(badge.left, badge.bottom), ), - skia_safe::gradient_shader::GradientShaderColors::Colors(&[ - accent(1.0).to_color(), - accent(0.68).to_color(), - ]), - None, - skia_safe::TileMode::Clamp, - None, + &skia_safe::gradient::Gradient::new( + skia_safe::gradient::Colors::new_evenly_spaced( + &colors, + skia_safe::TileMode::Clamp, + None, + ), + skia_safe::gradient::Interpolation::default(), + ), None, )); canvas.draw_rrect(rr, &p); @@ -586,7 +588,7 @@ fn draw_lock(canvas: &Canvas, x: f64, y: f64, k: f64) { p.set_style(skia_safe::PaintStyle::Stroke); p.set_stroke_width((1.6 * k) as f32); p.set_anti_alias(true); - let mut shackle = Path::new(); + let mut shackle = PathBuilder::new(); let (cx, r) = (x + body_w / 2.0, 3.2 * k); shackle.move_to(((cx - r) as f32, body_top as f32)); shackle.arc_to( @@ -600,7 +602,7 @@ fn draw_lock(canvas: &Canvas, x: f64, y: f64, k: f64) { 180.0, false, ); - canvas.draw_path(&shackle, &p); + canvas.draw_path(&shackle.detach(), &p); } #[cfg(test)] diff --git a/crates/pf-console-ui/src/shell/overlays.rs b/crates/pf-console-ui/src/shell/overlays.rs index 49075830..ac619b02 100644 --- a/crates/pf-console-ui/src/shell/overlays.rs +++ b/crates/pf-console-ui/src/shell/overlays.rs @@ -3,7 +3,7 @@ use crate::anim::{approach, ease_out_cubic}; use crate::glyphs::{hint_bar, Hint, HintKey}; use crate::theme::{fg, Fonts, PanelStroke, W}; -use skia_safe::{gradient_shader, Canvas, Paint, Point, Rect, TileMode}; +use skia_safe::{gradient, Canvas, Paint, Point, Rect, TileMode}; use super::{Shell, BOTTOM_BAND}; @@ -170,16 +170,16 @@ impl Shell { // A soft pool of shade under the centre seats the text against a bright field — // dark on a dark palette, light on a pale one, so it always separates. let mut vignette = Paint::default(); - vignette.set_shader(gradient_shader::radial( - Point::new(cx as f32, (h / 2.0) as f32), - (w.max(h) * 0.42) as f32, - gradient_shader::GradientShaderColors::Colors(&[ - crate::theme::shade(0.5).to_color(), - crate::theme::shade(0.0).to_color(), - ]), - None, - TileMode::Clamp, - None, + let shades = [crate::theme::shade(0.5), crate::theme::shade(0.0)]; + vignette.set_shader(gradient::shaders::radial_gradient( + ( + Point::new(cx as f32, (h / 2.0) as f32), + (w.max(h) * 0.42) as f32, + ), + &gradient::Gradient::new( + gradient::Colors::new_evenly_spaced(&shades, TileMode::Clamp, None), + gradient::Interpolation::default(), + ), None, )); canvas.draw_rect(Rect::from_wh(w as f32, h as f32), &vignette); diff --git a/crates/pf-console-ui/src/skia_overlay.rs b/crates/pf-console-ui/src/skia_overlay.rs index 86ad4e25..1d134eca 100644 --- a/crates/pf-console-ui/src/skia_overlay.rs +++ b/crates/pf-console-ui/src/skia_overlay.rs @@ -236,21 +236,25 @@ impl Overlay for SkiaOverlay { } } }; + let backend_builder = skvk::BackendContext::new_builder( + shared.instance.handle().as_raw() as _, + shared.physical_device.as_raw() as _, + shared.device.handle().as_raw() as _, + ( + shared.queue.as_raw() as _, + shared.queue_family_index as usize, + ), + &get_proc, + // `None` leaves Skia's `fMaxAPIVersion` at its `0` sentinel, so it caps entry-point + // validation at whatever `vkEnumerateInstanceVersion()` reports — byte-for-byte what + // the (now removed) `BackendContext::new` did. The presenter owns the instance and its + // `VkApplicationInfo`, so pinning a version here would just duplicate its choice. + None, + ); // SAFETY: the instance/physical-device/device handles come from `shared`, which owns them // and outlives this backend context, and `get_proc` above resolves through those same // handles. Skia stores them but does not take ownership — teardown stays ours. - let backend = unsafe { - skvk::BackendContext::new( - shared.instance.handle().as_raw() as _, - shared.physical_device.as_raw() as _, - shared.device.handle().as_raw() as _, - ( - shared.queue.as_raw() as _, - shared.queue_family_index as usize, - ), - &get_proc, - ) - }; + let backend = unsafe { backend_builder.build() }; let mut context = gpu::direct_contexts::make_vulkan(&backend, None) .ok_or_else(|| anyhow!("Skia DirectContext over the shared device"))?; context.set_resource_cache_limit(RESOURCE_CACHE_BYTES); diff --git a/crates/pf-console-ui/src/theme.rs b/crates/pf-console-ui/src/theme.rs index ac58f7db..3a516b27 100644 --- a/crates/pf-console-ui/src/theme.rs +++ b/crates/pf-console-ui/src/theme.rs @@ -10,8 +10,8 @@ use skia_safe::textlayout::{ FontCollection, ParagraphBuilder, ParagraphStyle, TextAlign, TextStyle, TypefaceFontProvider, }; use skia_safe::{ - gradient_shader, Canvas, Color4f, Font, FontMgr, FontStyle, MaskFilter, Paint, PathEffect, - Point, RRect, Rect, TileMode, Typeface, + gradient, Canvas, Color4f, Font, FontMgr, FontStyle, MaskFilter, Paint, PathEffect, Point, + RRect, Rect, TileMode, Typeface, }; // --- Ink ---------------------------------------------------------------------------------- @@ -166,18 +166,16 @@ pub(crate) fn panel( sp.set_color4f(accent(alpha), None); } PanelStroke::Gradient | PanelStroke::GradientDashed => { - sp.set_shader(gradient_shader::linear( + let colors = [fg(0.22), fg(0.04)]; + sp.set_shader(gradient::shaders::linear_gradient( ( Point::new(rect.left, rect.top), Point::new(rect.left, rect.bottom), ), - gradient_shader::GradientShaderColors::Colors(&[ - fg(0.22).to_color(), - fg(0.04).to_color(), - ]), - None, - TileMode::Clamp, - None, + &gradient::Gradient::new( + gradient::Colors::new_evenly_spaced(&colors, TileMode::Clamp, None), + gradient::Interpolation::default(), + ), None, )); if matches!(stroke, PanelStroke::GradientDashed) { diff --git a/crates/pf-console-ui/src/widgets.rs b/crates/pf-console-ui/src/widgets.rs index 3f481802..b454236b 100644 --- a/crates/pf-console-ui/src/widgets.rs +++ b/crates/pf-console-ui/src/widgets.rs @@ -9,7 +9,7 @@ use crate::library::{BUMP_C, BUMP_K}; use crate::pointer::{Pointer, PointerKind}; use crate::theme::{accent, fg, Fonts, PanelStroke, W}; use pf_client_core::gamepad::{MenuDir, MenuEvent, MenuPulse}; -use skia_safe::{Canvas, Paint, Path, RRect, Rect}; +use skia_safe::{Canvas, Paint, PathBuilder, RRect, Rect}; // --- Menu list ----------------------------------------------------------------------------- @@ -479,11 +479,11 @@ fn chevron(canvas: &Canvas, x: f64, cy: f64, r: f64, left: bool, alpha: f32) { p.set_stroke_width((1.8 * r / 4.0) as f32); p.set_stroke_cap(skia_safe::PaintCap::Round); p.set_anti_alias(true); - let mut path = Path::new(); + let mut path = PathBuilder::new(); path.move_to(((x - dir * r / 2.0) as f32, (cy - r) as f32)); path.line_to(((x + dir * r / 2.0) as f32, cy as f32)); path.line_to(((x - dir * r / 2.0) as f32, (cy + r) as f32)); - canvas.draw_path(&path, &p); + canvas.draw_path(&path.detach(), &p); } // --- On-screen keyboard ---------------------------------------------------------------------- @@ -785,12 +785,12 @@ fn draw_space_icon(canvas: &Canvas, cx: f64, cy: f64, k: f64, ink: skia_safe::Co // ⎵ — an underline bracket. let (w, h) = (16.0 * k, 5.0 * k); let p = stroke_paint(ink, (1.6 * k) as f32); - let mut path = Path::new(); + let mut path = PathBuilder::new(); path.move_to(((cx - w / 2.0) as f32, (cy - h / 2.0) as f32)); path.line_to(((cx - w / 2.0) as f32, (cy + h / 2.0) as f32)); path.line_to(((cx + w / 2.0) as f32, (cy + h / 2.0) as f32)); path.line_to(((cx + w / 2.0) as f32, (cy - h / 2.0) as f32)); - canvas.draw_path(&path, &p); + canvas.draw_path(&path.detach(), &p); } fn draw_backspace_icon(canvas: &Canvas, cx: f64, cy: f64, k: f64, ink: skia_safe::Color4f) { @@ -799,14 +799,14 @@ fn draw_backspace_icon(canvas: &Canvas, cx: f64, cy: f64, k: f64, ink: skia_safe let nose = 6.0 * k; let p = stroke_paint(ink, (1.6 * k) as f32); let (l, r, t, b) = (cx - w / 2.0, cx + w / 2.0, cy - h / 2.0, cy + h / 2.0); - let mut path = Path::new(); + let mut path = PathBuilder::new(); path.move_to(((l + nose) as f32, t as f32)); path.line_to((r as f32, t as f32)); path.line_to((r as f32, b as f32)); path.line_to(((l + nose) as f32, b as f32)); path.line_to((l as f32, cy as f32)); path.close(); - canvas.draw_path(&path, &p); + canvas.draw_path(&path.detach(), &p); let (xc, xr) = (cx + nose / 2.0, 2.6 * k); canvas.draw_line( ((xc - xr) as f32, (cy - xr) as f32), @@ -823,11 +823,11 @@ fn draw_backspace_icon(canvas: &Canvas, cx: f64, cy: f64, k: f64, ink: skia_safe fn draw_check(canvas: &Canvas, cx: f64, cy: f64, k: f64, ink: skia_safe::Color4f) { let p = stroke_paint(ink, (1.8 * k) as f32); let r = 5.0 * k; - let mut path = Path::new(); + let mut path = PathBuilder::new(); path.move_to(((cx - r) as f32, cy as f32)); path.line_to(((cx - r * 0.25) as f32, (cy + r * 0.7) as f32)); path.line_to(((cx + r) as f32, (cy - r * 0.7) as f32)); - canvas.draw_path(&path, &p); + canvas.draw_path(&path.detach(), &p); } #[cfg(test)]