Merge pull request #8451 from penpot/superalex-update-skia-version

🎉 Update skia version
This commit is contained in:
Elena Torró 2026-02-25 11:07:00 +01:00 committed by GitHub
commit 12a1cb1d32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 169 additions and 175 deletions

86
render-wasm/Cargo.lock generated
View File

@ -202,9 +202,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.0" version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]] [[package]]
name = "heck" name = "heck"
@ -214,9 +214,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.7.1" version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -253,12 +253,6 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.161" version = "0.2.161"
@ -468,18 +462,27 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.210" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.210" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -500,11 +503,11 @@ dependencies = [
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.8" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
dependencies = [ dependencies = [
"serde", "serde_core",
] ]
[[package]] [[package]]
@ -515,9 +518,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]] [[package]]
name = "skia-bindings" name = "skia-bindings"
version = "0.87.0" version = "0.93.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704242769235d2ffe66a2a0a3002661262fc4af08d32807c362d7b0160ee703c" checksum = "2359f7e30c9da3f322f8ca3d4ec0abbc12a40035ce758309db0cdab07b5d4476"
dependencies = [ dependencies = [
"bindgen", "bindgen",
"cc", "cc",
@ -532,13 +535,12 @@ dependencies = [
[[package]] [[package]]
name = "skia-safe" name = "skia-safe"
version = "0.87.0" version = "0.93.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f7d94f3e7537c71ad4cf132eb26e3be8c8a886ed3649c4525c089041fc312b2" checksum = "7f9e837ea9d531c9efee8f980bfcdb7226b21db0285b0c3171d8be745829f940"
dependencies = [ dependencies = [
"base64", "base64",
"bitflags", "bitflags",
"lazy_static",
"percent-encoding", "percent-encoding",
"skia-bindings", "skia-bindings",
"skia-svg-macros", "skia-svg-macros",
@ -579,38 +581,43 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.19" version = "1.0.3+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c"
dependencies = [ dependencies = [
"serde", "indexmap",
"serde_core",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit", "toml_parser",
"toml_writer",
"winnow",
] ]
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.6.8" version = "1.0.0+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
dependencies = [ dependencies = [
"serde", "serde_core",
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_parser"
version = "0.22.22" version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [ dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow", "winnow",
] ]
[[package]]
name = "toml_writer"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.13" version = "1.0.13"
@ -775,12 +782,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.20" version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "xattr" name = "xattr"

View File

@ -25,7 +25,7 @@ gl = "0.14.0"
glam = "0.24.2" glam = "0.24.2"
indexmap = "2.7.1" indexmap = "2.7.1"
macros = { path = "macros" } macros = { path = "macros" }
skia-safe = { version = "0.87.0", default-features = false, features = [ skia-safe = { version = "0.93.1", default-features = false, features = [
"gl", "gl",
"svg", "svg",
"textlayout", "textlayout",

View File

@ -10,7 +10,7 @@ fi
export BUILD_NAME="${BUILD_NAME:-render-wasm}" export BUILD_NAME="${BUILD_NAME:-render-wasm}"
export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"wasm32-unknown-emscripten"}; export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"wasm32-unknown-emscripten"};
export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.87.0/skia-binaries-e551f334ad5cbdf43abf-wasm32-unknown-emscripten-gl-svg-textlayout-binary-cache-webp.tar.gz"} export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.93.1/skia-binaries-319323662b1685a112f5-wasm32-unknown-emscripten-gl-svg-textlayout-binary-cache-webp.tar.gz"}
# 256 MB of initial heap to perform less # 256 MB of initial heap to perform less
# initial calls to memory grow. # initial calls to memory grow.

View File

@ -11,7 +11,7 @@ fi
. ./_build_env . ./_build_env
export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"wasm32-unknown-emscripten"}; export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"wasm32-unknown-emscripten"};
export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.87.0/skia-binaries-e551f334ad5cbdf43abf-wasm32-unknown-emscripten-gl-svg-textlayout-binary-cache-webp.tar.gz"} export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.93.1/skia-binaries-319323662b1685a112f5-wasm32-unknown-emscripten-gl-svg-textlayout-binary-cache-webp.tar.gz"}
ALLOWED_RULES="-D static_mut_refs" ALLOWED_RULES="-D static_mut_refs"

View File

@ -356,7 +356,7 @@ impl Bounds {
} }
pub fn from_rect(r: &Rect) -> Self { pub fn from_rect(r: &Rect) -> Self {
let [nw, ne, se, sw] = r.to_quad(); let [nw, ne, se, sw] = r.to_quad(None);
Self::new(nw, ne, se, sw) Self::new(nw, ne, se, sw)
} }

View File

@ -477,30 +477,32 @@ pub fn debug_render_bool_paths(
paint.set_alpha_f(1.0); paint.set_alpha_f(1.0);
paint.set_style(skia::PaintStyle::Stroke); paint.set_style(skia::PaintStyle::Stroke);
let mut path = skia::Path::default(); let path = {
path.move_to((b.1.start.x as f32, b.1.start.y as f32)); let mut pb = skia::PathBuilder::new();
pb.move_to((b.1.start.x as f32, b.1.start.y as f32));
match b.1.handles { match b.1.handles {
BezierHandles::Linear => { BezierHandles::Linear => {
path.line_to((b.1.end.x as f32, b.1.end.y as f32)); pb.line_to((b.1.end.x as f32, b.1.end.y as f32));
}
BezierHandles::Quadratic { handle } => {
pb.quad_to(
(handle.x as f32, handle.y as f32),
(b.1.end.x as f32, b.1.end.y as f32),
);
}
BezierHandles::Cubic {
handle_start,
handle_end,
} => {
pb.cubic_to(
(handle_start.x as f32, handle_start.y as f32),
(handle_end.x as f32, handle_end.y as f32),
(b.1.end.x as f32, b.1.end.y as f32),
);
}
} }
BezierHandles::Quadratic { handle } => { pb.detach()
path.quad_to( };
(handle.x as f32, handle.y as f32),
(b.1.end.x as f32, b.1.end.y as f32),
);
}
BezierHandles::Cubic {
handle_start,
handle_end,
} => {
path.cubic_to(
(handle_start.x as f32, handle_start.y as f32),
(handle_end.x as f32, handle_end.y as f32),
(b.1.end.x as f32, b.1.end.y as f32),
);
}
}
canvas.draw_path(&path, &paint); canvas.draw_path(&path, &paint);
let mut v1 = b.1.normal(TValue::Parametric(1.0)); let mut v1 = b.1.normal(TValue::Parametric(1.0));

View File

@ -51,15 +51,18 @@ fn draw_image_fill(
canvas.clip_rect(container, skia::ClipOp::Intersect, antialias); canvas.clip_rect(container, skia::ClipOp::Intersect, antialias);
} }
Type::Circle => { Type::Circle => {
let mut oval_path = skia::Path::new(); let oval_path = {
oval_path.add_oval(container, None); let mut pb = skia::PathBuilder::new();
pb.add_oval(container, None, None);
pb.detach()
};
canvas.clip_path(&oval_path, skia::ClipOp::Intersect, antialias); canvas.clip_path(&oval_path, skia::ClipOp::Intersect, antialias);
} }
shape_type @ (Type::Path(_) | Type::Bool(_)) => { shape_type @ (Type::Path(_) | Type::Bool(_)) => {
if let Some(path) = shape_type.path() { if let Some(path) = shape_type.path() {
if let Some(path_transform) = path_transform { if let Some(path_transform) = path_transform {
canvas.clip_path( canvas.clip_path(
path.to_skia_path().transform(&path_transform), &path.to_skia_path().make_transform(&path_transform),
skia::ClipOp::Intersect, skia::ClipOp::Intersect,
antialias, antialias,
); );

View File

@ -24,7 +24,11 @@ pub fn render_overlay(zoom: f32, canvas: &skia::Canvas, shape: &Shape, shapes: S
cell.anchor + hv + vv, cell.anchor + hv + vv,
cell.anchor + vv, cell.anchor + vv,
]; ];
let polygon = skia::Path::polygon(&points, true, None, None); let polygon = {
let mut pb = skia::PathBuilder::new();
pb.add_polygon(&points, true);
pb.detach()
};
canvas.draw_path(&polygon, &paint); canvas.draw_path(&polygon, &paint);
} }
} }

View File

@ -83,8 +83,11 @@ fn draw_stroke_on_circle(
if let Some(clip_op) = stroke.clip_op() { if let Some(clip_op) = stroke.clip_op() {
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint); let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
canvas.save_layer(&layer_rec); canvas.save_layer(&layer_rec);
let mut clip_path = skia::Path::new(); let clip_path = {
clip_path.add_oval(rect, None); let mut pb = skia::PathBuilder::new();
pb.add_oval(rect, None, None);
pb.detach()
};
canvas.clip_path(&clip_path, clip_op, antialias); canvas.clip_path(&clip_path, clip_op, antialias);
canvas.draw_oval(stroke_rect, &paint); canvas.draw_oval(stroke_rect, &paint);
canvas.restore(); canvas.restore();
@ -153,8 +156,9 @@ fn draw_stroke_on_path(
blur: Option<&ImageFilter>, blur: Option<&ImageFilter>,
antialias: bool, antialias: bool,
) { ) {
let mut skia_path = path.to_skia_path(); let skia_path = path
skia_path.transform(path_transform.unwrap_or(&Matrix::default())); .to_skia_path()
.make_transform(path_transform.unwrap_or(&Matrix::default()));
let is_open = path.is_open(); let is_open = path.is_open();
@ -174,15 +178,7 @@ fn draw_stroke_on_path(
} }
} }
handle_stroke_caps( handle_stroke_caps(&skia_path, stroke, canvas, is_open, paint, blur, antialias);
&mut skia_path,
stroke,
canvas,
is_open,
paint,
blur,
antialias,
);
} }
fn handle_stroke_cap( fn handle_stroke_cap(
@ -224,7 +220,7 @@ fn handle_stroke_cap(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn handle_stroke_caps( fn handle_stroke_caps(
path: &mut skia::Path, path: &skia::Path,
stroke: &Stroke, stroke: &Stroke,
canvas: &skia::Canvas, canvas: &skia::Canvas,
is_open: bool, is_open: bool,
@ -232,8 +228,7 @@ fn handle_stroke_caps(
blur: Option<&ImageFilter>, blur: Option<&ImageFilter>,
_antialias: bool, _antialias: bool,
) { ) {
let mut points = vec![Point::default(); path.count_points()]; let mut points = path.points().to_vec();
path.get_points(&mut points);
// Curves can have duplicated points, so let's remove consecutive duplicated points // Curves can have duplicated points, so let's remove consecutive duplicated points
points.dedup(); points.dedup();
let c_points = points.len(); let c_points = points.len();
@ -304,13 +299,16 @@ fn draw_square_cap(
let mut transformed_points = points; let mut transformed_points = points;
matrix.map_points(&mut transformed_points, &points); matrix.map_points(&mut transformed_points, &points);
let mut path = skia::Path::new(); let path = {
path.move_to(Point::new(center.x, center.y)); let mut pb = skia::PathBuilder::new();
path.move_to(transformed_points[0]); pb.move_to(Point::new(center.x, center.y));
path.line_to(transformed_points[1]); pb.move_to(transformed_points[0]);
path.line_to(transformed_points[2]); pb.line_to(transformed_points[1]);
path.line_to(transformed_points[3]); pb.line_to(transformed_points[2]);
path.close(); pb.line_to(transformed_points[3]);
pb.close();
pb.detach()
};
canvas.draw_path(&path, paint); canvas.draw_path(&path, paint);
} }
@ -338,13 +336,15 @@ fn draw_arrow_cap(
let mut transformed_points = points; let mut transformed_points = points;
matrix.map_points(&mut transformed_points, &points); matrix.map_points(&mut transformed_points, &points);
let mut path = skia::Path::new(); let path = {
path.move_to(transformed_points[1]); let mut pb = skia::PathBuilder::new();
path.line_to(transformed_points[0]); pb.move_to(transformed_points[1]);
path.line_to(transformed_points[2]); pb.line_to(transformed_points[0]);
path.move_to(Point::new(center.x, center.y)); pb.line_to(transformed_points[2]);
path.line_to(transformed_points[0]); pb.move_to(Point::new(center.x, center.y));
pb.line_to(transformed_points[0]);
pb.detach()
};
canvas.draw_path(&path, paint); canvas.draw_path(&path, paint);
} }
@ -372,12 +372,14 @@ fn draw_triangle_cap(
let mut transformed_points = points; let mut transformed_points = points;
matrix.map_points(&mut transformed_points, &points); matrix.map_points(&mut transformed_points, &points);
let mut path = skia::Path::new(); let path = {
path.move_to(transformed_points[0]); let mut pb = skia::PathBuilder::new();
path.line_to(transformed_points[1]); pb.move_to(transformed_points[0]);
path.line_to(transformed_points[2]); pb.line_to(transformed_points[1]);
path.close(); pb.line_to(transformed_points[2]);
pb.close();
pb.detach()
};
canvas.draw_path(&path, paint); canvas.draw_path(&path, paint);
} }
@ -441,8 +443,7 @@ fn draw_image_stroke_in_container(
shape_type @ (Type::Path(_) | Type::Bool(_)) => { shape_type @ (Type::Path(_) | Type::Bool(_)) => {
if let Some(p) = shape_type.path() { if let Some(p) = shape_type.path() {
canvas.save(); canvas.save();
let mut path = p.to_skia_path(); let path = p.to_skia_path().make_transform(&path_transform.unwrap());
path.transform(&path_transform.unwrap());
let stroke_kind = stroke.render_kind(p.is_open()); let stroke_kind = stroke.render_kind(p.is_open());
match stroke_kind { match stroke_kind {
StrokeKind::Inner => { StrokeKind::Inner => {
@ -464,7 +465,7 @@ fn draw_image_stroke_in_container(
canvas.draw_path(&path, &thin_paint); canvas.draw_path(&path, &thin_paint);
} }
handle_stroke_caps( handle_stroke_caps(
&mut path, &path,
stroke, stroke,
canvas, canvas,
is_open, is_open,
@ -504,8 +505,7 @@ fn draw_image_stroke_in_container(
// Clear outer stroke for paths if necessary. When adding an outer stroke we need to empty the stroke added too in the inner area. // Clear outer stroke for paths if necessary. When adding an outer stroke we need to empty the stroke added too in the inner area.
if let Type::Path(p) = &shape.shape_type { if let Type::Path(p) = &shape.shape_type {
if stroke.render_kind(p.is_open()) == StrokeKind::Outer { if stroke.render_kind(p.is_open()) == StrokeKind::Outer {
let mut path = p.to_skia_path(); let path = p.to_skia_path().make_transform(&path_transform.unwrap());
path.transform(&path_transform.unwrap());
let mut clear_paint = skia::Paint::default(); let mut clear_paint = skia::Paint::default();
clear_paint.set_blend_mode(skia::BlendMode::Clear); clear_paint.set_blend_mode(skia::BlendMode::Clear);
clear_paint.set_anti_alias(antialias); clear_paint.set_anti_alias(antialias);

View File

@ -456,11 +456,7 @@ impl Surfaces {
self.current.height() - TILE_SIZE_MULTIPLIER * self.margins.height, self.current.height() - TILE_SIZE_MULTIPLIER * self.margins.height,
); );
let snapshot = self.current.image_snapshot(); let tile_image_opt = self.current.image_snapshot_with_bounds(rect);
let mut direct_context = self.current.direct_context();
let tile_image_opt = snapshot
.make_subset(direct_context.as_mut(), rect)
.or_else(|| self.current.image_snapshot_with_bounds(rect));
if let Some(tile_image) = tile_image_opt { if let Some(tile_image) = tile_image_opt {
// Draw to cache first (takes reference), then move to tile cache // Draw to cache first (takes reference), then move to tile cache

View File

@ -1348,7 +1348,7 @@ impl Shape {
if let Some(path) = self.shape_type.path() { if let Some(path) = self.shape_type.path() {
let mut skia_path = path.to_skia_path(); let mut skia_path = path.to_skia_path();
if let Some(path_transform) = self.to_path_transform() { if let Some(path_transform) = self.to_path_transform() {
skia_path.transform(&path_transform); skia_path = skia_path.make_transform(&path_transform);
} }
if let Some(svg_attrs) = &self.svg_attrs { if let Some(svg_attrs) = &self.svg_attrs {
if svg_attrs.fill_rule == FillRule::Evenodd { if svg_attrs.fill_rule == FillRule::Evenodd {

View File

@ -51,10 +51,10 @@ impl Gradient {
rect.left + self.end.0 * rect.width(), rect.left + self.end.0 * rect.width(),
rect.top + self.end.1 * rect.height(), rect.top + self.end.1 * rect.height(),
); );
skia::shader::Shader::linear_gradient( skia::gradient_shader::linear(
(start, end), (start, end),
self.colors.as_slice(), self.colors.as_slice(),
self.offsets.as_slice(), Some(self.offsets.as_slice()),
skia::TileMode::Clamp, skia::TileMode::Clamp,
None, None,
None, None,
@ -83,11 +83,11 @@ impl Gradient {
transform.pre_scale((self.width * rect.width() / rect.height(), 1.), None); transform.pre_scale((self.width * rect.width() / rect.height(), 1.), None);
transform.pre_translate((-center.x, -center.y)); transform.pre_translate((-center.x, -center.y));
skia::shader::Shader::radial_gradient( skia::gradient_shader::radial(
center, center,
distance, distance,
self.colors.as_slice(), self.colors.as_slice(),
self.offsets.as_slice(), Some(self.offsets.as_slice()),
skia::TileMode::Clamp, skia::TileMode::Clamp,
None, None,
Some(&transform), Some(&transform),

View File

@ -29,40 +29,28 @@ impl Default for Path {
} }
} }
fn to_verb(v: u8) -> skia::path::Verb {
match v {
0 => skia::path::Verb::Move,
1 => skia::path::Verb::Line,
2 => skia::path::Verb::Quad,
3 => skia::path::Verb::Conic,
4 => skia::path::Verb::Cubic,
5 => skia::path::Verb::Close,
_ => skia::path::Verb::Done,
}
}
impl Path { impl Path {
pub fn new(segments: Vec<Segment>) -> Self { pub fn new(segments: Vec<Segment>) -> Self {
let mut skia_path = skia::Path::new(); let mut pb = skia::PathBuilder::new();
let mut start = None; let mut start = None;
for segment in segments.iter() { for segment in segments.iter() {
let destination = match *segment { let destination = match *segment {
Segment::MoveTo(xy) => { Segment::MoveTo(xy) => {
start = Some(xy); start = Some(xy);
skia_path.move_to(xy); pb.move_to(xy);
None None
} }
Segment::LineTo(xy) => { Segment::LineTo(xy) => {
skia_path.line_to(xy); pb.line_to(xy);
Some(xy) Some(xy)
} }
Segment::CurveTo((c1, c2, xy)) => { Segment::CurveTo((c1, c2, xy)) => {
skia_path.cubic_to(c1, c2, xy); pb.cubic_to(c1, c2, xy);
Some(xy) Some(xy)
} }
Segment::Close => { Segment::Close => {
skia_path.close(); pb.close();
None None
} }
}; };
@ -71,11 +59,12 @@ impl Path {
if math::is_close_to(destination.0, start.0) if math::is_close_to(destination.0, start.0)
&& math::is_close_to(destination.1, start.1) && math::is_close_to(destination.1, start.1)
{ {
skia_path.close(); pb.close();
} }
} }
} }
let skia_path = pb.detach();
let open = subpaths::is_open_path(&segments); let open = subpaths::is_open_path(&segments);
Self { Self {
@ -86,38 +75,31 @@ impl Path {
} }
pub fn from_skia_path(path: skia::Path) -> Self { pub fn from_skia_path(path: skia::Path) -> Self {
let nv = path.count_verbs(); let verbs = path.verbs();
let mut verbs = vec![0; nv]; let points = path.points();
path.get_verbs(&mut verbs);
let np = path.count_points();
let mut points = Vec::with_capacity(np);
points.resize(np, skia::Point::default());
path.get_points(&mut points);
let mut segments = Vec::new(); let mut segments = Vec::new();
let mut current_point = 0; let mut current_point = 0;
for verb in verbs { for verb in verbs {
let verb = to_verb(verb);
match verb { match verb {
skia::path::Verb::Move => { skia::PathVerb::Move => {
let p = points[current_point]; let p = points[current_point];
segments.push(Segment::MoveTo((p.x, p.y))); segments.push(Segment::MoveTo((p.x, p.y)));
current_point += 1; current_point += 1;
} }
skia::path::Verb::Line => { skia::PathVerb::Line => {
let p = points[current_point]; let p = points[current_point];
segments.push(Segment::LineTo((p.x, p.y))); segments.push(Segment::LineTo((p.x, p.y)));
current_point += 1; current_point += 1;
} }
skia::path::Verb::Quad => { skia::PathVerb::Quad => {
let p1 = points[current_point]; let p1 = points[current_point];
let p2 = points[current_point + 1]; let p2 = points[current_point + 1];
segments.push(Segment::CurveTo(((p1.x, p1.y), (p1.x, p1.y), (p2.x, p2.y)))); segments.push(Segment::CurveTo(((p1.x, p1.y), (p1.x, p1.y), (p2.x, p2.y))));
current_point += 2; current_point += 2;
} }
skia::path::Verb::Conic => { skia::PathVerb::Conic => {
// TODO: There is no way currently to access the conic weight // TODO: There is no way currently to access the conic weight
// to transform this correctly // to transform this correctly
let p1 = points[current_point]; let p1 = points[current_point];
@ -125,17 +107,14 @@ impl Path {
segments.push(Segment::CurveTo(((p1.x, p1.y), (p1.x, p1.y), (p2.x, p2.y)))); segments.push(Segment::CurveTo(((p1.x, p1.y), (p1.x, p1.y), (p2.x, p2.y))));
current_point += 2; current_point += 2;
} }
skia::path::Verb::Cubic => { skia::PathVerb::Cubic => {
let p1 = points[current_point]; let p1 = points[current_point];
let p2 = points[current_point + 1]; let p2 = points[current_point + 1];
let p3 = points[current_point + 2]; let p3 = points[current_point + 2];
segments.push(Segment::CurveTo(((p1.x, p1.y), (p2.x, p2.y), (p3.x, p3.y)))); segments.push(Segment::CurveTo(((p1.x, p1.y), (p2.x, p2.y), (p3.x, p3.y))));
current_point += 3; current_point += 3;
} }
skia::path::Verb::Close => { skia::PathVerb::Close => {
segments.push(Segment::Close);
}
skia::path::Verb::Done => {
segments.push(Segment::Close); segments.push(Segment::Close);
} }
} }
@ -184,7 +163,7 @@ impl Path {
_ => {} _ => {}
}); });
self.skia_path.transform(mtx); self.skia_path = self.skia_path.make_transform(mtx);
} }
pub fn segments(&self) -> &Vec<Segment> { pub fn segments(&self) -> &Vec<Segment> {

View File

@ -225,13 +225,16 @@ impl Stroke {
if self.style != StrokeStyle::Solid { if self.style != StrokeStyle::Solid {
let path_effect = match self.style { let path_effect = match self.style {
StrokeStyle::Dotted => { StrokeStyle::Dotted => {
let mut circle_path = skia::Path::new();
let width = match self.kind { let width = match self.kind {
StrokeKind::Inner => self.width, StrokeKind::Inner => self.width,
StrokeKind::Center => self.width / 2.0, StrokeKind::Center => self.width / 2.0,
StrokeKind::Outer => self.width, StrokeKind::Outer => self.width,
}; };
circle_path.add_circle((0.0, 0.0), width, None); let circle_path = {
let mut pb = skia::PathBuilder::new();
pb.add_circle((0.0, 0.0), width, None);
pb.detach()
};
let advance = self.width + 5.0; let advance = self.width + 5.0;
skia::PathEffect::path_1d( skia::PathEffect::path_1d(
&circle_path, &circle_path,

View File

@ -101,7 +101,6 @@ impl TextPaths {
if let Some((text_blob_path, text_blob_bounds)) = if let Some((text_blob_path, text_blob_bounds)) =
Self::get_text_blob_path(span_text, font, blob_offset_x, blob_offset_y) Self::get_text_blob_path(span_text, font, blob_offset_x, blob_offset_y)
{ {
let mut text_path = text_blob_path.clone();
let text_width = font.measure_text(span_text, None).0; let text_width = font.measure_text(span_text, None).0;
let decoration = style_metric.text_style.decoration(); let decoration = style_metric.text_style.decoration();
@ -111,16 +110,20 @@ impl TextPaths {
let blob_top = blob_offset_y; let blob_top = blob_offset_y;
let blob_height = text_blob_bounds.height(); let blob_height = text_blob_bounds.height();
if let Some(decoration_rect) = self.calculate_text_decoration_rect( let text_path = {
decoration.ty, let mut pb = skia::PathBuilder::new_path(&text_blob_path);
font_metrics, if let Some(decoration_rect) = self.calculate_text_decoration_rect(
blob_left, decoration.ty,
blob_top, font_metrics,
text_width, blob_left,
blob_height, blob_top,
) { text_width,
text_path.add_rect(decoration_rect, None); blob_height,
} ) {
pb.add_rect(decoration_rect, None, None);
}
pb.detach()
};
let mut paint = style_metric.text_style.foreground(); let mut paint = style_metric.text_style.foreground();
paint.set_anti_alias(antialias); paint.set_anti_alias(antialias);

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -x set -x
export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.87.0/skia-binaries-e551f334ad5cbdf43abf-x86_64-unknown-linux-gnu-gl-svg-textlayout-binary-cache-webp.tar.gz"} export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-binaries/releases/download/0.93.1/skia-binaries-319323662b1685a112f5-x86_64-unknown-linux-gnu-gl-svg-textlayout-binary-cache-webp.tar.gz"}
export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"x86_64-unknown-linux-gnu"}; export CARGO_BUILD_TARGET=${CARGO_BUILD_TARGET:-"x86_64-unknown-linux-gnu"};
_SCRIPT_DIR=$(dirname $0); _SCRIPT_DIR=$(dirname $0);

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
_SCRIPT_DIR=$(dirname $0); _SCRIPT_DIR=$(dirname $0);
export SKIA_BINARIES_URL="https://github.com/penpot/skia-binaries/releases/download/0.87.0/skia-binaries-e551f334ad5cbdf43abf-x86_64-unknown-linux-gnu-gl-svg-textlayout-binary-cache-webp.tar.gz" export SKIA_BINARIES_URL="https://github.com/penpot/skia-binaries/releases/download/0.93.1/skia-binaries-319323662b1685a112f5-x86_64-unknown-linux-gnu-gl-svg-textlayout-binary-cache-webp.tar.gz"
pushd $_SCRIPT_DIR; pushd $_SCRIPT_DIR;
cargo watch -x "test --bin render_wasm -- --show-output" cargo watch -x "test --bin render_wasm -- --show-output"