fix(skia): migrate to skia-safe 0.99 so docs.rs can build - #216
Merged
Conversation
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
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
LeadcodeDev
added a commit
that referenced
this pull request
Aug 20, 2026
`cargo install rustmotion` could not work. The README documents it, and the crate's own description calls it "a CLI tool", but the published crate carried only a `[lib]`: the `rustmotion` binary was declared in `rustmotion-cli`, which is `publish = false`. Installing it gave a library and no command. The binary now lives in `crates/rustmotion` and `rustmotion-cli` is gone. The studio subcommand could not come along, and not for want of trying: an optional dependency does not help, because `rustmotion-studio` depends on `rustmotion`, so cargo rejects the cycle before compiling anything. No capability is lost — `rustmotion-studio` already declares its own binary of that name, so the studio is launched directly instead of through a subcommand. Moving the CLI exposed a second defect, latent while the crate was unpublished and the same class as the themes bug fixed in #216: `build.rs` walked `.claude/skills/rustmotion/` and `skills.rs` embedded `CLAUDE.md`, both outside the package directory. `cargo package` archives only what lives under the crate, so the tarball did not compile — the verify step failed on a missing SKILL.md. Both now live inside the crate, with symlinks at their old paths so Claude Code still finds them. One copy, not two: this repository already learned in #165 what a duplicated skill list costs when it drifts, and the test that caught that drift is what still guards it. The install destination is unchanged. `build.rs` embeds the path the file will be written to rather than the path it came from, and running the built binary in an empty directory writes 59 files to `.claude/skills/rustmotion/` as before.
This was referenced Aug 20, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
rustmotion 0.6.1published with no documentation: docs.rs could not build it.This moves the workspace to
skia-safe 0.99, where that build works.Closes #214. Follow-up in #215.
The cause
skia-bindings 0.82.0has a docs.rs-specific path in its build script, and it isbroken:
Not ours:
skia-safe 0.82.0has no docs on docs.rs either.0.99.0does.What actually broke
One thing. Skia made
SkPathimmutable and moved construction intoSkPathBuilder, so the mutating methods leftPath.22 of the 99 files that touch
skia_safeneeded changing.Canvas,Paint,Surface,ImageInfo,FontStyle,ShaderandDatacrossed seventeen minorversions untouched.
Three details a reviewer should not have to rediscover:
add_rect,add_ovalandadd_rrectgained a third argument (start_index).add_circlealready had three and is unchanged.Path::from_svgstill returns a realPath. A blanket rewrite ofdraw_path(&pathputs a.detach()there. It does not compile, which isfortunate — the failure mode had it compiled would have been silent.
chart/radar.rsdraws one path twice, filled then stroked. It is the only sitewhere
snapshot()is right anddetach()would empty the builder too early.Path::get_pointis deprecated; replaced bypoints().first(), same semantics.The gradient API, migrated too
25 sites were initially held under
#[allow(deprecated)]and the migrationdeferred to #215. That is no longer the case — there is no legacy left on this
branch, and #215 is closed by this PR.
Why those functions were deprecated at all (skia-safe 0.93): Skia gained CSS
Color 4 style interpolation, and the old
flags: u32could only carry oneboolean. The new model needs three orthogonal parameters — premultiplied or not,
which colour space to interpolate in, how to traverse hue — so the API moved to
Gradient { Colors, Interpolation }.Rendering is preserved by construction, not by hope:
Flags::default()wasempty(), the newInterpolation::default()isin_premul: No, and no site in this repository ever passed flagsexplicitly — so the defaults line up;
Interpolation::default(); no colour space is introducedwhere one was not already present.
shape.rskeeps the srgb space it declared;TileModedid not disappear from the API, it moved intoColorsnext to thecolours it applies to.
One implicit behaviour had to be made explicit: the deprecated
sweep()took anoptional angle range where
Nonemeant a full 0..360 turn. The replacement makesthe tuple mandatory, so that range is now written at the call site.
Verification
cargo clippy --workspace --all-targets -- -D warnings— cleancargo test --workspace— 1241 passed, 0 failed, 10 ignoredThe pixel regression suite is what matters here, not the compiler. A misplaced
detach()compiles perfectly and renders a missing shape; those tests are whatsay the paths still draw the same.