Skip to content

fix(skia): migrate to skia-safe 0.99 so docs.rs can build - #216

Merged
LeadcodeDev merged 2 commits into
mainfrom
fix/skia-pathbuilder
Aug 20, 2026
Merged

fix(skia): migrate to skia-safe 0.99 so docs.rs can build#216
LeadcodeDev merged 2 commits into
mainfrom
fix/skia-pathbuilder

Conversation

@LeadcodeDev

@LeadcodeDev LeadcodeDev commented Aug 20, 2026

Copy link
Copy Markdown
Owner

rustmotion 0.6.1 published 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.0 has a docs.rs-specific path in its build script, and it is
broken:

DETECTED DOCS_RS BUILD
COPYING bindings_docs.rs to OUT_DIR/skia/bindings.rs
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }

Not ours: skia-safe 0.82.0 has no docs on docs.rs either. 0.99.0 does.

What actually broke

One thing. Skia made SkPath immutable and moved construction into
SkPathBuilder, so the mutating methods left Path.

let mut path = PathBuilder::new();
path.move_to(a);
path.line_to(b);
path.close();
canvas.draw_path(&path.detach(), &paint);

22 of the 99 files that touch skia_safe needed changing. Canvas, Paint,
Surface, ImageInfo, FontStyle, Shader and Data crossed seventeen minor
versions untouched.

Three details a reviewer should not have to rediscover:

  • add_rect, add_oval and add_rrect gained a third argument (start_index).
    add_circle already had three and is unchanged.
  • Path::from_svg still returns a real Path. A blanket rewrite of
    draw_path(&path puts a .detach() there. It does not compile, which is
    fortunate — the failure mode had it compiled would have been silent.
  • chart/radar.rs draws one path twice, filled then stroked. It is the only site
    where snapshot() is right and detach() would empty the builder too early.

Path::get_point is deprecated; replaced by points().first(), same semantics.

The gradient API, migrated too

25 sites were initially held under #[allow(deprecated)] and the migration
deferred 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: u32 could only carry one
boolean. 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:

  • the old Flags::default() was empty(), the new Interpolation::default() is
    in_premul: No, and no site in this repository ever passed flags
    explicitly
    — so the defaults line up;
  • every call site uses Interpolation::default(); no colour space is introduced
    where one was not already present. shape.rs keeps the srgb space it declared;
  • TileMode did not disappear from the API, it moved into Colors next to the
    colours it applies to.

One implicit behaviour had to be made explicit: the deprecated sweep() took an
optional angle range where None meant a full 0..360 turn. The replacement makes
the tuple mandatory, so that range is now written at the call site.

Verification

  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo test --workspace1241 passed, 0 failed, 10 ignored

The pixel regression suite is what matters here, not the compiler. A misplaced
detach() compiles perfectly and renders a missing shape; those tests are what
say the paths still draw the same.

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
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Aug 20, 2026
@LeadcodeDev LeadcodeDev self-assigned this Aug 20, 2026
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
LeadcodeDev merged commit ac39010 into main Aug 20, 2026
3 checks passed
@LeadcodeDev
LeadcodeDev deleted the fix/skia-pathbuilder branch August 20, 2026 10:34
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs.rs cannot build 0.6.1: skia-safe 0.82 is broken there

1 participant