mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
canvas: Use bytemuck to remove unsafe from raqote backend (#38283)
This PR changes surface type from `Vec<u8>` to `Vec<u32>` as this is native type of raqote's backend. We used unsafe for `Vec<u8>` <-> `Vec<u32>` casting that is replaced with bytemuck. Bytemuck is already in cargo lock. Testing: Existing WPT tests. Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
daebb5a033
commit
f8d6c5646c
4 changed files with 41 additions and 57 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1064,6 +1064,7 @@ name = "canvas"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
|
"bytemuck",
|
||||||
"canvas_traits",
|
"canvas_traits",
|
||||||
"compositing_traits",
|
"compositing_traits",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
|
|
@ -33,6 +33,7 @@ base64 = "0.22.1"
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
bitflags = "2.9"
|
bitflags = "2.9"
|
||||||
bluetooth_traits = { path = "components/shared/bluetooth" }
|
bluetooth_traits = { path = "components/shared/bluetooth" }
|
||||||
|
bytemuck = "1"
|
||||||
byteorder = "1.5"
|
byteorder = "1.5"
|
||||||
canvas_traits = { path = "components/shared/canvas" }
|
canvas_traits = { path = "components/shared/canvas" }
|
||||||
cbc = "0.1.2"
|
cbc = "0.1.2"
|
||||||
|
|
|
@ -16,6 +16,7 @@ vello = ["dep:vello", "dep:pollster", "dep:futures-intrusive", "dep:peniko"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
app_units = { workspace = true }
|
app_units = { workspace = true }
|
||||||
|
bytemuck = { workspace = true, features = ["extern_crate_alloc"] }
|
||||||
canvas_traits = { workspace = true }
|
canvas_traits = { workspace = true }
|
||||||
compositing_traits = { workspace = true }
|
compositing_traits = { workspace = true }
|
||||||
crossbeam-channel = { workspace = true }
|
crossbeam-channel = { workspace = true }
|
||||||
|
|
|
@ -154,26 +154,16 @@ pub fn source(pattern: &Pattern) -> raqote::Source {
|
||||||
pattern.radius2,
|
pattern.radius2,
|
||||||
raqote::Spread::Pad,
|
raqote::Spread::Pad,
|
||||||
),
|
),
|
||||||
Pattern::Surface(pattern) => {
|
Pattern::Surface(pattern) => raqote::Source::Image(
|
||||||
#[allow(unsafe_code)]
|
raqote::Image {
|
||||||
let data = unsafe {
|
width: pattern.image.size().width as i32,
|
||||||
let data = pattern.image.as_raw_bytes();
|
height: pattern.image.size().height as i32,
|
||||||
std::slice::from_raw_parts(
|
data: bytemuck::cast_slice(pattern.image.as_raw_bytes()),
|
||||||
data.as_ptr() as *const u32,
|
},
|
||||||
data.len() / std::mem::size_of::<u32>(),
|
pattern.extend,
|
||||||
)
|
pattern.filter,
|
||||||
};
|
pattern.transform,
|
||||||
raqote::Source::Image(
|
),
|
||||||
raqote::Image {
|
|
||||||
width: pattern.image.size().width as i32,
|
|
||||||
height: pattern.image.size().height as i32,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
pattern.extend,
|
|
||||||
pattern.filter,
|
|
||||||
pattern.transform,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +178,7 @@ fn create_gradient_stops(gradient_stops: Vec<CanvasGradientStop>) -> Vec<raqote:
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericDrawTarget for raqote::DrawTarget {
|
impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
type SourceSurface = Vec<u8>; // TODO: See if we can avoid the alloc (probably?)
|
type SourceSurface = Vec<u32>; // TODO: See if we can avoid the alloc (probably?)
|
||||||
|
|
||||||
fn new(size: Size2D<u32>) -> Self {
|
fn new(size: Size2D<u32>) -> Self {
|
||||||
raqote::DrawTarget::new(size.width as i32, size.height as i32)
|
raqote::DrawTarget::new(size.width as i32, size.height as i32)
|
||||||
|
@ -206,17 +196,13 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
transform,
|
transform,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn copy_surface(
|
fn copy_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: Self::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
source: Rect<i32>,
|
source: Rect<i32>,
|
||||||
destination: Point2D<i32>,
|
destination: Point2D<i32>,
|
||||||
) {
|
) {
|
||||||
let mut dt = raqote::DrawTarget::new(source.size.width, source.size.height);
|
let dt = raqote::DrawTarget::from_vec(source.size.width, source.size.height, surface);
|
||||||
let data = surface;
|
|
||||||
let s = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) };
|
|
||||||
dt.get_data_mut().copy_from_slice(s);
|
|
||||||
raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination);
|
raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,16 +211,18 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
}
|
}
|
||||||
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<Self::SourceSurface> {
|
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<Self::SourceSurface> {
|
||||||
Some(
|
Some(
|
||||||
data.to_vec(
|
bytemuck::try_cast_vec(
|
||||||
Some(SnapshotAlphaMode::Transparent {
|
data.to_vec(
|
||||||
premultiplied: true,
|
Some(SnapshotAlphaMode::Transparent {
|
||||||
}),
|
premultiplied: true,
|
||||||
Some(SnapshotPixelFormat::BGRA),
|
}),
|
||||||
|
Some(SnapshotPixelFormat::BGRA),
|
||||||
|
)
|
||||||
|
.0,
|
||||||
)
|
)
|
||||||
.0,
|
.unwrap_or_else(|(_, surface)| bytemuck::pod_collect_to_vec(&surface)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn draw_surface(
|
fn draw_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: Self::SourceSurface,
|
surface: Self::SourceSurface,
|
||||||
|
@ -244,15 +232,6 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
composition_options: CompositionOptions,
|
composition_options: CompositionOptions,
|
||||||
transform: Transform2D<f32>,
|
transform: Transform2D<f32>,
|
||||||
) {
|
) {
|
||||||
let image = Snapshot::from_vec(
|
|
||||||
src.size.cast(),
|
|
||||||
SnapshotPixelFormat::BGRA,
|
|
||||||
SnapshotAlphaMode::Transparent {
|
|
||||||
premultiplied: true,
|
|
||||||
},
|
|
||||||
surface,
|
|
||||||
);
|
|
||||||
|
|
||||||
let paint_transform =
|
let paint_transform =
|
||||||
raqote::Transform::translation(-dest.origin.x as f32, -dest.origin.y as f32)
|
raqote::Transform::translation(-dest.origin.x as f32, -dest.origin.y as f32)
|
||||||
.then_scale(
|
.then_scale(
|
||||||
|
@ -260,13 +239,6 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
src.size.height as f32 / dest.size.height as f32,
|
src.size.height as f32 / dest.size.height as f32,
|
||||||
);
|
);
|
||||||
|
|
||||||
let pattern = Pattern::Surface(SurfacePattern::new(
|
|
||||||
image,
|
|
||||||
filter.to_raqote(),
|
|
||||||
Repetition::NoRepeat,
|
|
||||||
paint_transform,
|
|
||||||
));
|
|
||||||
|
|
||||||
self.set_transform(&transform);
|
self.set_transform(&transform);
|
||||||
let dest = dest.cast();
|
let dest = dest.cast();
|
||||||
let mut pb = raqote::PathBuilder::new();
|
let mut pb = raqote::PathBuilder::new();
|
||||||
|
@ -276,10 +248,20 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
dest.size.width,
|
dest.size.width,
|
||||||
dest.size.height,
|
dest.size.height,
|
||||||
);
|
);
|
||||||
|
let size = src.size.cast();
|
||||||
fill_draw_target(
|
fill_draw_target(
|
||||||
self,
|
self,
|
||||||
draw_options(composition_options),
|
draw_options(composition_options),
|
||||||
pattern,
|
&raqote::Source::Image(
|
||||||
|
raqote::Image {
|
||||||
|
width: size.width,
|
||||||
|
height: size.height,
|
||||||
|
data: &surface,
|
||||||
|
},
|
||||||
|
raqote::ExtendMode::Pad,
|
||||||
|
filter.to_raqote(),
|
||||||
|
paint_transform,
|
||||||
|
),
|
||||||
pb.finish(),
|
pb.finish(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -303,7 +285,7 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
let draw_options = draw_options(composition_options);
|
let draw_options = draw_options(composition_options);
|
||||||
let pattern = style.to_raqote_pattern();
|
let pattern = style.to_raqote_pattern();
|
||||||
let path = to_path(path);
|
let path = to_path(path);
|
||||||
fill_draw_target(self, draw_options, pattern, path);
|
fill_draw_target(self, draw_options, &source(&pattern), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_text(
|
fn fill_text(
|
||||||
|
@ -402,7 +384,7 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
self.push_clip_rect(rect.to_box2d());
|
self.push_clip_rect(rect.to_box2d());
|
||||||
}
|
}
|
||||||
fn surface(&mut self) -> Self::SourceSurface {
|
fn surface(&mut self) -> Self::SourceSurface {
|
||||||
self.get_data_u8().to_vec()
|
self.get_data().to_vec()
|
||||||
}
|
}
|
||||||
fn stroke(
|
fn stroke(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -481,13 +463,13 @@ impl GenericDrawTarget for raqote::DrawTarget {
|
||||||
fn fill_draw_target(
|
fn fill_draw_target(
|
||||||
draw_target: &mut raqote::DrawTarget,
|
draw_target: &mut raqote::DrawTarget,
|
||||||
draw_options: DrawOptions,
|
draw_options: DrawOptions,
|
||||||
pattern: Pattern,
|
source: &raqote::Source<'_>,
|
||||||
path: raqote::Path,
|
path: raqote::Path,
|
||||||
) {
|
) {
|
||||||
match draw_options.blend_mode {
|
match draw_options.blend_mode {
|
||||||
raqote::BlendMode::Src => {
|
raqote::BlendMode::Src => {
|
||||||
draw_target.clear(raqote::SolidSource::from_unpremultiplied_argb(0, 0, 0, 0));
|
draw_target.clear(raqote::SolidSource::from_unpremultiplied_argb(0, 0, 0, 0));
|
||||||
draw_target.fill(&path, &source(&pattern), &draw_options);
|
draw_target.fill(&path, source, &draw_options);
|
||||||
},
|
},
|
||||||
raqote::BlendMode::Clear |
|
raqote::BlendMode::Clear |
|
||||||
raqote::BlendMode::SrcAtop |
|
raqote::BlendMode::SrcAtop |
|
||||||
|
@ -496,7 +478,7 @@ fn fill_draw_target(
|
||||||
raqote::BlendMode::Xor |
|
raqote::BlendMode::Xor |
|
||||||
raqote::BlendMode::DstOver |
|
raqote::BlendMode::DstOver |
|
||||||
raqote::BlendMode::SrcOver => {
|
raqote::BlendMode::SrcOver => {
|
||||||
draw_target.fill(&path, &source(&pattern), &draw_options);
|
draw_target.fill(&path, source, &draw_options);
|
||||||
},
|
},
|
||||||
raqote::BlendMode::SrcIn |
|
raqote::BlendMode::SrcIn |
|
||||||
raqote::BlendMode::SrcOut |
|
raqote::BlendMode::SrcOut |
|
||||||
|
@ -505,7 +487,7 @@ fn fill_draw_target(
|
||||||
let mut options = draw_options;
|
let mut options = draw_options;
|
||||||
draw_target.push_layer_with_blend(1., options.blend_mode);
|
draw_target.push_layer_with_blend(1., options.blend_mode);
|
||||||
options.blend_mode = raqote::BlendMode::SrcOver;
|
options.blend_mode = raqote::BlendMode::SrcOver;
|
||||||
draw_target.fill(&path, &source(&pattern), &options);
|
draw_target.fill(&path, source, &options);
|
||||||
draw_target.pop_layer();
|
draw_target.pop_layer();
|
||||||
},
|
},
|
||||||
_ => warn!("unrecognized blend mode: {:?}", draw_options.blend_mode),
|
_ => warn!("unrecognized blend mode: {:?}", draw_options.blend_mode),
|
||||||
|
@ -620,7 +602,6 @@ impl ToRaqoteGradientStop for CanvasGradientStop {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToRaqotePattern for FillOrStrokeStyle {
|
impl ToRaqotePattern for FillOrStrokeStyle {
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn to_raqote_pattern(self) -> Pattern {
|
fn to_raqote_pattern(self) -> Pattern {
|
||||||
use canvas_traits::canvas::FillOrStrokeStyle::*;
|
use canvas_traits::canvas::FillOrStrokeStyle::*;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue