Skip to content

Commit ac39010

Browse files
authored
fix(skia): migrate to skia-safe 0.99 so docs.rs can build (#216)
* fix(skia): migrate to skia-safe 0.99 so docs.rs can build skia-bindings 0.82.0 has a broken docs.rs path: it detects the build, announces it is copying bindings_docs.rs into OUT_DIR, and the copy fails with NotFound. The build script exits 1 and rustdoc never runs, which is why 0.6.1 published with no documentation. skia-safe 0.82.0 has no docs there either, for the same reason; 0.99.0 does. The only breaking change that reaches us is Path becoming immutable: Skia moved construction into SkPathBuilder, so the mutating methods left Path. Of the 99 files that touch skia_safe, 22 needed work — Canvas, Paint, Surface, ImageInfo, FontStyle, Shader and Data crossed seventeen minor versions unchanged. Three details worth keeping: - add_rect, add_oval and add_rrect gained a third argument (start_index); add_circle already had three and is untouched. - Path::from_svg still returns a real Path. A blanket rewrite of draw_path(&path adds a .detach() there that does not compile — and would have been worse if it had. - chart/radar.rs draws one path twice, filled then stroked. That is the single place snapshot() is correct and detach() would empty the builder too early. get_point is replaced by points().first(), same semantics. The 25 remaining deprecations are all on the gradient shader API and are held under narrowly scoped allow(deprecated) rather than migrated: the replacement drops TileMode from the signature, so moving it blind changes rendering in ways that look plausible. Tracked in #215. Closes #214 * refactor(skia): migrate off the deprecated gradient shader API Deprecated in skia-safe 0.93. Not a rename: Skia gained CSS Color 4 style interpolation, and the old `flags: u32` could only carry one boolean. The new model needs three orthogonal parameters — premultiplied or not, which colour space to interpolate in, and how to traverse hue — so the API was restructured around Gradient { Colors, Interpolation }. Rendering is preserved by construction rather than by hope: the old Flags::default() was empty(), the new Interpolation::default() is in_premul: No, and no site in this repository ever passed flags explicitly. Every call site uses Interpolation::default(), and no colour space is introduced anywhere it was not already present — shape.rs keeps the srgb space it declared before. TileMode did not disappear, it moved into Colors alongside the colours it applies to. One behaviour was implicit and had to be made explicit: the deprecated sweep() took an optional angle range, and None meant a full 0..360 turn. The replacement makes the tuple mandatory, so that range is now written at the call site. Closes #215
1 parent c5a61f2 commit ac39010

30 files changed

Lines changed: 289 additions & 252 deletions

Cargo.lock

Lines changed: 67 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rustmotion-components/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ lottie-native = ["dep:thorvg", "dep:dashmap"]
1515

1616
[dependencies]
1717
rustmotion-core.workspace = true
18-
skia-safe = "0.82"
18+
skia-safe = "0.99"
1919
serde = { version = "1", features = ["derive"] }
2020
serde_json = "1"
2121
schemars = "0.8"

crates/rustmotion-components/src/arrow.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use schemars::JsonSchema;
22
use serde::{Deserialize, Serialize};
3-
use skia_safe::{Canvas, PaintStyle, Path, PathMeasure, Point};
3+
use skia_safe::{Canvas, PaintStyle, Path, PathBuilder, PathMeasure, Point};
44

55
use rustmotion_core::css::CssStyle;
66
use rustmotion_core::engine::animator::AnimatedProperties;
@@ -87,7 +87,7 @@ rustmotion_core::impl_traits!(Arrow {
8787
impl Arrow {
8888
/// Build the bezier path for this arrow (without arrowheads).
8989
fn build_path(&self) -> Path {
90-
let mut path = Path::new();
90+
let mut path = PathBuilder::new();
9191
path.move_to((self.x1, self.y1));
9292

9393
if let (Some(cp1), Some(cp2)) = (&self.cp1, &self.cp2) {
@@ -112,7 +112,7 @@ impl Arrow {
112112
path.line_to((self.x2, self.y2));
113113
}
114114

115-
path
115+
path.detach()
116116
}
117117

118118
/// Draw an arrowhead at the given position along the path.
@@ -146,7 +146,7 @@ impl Arrow {
146146
let angle = tangent.y.atan2(tangent.x);
147147
let half_angle = std::f32::consts::PI / 6.0; // 30 degrees
148148

149-
let mut arrow_path = Path::new();
149+
let mut arrow_path = PathBuilder::new();
150150
arrow_path.move_to(pos);
151151
arrow_path.line_to((
152152
pos.x - size * (angle - half_angle).cos(),
@@ -161,7 +161,7 @@ impl Arrow {
161161
let mut arrow_paint = paint.clone();
162162
arrow_paint.set_path_effect(None);
163163
arrow_paint.set_stroke_cap(skia_safe::PaintCap::Round);
164-
canvas.draw_path(&arrow_path, &arrow_paint);
164+
canvas.draw_path(&arrow_path.detach(), &arrow_paint);
165165
}
166166

167167
fn paint(&self, canvas: &Canvas, props: &AnimatedProperties) {

crates/rustmotion-components/src/callout.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustmotion_core::css::CssStyle;
22
use rustmotion_core::error::Result;
33
use schemars::JsonSchema;
44
use serde::{Deserialize, Serialize};
5-
use skia_safe::{Canvas, PaintStyle, Path, RRect, Rect};
5+
use skia_safe::{Canvas, PaintStyle, Path, PathBuilder, RRect, Rect};
66

77
use rustmotion_core::engine::animator::AnimatedProperties;
88
use rustmotion_core::engine::layout_pass::BoxLayout;
@@ -89,7 +89,7 @@ impl Callout {
8989
}
9090

9191
fn arrow_path(&self, w: f32, h: f32) -> Path {
92-
let mut path = Path::new();
92+
let mut path = PathBuilder::new();
9393
let a = self.arrow_size;
9494
// Overlap the arrow base 1px into the bubble to eliminate anti-aliasing seam
9595
let overlap = 1.0;
@@ -129,7 +129,7 @@ impl Callout {
129129
}
130130
}
131131

132-
path
132+
path.detach()
133133
}
134134
}
135135

crates/rustmotion-components/src/chart/funnel.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustmotion_core::error::Result;
2-
use skia_safe::{Canvas, PaintStyle, Path};
2+
use skia_safe::{Canvas, PaintStyle, PathBuilder};
33

44
use rustmotion_core::engine::renderer::{
55
draw_text_with_fallback, emoji_typeface, measure_text_with_fallback, paint_from_hex,
@@ -67,13 +67,13 @@ impl Chart {
6767
paint.set_style(PaintStyle::Fill);
6868
paint.set_anti_alias(true);
6969

70-
let mut path = Path::new();
70+
let mut path = PathBuilder::new();
7171
path.move_to((top_x, y_top));
7272
path.line_to((top_x + top_w, y_top));
7373
path.line_to((bot_x + bot_w, y_bot));
7474
path.line_to((bot_x, y_bot));
7575
path.close();
76-
canvas.draw_path(&path, &paint);
76+
canvas.draw_path(&path.detach(), &paint);
7777

7878
if self.show_labels {
7979
if let Some(label) = &dp.label {
@@ -148,13 +148,13 @@ impl Chart {
148148
paint.set_style(PaintStyle::Fill);
149149
paint.set_anti_alias(true);
150150

151-
let mut path = Path::new();
151+
let mut path = PathBuilder::new();
152152
path.move_to((x_left, left_y));
153153
path.line_to((x_right, right_y));
154154
path.line_to((x_right, right_y + right_h));
155155
path.line_to((x_left, left_y + left_h));
156156
path.close();
157-
canvas.draw_path(&path, &paint);
157+
canvas.draw_path(&path.detach(), &paint);
158158

159159
if self.show_labels {
160160
if let Some(label) = &dp.label {

crates/rustmotion-components/src/chart/line.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustmotion_core::error::Result;
2-
use skia_safe::{Canvas, Color, PaintStyle, Path, Point, Rect};
2+
use skia_safe::gradient::{self, Colors, Gradient};
3+
use skia_safe::{Canvas, Color, Color4f, PaintStyle, PathBuilder, Point, Rect};
34

45
use rustmotion_core::engine::renderer::{paint_from_hex, parse_hex_color};
56

@@ -67,8 +68,8 @@ impl Chart {
6768
return Ok(());
6869
}
6970

70-
let mut path = Path::new();
71-
let mut fill_path = Path::new();
71+
let mut path = PathBuilder::new();
72+
let mut fill_path = PathBuilder::new();
7273

7374
for (i, dp) in self.data.iter().enumerate() {
7475
let x = ml + (i as f32 / (n - 1) as f32) * chart_w;
@@ -102,14 +103,14 @@ impl Chart {
102103
let mut fill_paint = paint_from_hex(line_color);
103104
fill_paint.set_style(PaintStyle::Fill);
104105
fill_paint.set_alpha_f(0.15);
105-
canvas.draw_path(&fill_path, &fill_paint);
106+
canvas.draw_path(&fill_path.detach(), &fill_paint);
106107

107108
// Line stroke
108109
let mut line_paint = paint_from_hex(line_color);
109110
line_paint.set_style(PaintStyle::Stroke);
110111
line_paint.set_stroke_width(2.5);
111112
line_paint.set_anti_alias(true);
112-
canvas.draw_path(&path, &line_paint);
113+
canvas.draw_path(&path.detach(), &line_paint);
113114

114115
// Dots
115116
for (i, dp) in self.data.iter().enumerate() {
@@ -168,8 +169,8 @@ impl Chart {
168169
})
169170
.collect();
170171

171-
let mut line_path = Path::new();
172-
let mut fill_path = Path::new();
172+
let mut line_path = PathBuilder::new();
173+
let mut fill_path = PathBuilder::new();
173174

174175
if self.smooth && pts.len() >= 3 {
175176
// Catmull-Rom -> cubic bezier for smooth curves
@@ -227,12 +228,12 @@ impl Chart {
227228
let top_color = Color::from_argb((self.fill_opacity * 255.0) as u8, r, g, b);
228229
let bottom_color = Color::from_argb(0, r, g, b);
229230

230-
let shader = skia_safe::shader::Shader::linear_gradient(
231+
let colors4f = [Color4f::from(top_color), Color4f::from(bottom_color)];
232+
let stops = Colors::new(&colors4f, None, skia_safe::TileMode::Clamp, None);
233+
let grad = Gradient::new(stops, gradient::Interpolation::default());
234+
let shader = gradient::shaders::linear_gradient(
231235
(Point::new(0.0, mt), Point::new(0.0, mt + chart_h)),
232-
skia_safe::gradient_shader::GradientShaderColors::Colors(&[top_color, bottom_color]),
233-
None,
234-
skia_safe::TileMode::Clamp,
235-
None,
236+
&grad,
236237
None,
237238
);
238239

@@ -241,15 +242,15 @@ impl Chart {
241242
fill_paint.set_style(PaintStyle::Fill);
242243
fill_paint.set_anti_alias(true);
243244
fill_paint.set_shader(shader);
244-
canvas.draw_path(&fill_path, &fill_paint);
245+
canvas.draw_path(&fill_path.detach(), &fill_paint);
245246
}
246247

247248
// Line stroke
248249
let mut line_paint = paint_from_hex(line_color);
249250
line_paint.set_style(PaintStyle::Stroke);
250251
line_paint.set_stroke_width(2.5);
251252
line_paint.set_anti_alias(true);
252-
canvas.draw_path(&line_path, &line_paint);
253+
canvas.draw_path(&line_path.detach(), &line_paint);
253254

254255
// Dots
255256
for &(x, y) in &pts {

0 commit comments

Comments
 (0)