thorvg 0.3.0
A large API-hardening and ergonomics release. The headline themes are
type-safety (enums and parameter structs replacing primitives), a
shared color module, sealed traits, lifetime-correct borrowed views,
and a sweep of memory-safety fixes around FFI ownership.
Changed (breaking)
- Colors are now typed.
Text::set_color/set_outlinetake
Rgb;Shapefill/stroke and gradientColorStoptakeRgba.
Rawu8channel arguments are gone.Rgb/Rgbalive in a shared
colormodule, which now also hostsColorSpace. EngineOptionis a plain enum (None/Default/SmartRender)
matching the C++ engine's exact-equality semantics, instead of a
bitflags newtype.Shapepaint order is aPaintOrderenum (FillThenStroke/
StrokeThenFill) instead of abool.- Shape primitives take parameter structs —
RectandCircle
(with builders andDefault) replace long positional argument lists. - Scene effects take parameter structs —
GaussianBlur,
DropShadow,Tint, andTritone(builders +Default); blur
direction and border are now enums rather than ints. Effect methods
were renamed for consistency. - Factory methods return
Resultacross paint/scene/picture/text/
animation/saver/accessor/gradient, instead of panicking or returning
bare handles on allocation failure. set_mask/set_clipconsume the paint by value, modelling the
ownership transfer to the C engine (prevents double-free / leaks).Canvas::pushandScene::pushrenamed toaddfor C API parity.Picture::load_datatakes a typedMimeTypeenum instead of a
string.- Font-loading API moved from
TexttoThorvg(it is engine-global
state, not per-text). Thorvg::initsignature is gated on thethreadsfeature.PaintandCanvasare now sealed traits — they cannot be
implemented downstream.from_rawconversions are exhaustive forPaintTypeand
MaskMethod, andShapeenums (FillRule,StrokeCap,StrokeJoin)
are exhaustive.
Added
- Typed
Path/PathCommand/Segmentmodel;Shape::pathreturns
it andShape::append_pathcloses the round-trip.Segmentsnow
implementssize_hint. Text::textgetter (C parity).Shape::set_stroke_radial_gradient(C parity).- Chainable
Matrixtransform combinators. Point::newplus rounded-out ergonomics and enum-variant docs.GlCanvas/WgCanvasGPU target builders for API parity (the
vendored build still strips the GPU engine).- Safe, closure-based
Picture::set_asset_resolver;BorrowedAccessor
andBorrowedPaintare passed intofor_eachvisitors. impl From<NulError> for Error, soCStringconstruction works with
?.- Gradient kinds are enumerated in
PaintType.
Fixed
- Memory leaks in
Paint::set_clip/set_maskand a leaked gradient
handle inShape(now exposed as aBorrowedGradientview). Leaks are
memory-safe; the related double-free is listed under Security below. Paint's mask getter called the wrong C API; replaced with the correct
one.Animation::pictureandPicture::get_paintnow return stable borrows
(&Picture/BorrowedPaint) instead of a rebuilt wrapper / raw
handle — clearer ownership. (Neither was unsound in prior releases.)- Hardened the newly safe, closure-based
Picture::set_asset_resolver
(new in this release, see Added) so its trampoline pointer stays stable
across moves of the picture.
Security
Several FFI-ownership and bounds bugs that were unsound — reachable
from safe code without unsafe — are fixed in this release. All of
them affect published versions ≤ 0.2.0 (the APIs date back to the
initial release) and are fixed in 0.3.0; users should upgrade.
0.1.0 and 0.1.1 were already yanked.
- Use-after-free in
Saver::save_animation. - Dangling input buffers —
Picture::load_data/Picture::load_raw
andText::load_font_datadid not tie the borrowed slice's lifetime to
the consuming object, so the engine could read freed memory after the
slice was dropped. The buffer lifetime is now enforced by the type
system. - Out-of-bounds read in
Picture::load_raw— the pixel-buffer length
was not validated against the declaredwidth × height; now
bounds-checked. - Out-of-bounds write in
SwCanvas::set_target— the target buffer
size computation could overflow and accept an undersized buffer; now
overflow-checked. - Double-free via
Paint::set_clip/set_mask— these took the
clipper/mask by reference while the engine took ownership, so the Rust
wrapper and the engine could both free it. They now consume the paint
by value. - Undefined behaviour on panic across FFI — a panic in a user closure
passed toAccessor::for_eachunwound through anextern "C"
trampoline (UB). Such closures are now wrapped incatch_unwindunder
std; theno_stdpanic policy is documented.
Removed
- The unused, unsafe
Accessor::setraw-FFI escape hatch.
Deprecated
Gradient::get_transform— renamed totransformfor consistency
withPaint::transform.