mirror of
https://github.com/servo/servo.git
synced 2025-07-14 19:03:40 +01:00
canvas: Use snapshot in canvas backends (#37863)
This removes assumption about pixel format from backend abstraction to actual backend implementation. This is important for vello. Testing: WPT tests --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
8df5e1e74d
commit
e1a891ea96
10 changed files with 174 additions and 292 deletions
|
@ -2,15 +2,16 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use canvas_traits::canvas::{
|
||||
CompositionOrBlending, FillOrStrokeStyle, LineCapStyle, LineJoinStyle, PathSegment,
|
||||
};
|
||||
use compositing_traits::SerializableImageData;
|
||||
use euclid::Angle;
|
||||
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
|
||||
use lyon_geom::Arc;
|
||||
use pixels::Snapshot;
|
||||
use style::color::AbsoluteColor;
|
||||
use webrender_api::ImageDescriptor;
|
||||
|
||||
use crate::canvas_data::{CanvasPaintState, Filter, PathBuilderRef, TextRun};
|
||||
|
||||
|
@ -61,7 +62,7 @@ pub(crate) trait GenericDrawTarget<B: Backend> {
|
|||
destination: Point2D<i32>,
|
||||
);
|
||||
fn create_similar_draw_target(&self, size: &Size2D<i32>) -> Self;
|
||||
fn create_source_surface_from_data(&self, data: &[u8]) -> Option<B::SourceSurface>;
|
||||
fn create_source_surface_from_data(&self, data: Snapshot) -> Option<B::SourceSurface>;
|
||||
fn draw_surface(
|
||||
&mut self,
|
||||
surface: B::SourceSurface,
|
||||
|
@ -113,7 +114,8 @@ pub(crate) trait GenericDrawTarget<B: Backend> {
|
|||
draw_options: &B::DrawOptions,
|
||||
);
|
||||
fn surface(&self) -> B::SourceSurface;
|
||||
fn bytes(&self) -> Cow<[u8]>;
|
||||
fn image_descriptor_and_serializable_data(&self) -> (ImageDescriptor, SerializableImageData);
|
||||
fn snapshot(&self) -> Snapshot;
|
||||
}
|
||||
|
||||
/// A generic Path that abstracts the interface for raqote's PathBuilder/Path.
|
||||
|
|
|
@ -8,22 +8,22 @@ use std::sync::Arc;
|
|||
|
||||
use app_units::Au;
|
||||
use canvas_traits::canvas::*;
|
||||
use compositing_traits::{CrossProcessCompositorApi, SerializableImageData};
|
||||
use compositing_traits::CrossProcessCompositorApi;
|
||||
use euclid::default::{Box2D, Point2D, Rect, Size2D, Transform2D, Vector2D};
|
||||
use euclid::point2;
|
||||
use fonts::{
|
||||
ByteIndex, FontBaseline, FontContext, FontGroup, FontMetrics, FontRef, GlyphInfo, GlyphStore,
|
||||
LAST_RESORT_GLYPH_ADVANCE, ShapingFlags, ShapingOptions,
|
||||
};
|
||||
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use log::warn;
|
||||
use pixels::{Snapshot, SnapshotAlphaMode, SnapshotPixelFormat};
|
||||
use pixels::Snapshot;
|
||||
use range::Range;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
use style::color::AbsoluteColor;
|
||||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
use unicode_script::Script;
|
||||
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey};
|
||||
use webrender_api::ImageKey;
|
||||
|
||||
use crate::backend::{
|
||||
Backend, DrawOptionsHelpers as _, GenericDrawTarget as _, GenericPath, PatternHelpers,
|
||||
|
@ -352,15 +352,7 @@ impl<'a, B: Backend> CanvasData<'a, B> {
|
|||
let size = size.max(MIN_WR_IMAGE_SIZE);
|
||||
let draw_target = backend.create_drawtarget(size);
|
||||
let image_key = compositor_api.generate_image_key_blocking().unwrap();
|
||||
let descriptor = ImageDescriptor {
|
||||
size: size.cast().cast_unit(),
|
||||
stride: None,
|
||||
format: ImageFormat::BGRA8,
|
||||
offset: 0,
|
||||
flags: ImageDescriptorFlags::empty(),
|
||||
};
|
||||
let data =
|
||||
SerializableImageData::Raw(IpcSharedMemory::from_bytes(draw_target.bytes().as_ref()));
|
||||
let (descriptor, data) = draw_target.image_descriptor_and_serializable_data();
|
||||
compositor_api.add_image(image_key, descriptor, data);
|
||||
CanvasData {
|
||||
state: backend.new_paint_state(),
|
||||
|
@ -380,31 +372,27 @@ impl<'a, B: Backend> CanvasData<'a, B> {
|
|||
|
||||
pub(crate) fn draw_image(
|
||||
&mut self,
|
||||
image_data: &[u8],
|
||||
image_size: Size2D<u32>,
|
||||
snapshot: Snapshot,
|
||||
dest_rect: Rect<f64>,
|
||||
source_rect: Rect<f64>,
|
||||
smoothing_enabled: bool,
|
||||
premultiply: bool,
|
||||
) {
|
||||
// We round up the floating pixel values to draw the pixels
|
||||
let source_rect = source_rect.ceil();
|
||||
// It discards the extra pixels (if any) that won't be painted
|
||||
let image_data = if Rect::from_size(image_size.to_f64()).contains_rect(&source_rect) {
|
||||
pixels::rgba8_get_rect(image_data, image_size, source_rect.to_u32()).into()
|
||||
let snapshot = if Rect::from_size(snapshot.size().to_f64()).contains_rect(&source_rect) {
|
||||
snapshot.get_rect(source_rect.to_u32())
|
||||
} else {
|
||||
image_data.into()
|
||||
snapshot
|
||||
};
|
||||
|
||||
let draw_options = self.state.draw_options.clone();
|
||||
let writer = |draw_target: &mut B::DrawTarget| {
|
||||
write_image::<B>(
|
||||
draw_target,
|
||||
image_data,
|
||||
source_rect.size,
|
||||
snapshot,
|
||||
dest_rect,
|
||||
smoothing_enabled,
|
||||
premultiply,
|
||||
&draw_options,
|
||||
);
|
||||
};
|
||||
|
@ -1107,29 +1095,18 @@ impl<'a, B: Backend> CanvasData<'a, B> {
|
|||
|
||||
/// Update image in WebRender
|
||||
pub(crate) fn update_image_rendering(&mut self) {
|
||||
let descriptor = ImageDescriptor {
|
||||
size: self.drawtarget.get_size().cast_unit(),
|
||||
stride: None,
|
||||
format: ImageFormat::BGRA8,
|
||||
offset: 0,
|
||||
flags: ImageDescriptorFlags::empty(),
|
||||
};
|
||||
let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes(
|
||||
self.drawtarget.bytes().as_ref(),
|
||||
));
|
||||
let (descriptor, data) = self.drawtarget.image_descriptor_and_serializable_data();
|
||||
|
||||
self.compositor_api
|
||||
.update_image(self.image_key, descriptor, data);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
|
||||
pub(crate) fn put_image_data(&mut self, mut imagedata: Vec<u8>, rect: Rect<u32>) {
|
||||
assert_eq!(imagedata.len() % 4, 0);
|
||||
assert_eq!(rect.size.area() as usize, imagedata.len() / 4);
|
||||
pixels::rgba8_byte_swap_and_premultiply_inplace(&mut imagedata);
|
||||
pub(crate) fn put_image_data(&mut self, snapshot: Snapshot, rect: Rect<u32>) {
|
||||
assert_eq!(rect.size, snapshot.size());
|
||||
let source_surface = self
|
||||
.drawtarget
|
||||
.create_source_surface_from_data(&imagedata)
|
||||
.create_source_surface_from_data(snapshot)
|
||||
.unwrap();
|
||||
self.drawtarget.copy_surface(
|
||||
source_surface,
|
||||
|
@ -1217,29 +1194,19 @@ impl<'a, B: Backend> CanvasData<'a, B> {
|
|||
) -> Snapshot {
|
||||
let canvas_size = canvas_size.unwrap_or(self.drawtarget.get_size().cast());
|
||||
|
||||
let data = if let Some(read_rect) = read_rect {
|
||||
if let Some(read_rect) = read_rect {
|
||||
let canvas_rect = Rect::from_size(canvas_size);
|
||||
if canvas_rect
|
||||
.intersection(&read_rect)
|
||||
.is_none_or(|rect| rect.is_empty())
|
||||
{
|
||||
vec![]
|
||||
Snapshot::empty()
|
||||
} else {
|
||||
pixels::rgba8_get_rect(self.drawtarget.bytes().as_ref(), canvas_size, read_rect)
|
||||
.to_vec()
|
||||
self.drawtarget.snapshot().get_rect(read_rect)
|
||||
}
|
||||
} else {
|
||||
self.drawtarget.bytes().into_owned()
|
||||
};
|
||||
|
||||
Snapshot::from_vec(
|
||||
canvas_size,
|
||||
SnapshotPixelFormat::BGRA,
|
||||
SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
},
|
||||
data,
|
||||
)
|
||||
self.drawtarget.snapshot()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1279,22 +1246,16 @@ pub(crate) struct CanvasPaintState<'a, B: Backend> {
|
|||
/// premultiply: Determines whenever the image data should be premultiplied or not
|
||||
fn write_image<B: Backend>(
|
||||
draw_target: &mut B::DrawTarget,
|
||||
mut image_data: Vec<u8>,
|
||||
image_size: Size2D<f64>,
|
||||
snapshot: Snapshot,
|
||||
dest_rect: Rect<f64>,
|
||||
smoothing_enabled: bool,
|
||||
premultiply: bool,
|
||||
draw_options: &B::DrawOptions,
|
||||
) {
|
||||
if image_data.is_empty() {
|
||||
if snapshot.size().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if premultiply {
|
||||
pixels::rgba8_premultiply_inplace(&mut image_data);
|
||||
}
|
||||
|
||||
let image_rect = Rect::new(Point2D::zero(), image_size);
|
||||
let image_rect = Rect::new(Point2D::zero(), snapshot.size().cast());
|
||||
|
||||
// From spec https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
// When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt
|
||||
|
@ -1307,7 +1268,7 @@ fn write_image<B: Backend>(
|
|||
};
|
||||
|
||||
let source_surface = draw_target
|
||||
.create_source_surface_from_data(&image_data)
|
||||
.create_source_surface_from_data(snapshot)
|
||||
.unwrap();
|
||||
|
||||
draw_target.draw_surface(source_surface, dest_rect, image_rect, filter, draw_options);
|
||||
|
|
|
@ -17,7 +17,7 @@ use ipc_channel::ipc::{self, IpcSender};
|
|||
use ipc_channel::router::ROUTER;
|
||||
use log::warn;
|
||||
use net_traits::ResourceThreads;
|
||||
use pixels::{Snapshot, SnapshotPixelFormat};
|
||||
use pixels::Snapshot;
|
||||
use style::color::AbsoluteColor;
|
||||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
use webrender_api::ImageKey;
|
||||
|
@ -175,29 +175,16 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
.canvas(canvas_id)
|
||||
.is_point_in_path_(&path[..], x, y, fill_rule, chan),
|
||||
Canvas2dMsg::DrawImage(snapshot, dest_rect, source_rect, smoothing_enabled) => {
|
||||
let mut snapshot = snapshot.to_owned();
|
||||
let size = snapshot.size();
|
||||
let (data, alpha_mode, _) =
|
||||
snapshot.as_bytes(None, Some(SnapshotPixelFormat::BGRA));
|
||||
self.canvas(canvas_id).draw_image(
|
||||
data,
|
||||
size,
|
||||
snapshot.to_owned(),
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
alpha_mode.alpha().needs_alpha_multiplication(),
|
||||
)
|
||||
},
|
||||
Canvas2dMsg::DrawEmptyImage(image_size, dest_rect, source_rect) => {
|
||||
self.canvas(canvas_id).draw_image(
|
||||
&vec![0; image_size.area() as usize * 4],
|
||||
image_size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
},
|
||||
Canvas2dMsg::DrawEmptyImage(image_size, dest_rect, source_rect) => self
|
||||
.canvas(canvas_id)
|
||||
.draw_image(Snapshot::cleared(image_size), dest_rect, source_rect, false),
|
||||
Canvas2dMsg::DrawImageInOther(
|
||||
other_canvas_id,
|
||||
image_size,
|
||||
|
@ -205,18 +192,14 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
source_rect,
|
||||
smoothing,
|
||||
) => {
|
||||
let mut snapshot = self
|
||||
let snapshot = self
|
||||
.canvas(canvas_id)
|
||||
.read_pixels(Some(source_rect.to_u32()), Some(image_size));
|
||||
let (data, alpha_mode, _) =
|
||||
snapshot.as_bytes(None, Some(SnapshotPixelFormat::BGRA));
|
||||
self.canvas(other_canvas_id).draw_image(
|
||||
data,
|
||||
source_rect.size.to_u32(),
|
||||
snapshot,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing,
|
||||
alpha_mode.alpha().needs_alpha_multiplication(),
|
||||
);
|
||||
},
|
||||
Canvas2dMsg::MoveTo(ref point) => self.canvas(canvas_id).move_to(point),
|
||||
|
@ -266,9 +249,9 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
.read_pixels(Some(dest_rect), Some(canvas_size));
|
||||
sender.send(snapshot.as_ipc()).unwrap();
|
||||
},
|
||||
Canvas2dMsg::PutImageData(rect, receiver) => {
|
||||
Canvas2dMsg::PutImageData(rect, snapshot) => {
|
||||
self.canvas(canvas_id)
|
||||
.put_image_data(receiver.recv().unwrap(), rect);
|
||||
.put_image_data(snapshot.to_owned(), rect);
|
||||
},
|
||||
Canvas2dMsg::SetShadowOffsetX(value) => {
|
||||
self.canvas(canvas_id).set_shadow_offset_x(value)
|
||||
|
@ -403,22 +386,15 @@ impl Canvas<'_> {
|
|||
|
||||
fn draw_image(
|
||||
&mut self,
|
||||
data: &[u8],
|
||||
size: Size2D<u32>,
|
||||
snapshot: Snapshot,
|
||||
dest_rect: Rect<f64>,
|
||||
source_rect: Rect<f64>,
|
||||
smoothing_enabled: bool,
|
||||
premultiply: bool,
|
||||
) {
|
||||
match self {
|
||||
Canvas::Raqote(canvas_data) => canvas_data.draw_image(
|
||||
data,
|
||||
size,
|
||||
dest_rect,
|
||||
source_rect,
|
||||
smoothing_enabled,
|
||||
premultiply,
|
||||
),
|
||||
Canvas::Raqote(canvas_data) => {
|
||||
canvas_data.draw_image(snapshot, dest_rect, source_rect, smoothing_enabled)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,9 +594,9 @@ impl Canvas<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn put_image_data(&mut self, unwrap: Vec<u8>, rect: Rect<u32>) {
|
||||
fn put_image_data(&mut self, snapshot: Snapshot, rect: Rect<u32>) {
|
||||
match self {
|
||||
Canvas::Raqote(canvas_data) => canvas_data.put_image_data(unwrap, rect),
|
||||
Canvas::Raqote(canvas_data) => canvas_data.put_image_data(snapshot, rect),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,22 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use canvas_traits::canvas::*;
|
||||
use compositing_traits::SerializableImageData;
|
||||
use cssparser::color::clamp_unit_f32;
|
||||
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
|
||||
use font_kit::font::Font;
|
||||
use fonts::{ByteIndex, FontIdentifier, FontTemplateRefMethods};
|
||||
use ipc_channel::ipc::IpcSharedMemory;
|
||||
use log::warn;
|
||||
use pixels::{Snapshot, SnapshotAlphaMode, SnapshotPixelFormat};
|
||||
use range::Range;
|
||||
use raqote::PathOp;
|
||||
use style::color::AbsoluteColor;
|
||||
use webrender_api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat};
|
||||
|
||||
use crate::backend::{
|
||||
Backend, DrawOptionsHelpers, GenericDrawTarget, GenericPath, PatternHelpers,
|
||||
|
@ -34,7 +37,7 @@ thread_local! {
|
|||
pub(crate) struct RaqoteBackend;
|
||||
|
||||
impl Backend for RaqoteBackend {
|
||||
type Pattern<'a> = Pattern<'a>;
|
||||
type Pattern<'a> = Pattern;
|
||||
type StrokeOptions = raqote::StrokeStyle;
|
||||
type Color = raqote::SolidSource;
|
||||
type DrawOptions = raqote::DrawOptions;
|
||||
|
@ -112,12 +115,12 @@ impl Backend for RaqoteBackend {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Pattern<'a> {
|
||||
pub enum Pattern {
|
||||
// argb
|
||||
Color(u8, u8, u8, u8),
|
||||
LinearGradient(LinearGradientPattern),
|
||||
RadialGradient(RadialGradientPattern),
|
||||
Surface(SurfacePattern<'a>),
|
||||
Surface(SurfacePattern),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -165,17 +168,17 @@ impl RadialGradientPattern {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SurfacePattern<'a> {
|
||||
image: raqote::Image<'a>,
|
||||
pub struct SurfacePattern {
|
||||
image: Snapshot,
|
||||
filter: raqote::FilterMode,
|
||||
extend: raqote::ExtendMode,
|
||||
repeat: Repetition,
|
||||
transform: Transform2D<f32>,
|
||||
}
|
||||
|
||||
impl<'a> SurfacePattern<'a> {
|
||||
impl SurfacePattern {
|
||||
fn new(
|
||||
image: raqote::Image<'a>,
|
||||
image: Snapshot,
|
||||
filter: raqote::FilterMode,
|
||||
repeat: Repetition,
|
||||
transform: Transform2D<f32>,
|
||||
|
@ -195,7 +198,7 @@ impl<'a> SurfacePattern<'a> {
|
|||
}
|
||||
}
|
||||
pub fn size(&self) -> Size2D<f32> {
|
||||
Size2D::new(self.image.width as f32, self.image.height as f32)
|
||||
self.image.size().cast()
|
||||
}
|
||||
pub fn repetition(&self) -> &Repetition {
|
||||
&self.repeat
|
||||
|
@ -224,7 +227,7 @@ impl Repetition {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn source<'a>(pattern: &Pattern<'a>) -> raqote::Source<'a> {
|
||||
pub fn source(pattern: &Pattern) -> raqote::Source {
|
||||
match pattern {
|
||||
Pattern::Color(a, r, g, b) => raqote::Source::Solid(
|
||||
raqote::SolidSource::from_unpremultiplied_argb(*a, *r, *g, *b),
|
||||
|
@ -243,16 +246,30 @@ pub fn source<'a>(pattern: &Pattern<'a>) -> raqote::Source<'a> {
|
|||
pattern.radius2,
|
||||
raqote::Spread::Pad,
|
||||
),
|
||||
Pattern::Surface(pattern) => raqote::Source::Image(
|
||||
pattern.image,
|
||||
pattern.extend,
|
||||
pattern.filter,
|
||||
pattern.transform,
|
||||
),
|
||||
Pattern::Surface(pattern) => {
|
||||
#[allow(unsafe_code)]
|
||||
let data = unsafe {
|
||||
let data = pattern.image.as_raw_bytes();
|
||||
std::slice::from_raw_parts(
|
||||
data.as_ptr() as *const u32,
|
||||
data.len() / std::mem::size_of::<u32>(),
|
||||
)
|
||||
};
|
||||
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,
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
impl PatternHelpers for Pattern<'_> {
|
||||
impl PatternHelpers for Pattern {
|
||||
fn is_zero_size_gradient(&self) -> bool {
|
||||
match self {
|
||||
Pattern::RadialGradient(pattern) => {
|
||||
|
@ -371,9 +388,17 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
}
|
||||
fn create_source_surface_from_data(
|
||||
&self,
|
||||
data: &[u8],
|
||||
data: Snapshot,
|
||||
) -> Option<<RaqoteBackend as Backend>::SourceSurface> {
|
||||
Some(data.to_vec())
|
||||
Some(
|
||||
data.to_vec(
|
||||
Some(SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
}),
|
||||
Some(SnapshotPixelFormat::BGRA),
|
||||
)
|
||||
.0,
|
||||
)
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
fn draw_surface(
|
||||
|
@ -384,23 +409,20 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
filter: Filter,
|
||||
draw_options: &<RaqoteBackend as Backend>::DrawOptions,
|
||||
) {
|
||||
let surface_data = surface;
|
||||
let image = raqote::Image {
|
||||
width: source.size.width as i32,
|
||||
height: source.size.height as i32,
|
||||
data: unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
surface_data.as_ptr() as *const u32,
|
||||
surface_data.len() / std::mem::size_of::<u32>(),
|
||||
)
|
||||
let image = Snapshot::from_vec(
|
||||
source.size.cast(),
|
||||
SnapshotPixelFormat::BGRA,
|
||||
SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
},
|
||||
};
|
||||
surface,
|
||||
);
|
||||
|
||||
let transform =
|
||||
raqote::Transform::translation(-dest.origin.x as f32, -dest.origin.y as f32)
|
||||
.then_scale(
|
||||
image.width as f32 / dest.size.width as f32,
|
||||
image.height as f32 / dest.size.height as f32,
|
||||
source.size.width as f32 / dest.size.width as f32,
|
||||
source.size.height as f32 / dest.size.height as f32,
|
||||
);
|
||||
|
||||
let pattern = Pattern::Surface(SurfacePattern::new(
|
||||
|
@ -434,7 +456,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
fn fill(
|
||||
&mut self,
|
||||
path: &<RaqoteBackend as Backend>::Path,
|
||||
pattern: &<RaqoteBackend as Backend>::Pattern<'_>,
|
||||
pattern: &Pattern,
|
||||
draw_options: &<RaqoteBackend as Backend>::DrawOptions,
|
||||
) {
|
||||
let path = path.into();
|
||||
|
@ -470,7 +492,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
&mut self,
|
||||
text_runs: Vec<TextRun>,
|
||||
start: Point2D<f32>,
|
||||
pattern: &<RaqoteBackend as Backend>::Pattern<'_>,
|
||||
pattern: &Pattern,
|
||||
draw_options: &<RaqoteBackend as Backend>::DrawOptions,
|
||||
) {
|
||||
let mut advance = 0.;
|
||||
|
@ -558,12 +580,12 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
self.set_transform(matrix);
|
||||
}
|
||||
fn surface(&self) -> <RaqoteBackend as Backend>::SourceSurface {
|
||||
self.bytes().to_vec()
|
||||
self.get_data_u8().to_vec()
|
||||
}
|
||||
fn stroke(
|
||||
&mut self,
|
||||
path: &<RaqoteBackend as Backend>::Path,
|
||||
pattern: &Pattern<'_>,
|
||||
pattern: &Pattern,
|
||||
stroke_options: &<RaqoteBackend as Backend>::StrokeOptions,
|
||||
draw_options: &<RaqoteBackend as Backend>::DrawOptions,
|
||||
) {
|
||||
|
@ -586,12 +608,33 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget {
|
|||
|
||||
self.stroke(&pb.finish(), &source(pattern), stroke_options, draw_options);
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
fn bytes(&self) -> Cow<[u8]> {
|
||||
let v = self.get_data();
|
||||
Cow::Borrowed(unsafe {
|
||||
std::slice::from_raw_parts(v.as_ptr() as *const u8, std::mem::size_of_val(v))
|
||||
})
|
||||
|
||||
fn image_descriptor_and_serializable_data(
|
||||
&self,
|
||||
) -> (
|
||||
webrender_api::ImageDescriptor,
|
||||
compositing_traits::SerializableImageData,
|
||||
) {
|
||||
let descriptor = ImageDescriptor {
|
||||
size: self.get_size().cast_unit(),
|
||||
stride: None,
|
||||
format: ImageFormat::BGRA8,
|
||||
offset: 0,
|
||||
flags: ImageDescriptorFlags::empty(),
|
||||
};
|
||||
let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes(self.get_data_u8()));
|
||||
(descriptor, data)
|
||||
}
|
||||
|
||||
fn snapshot(&self) -> Snapshot {
|
||||
Snapshot::from_vec(
|
||||
self.get_size().cast(),
|
||||
SnapshotPixelFormat::BGRA,
|
||||
SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
},
|
||||
self.get_data_u8().to_vec(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,8 +771,8 @@ impl ToRaqoteStyle for LineCapStyle {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ToRaqotePattern<'a> {
|
||||
fn to_raqote_pattern(self) -> Option<Pattern<'a>>;
|
||||
pub trait ToRaqotePattern {
|
||||
fn to_raqote_pattern(self) -> Option<Pattern>;
|
||||
}
|
||||
|
||||
pub trait ToRaqoteGradientStop {
|
||||
|
@ -750,9 +793,9 @@ impl ToRaqoteGradientStop for CanvasGradientStop {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToRaqotePattern<'_> for FillOrStrokeStyle {
|
||||
impl ToRaqotePattern for FillOrStrokeStyle {
|
||||
#[allow(unsafe_code)]
|
||||
fn to_raqote_pattern(self) -> Option<Pattern<'static>> {
|
||||
fn to_raqote_pattern(self) -> Option<Pattern> {
|
||||
use canvas_traits::canvas::FillOrStrokeStyle::*;
|
||||
|
||||
match self {
|
||||
|
@ -785,19 +828,17 @@ impl ToRaqotePattern<'_> for FillOrStrokeStyle {
|
|||
stops,
|
||||
)))
|
||||
},
|
||||
Surface(ref style) => {
|
||||
Surface(style) => {
|
||||
let repeat = Repetition::from_xy(style.repeat_x, style.repeat_y);
|
||||
let data = &style.surface_data[..];
|
||||
|
||||
let image = raqote::Image {
|
||||
width: style.surface_size.width as i32,
|
||||
height: style.surface_size.height as i32,
|
||||
data: unsafe {
|
||||
std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4)
|
||||
let mut snapshot = style.surface_data.to_owned();
|
||||
snapshot.transform(
|
||||
SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
},
|
||||
};
|
||||
SnapshotPixelFormat::BGRA,
|
||||
);
|
||||
Some(Pattern::Surface(SurfacePattern::new(
|
||||
image,
|
||||
snapshot,
|
||||
raqote::FilterMode::Nearest,
|
||||
repeat,
|
||||
style.transform,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use euclid::default::Size2D;
|
||||
use euclid::default::{Rect, Size2D};
|
||||
use image::codecs::jpeg::JpegEncoder;
|
||||
use image::codecs::png::PngEncoder;
|
||||
use image::codecs::webp::WebPEncoder;
|
||||
|
@ -13,7 +13,7 @@ use ipc_channel::ipc::IpcSharedMemory;
|
|||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{EncodedImageType, Multiply, transform_inplace};
|
||||
use crate::{EncodedImageType, Multiply, rgba8_get_rect, transform_inplace};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum SnapshotPixelFormat {
|
||||
|
@ -180,6 +180,11 @@ impl Snapshot<SnapshotData> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_rect(&self, rect: Rect<u32>) -> Self {
|
||||
let data = rgba8_get_rect(self.as_raw_bytes(), self.size(), rect).to_vec();
|
||||
Self::from_vec(rect.size, self.format, self.alpha_mode, data)
|
||||
}
|
||||
|
||||
// TODO: https://github.com/servo/servo/issues/36594
|
||||
/*
|
||||
/// # Safety
|
||||
|
|
|
@ -1186,14 +1186,7 @@ impl CanvasState {
|
|||
let size = snapshot.size();
|
||||
Ok(Some(CanvasPattern::new(
|
||||
global,
|
||||
snapshot
|
||||
.to_vec(
|
||||
Some(SnapshotAlphaMode::Transparent {
|
||||
premultiplied: true,
|
||||
}),
|
||||
Some(SnapshotPixelFormat::BGRA),
|
||||
)
|
||||
.0, // TODO: send snapshot
|
||||
snapshot,
|
||||
size.cast(),
|
||||
rep,
|
||||
self.is_origin_clean(image),
|
||||
|
@ -1703,10 +1696,8 @@ impl CanvasState {
|
|||
};
|
||||
|
||||
// Step 7.
|
||||
let (sender, receiver) = ipc::bytes_channel().unwrap();
|
||||
let pixels = unsafe { &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) };
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver));
|
||||
sender.send(pixels).unwrap();
|
||||
let snapshot = imagedata.get_snapshot_rect(Rect::new(src_rect.origin, dst_rect.size));
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, snapshot.as_ipc()));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use canvas_traits::canvas::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle};
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::default::{Size2D, Transform2D};
|
||||
use pixels::{IpcSnapshot, Snapshot};
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasPatternMethods;
|
||||
|
@ -21,7 +22,8 @@ use crate::script_runtime::CanGc;
|
|||
#[dom_struct]
|
||||
pub(crate) struct CanvasPattern {
|
||||
reflector_: Reflector,
|
||||
surface_data: Vec<u8>,
|
||||
#[no_trace]
|
||||
surface_data: IpcSnapshot,
|
||||
#[no_trace]
|
||||
surface_size: Size2D<u32>,
|
||||
repeat_x: bool,
|
||||
|
@ -33,7 +35,7 @@ pub(crate) struct CanvasPattern {
|
|||
|
||||
impl CanvasPattern {
|
||||
fn new_inherited(
|
||||
surface_data: Vec<u8>,
|
||||
surface_data: Snapshot,
|
||||
surface_size: Size2D<u32>,
|
||||
repeat: RepetitionStyle,
|
||||
origin_clean: bool,
|
||||
|
@ -47,7 +49,7 @@ impl CanvasPattern {
|
|||
|
||||
CanvasPattern {
|
||||
reflector_: Reflector::new(),
|
||||
surface_data,
|
||||
surface_data: surface_data.as_ipc(),
|
||||
surface_size,
|
||||
repeat_x: x,
|
||||
repeat_y: y,
|
||||
|
@ -57,7 +59,7 @@ impl CanvasPattern {
|
|||
}
|
||||
pub(crate) fn new(
|
||||
global: &GlobalScope,
|
||||
surface_data: Vec<u8>,
|
||||
surface_data: Snapshot,
|
||||
surface_size: Size2D<u32>,
|
||||
repeat: RepetitionStyle,
|
||||
origin_clean: bool,
|
||||
|
|
|
@ -12,6 +12,7 @@ use js::gc::CustomAutoRooterGuard;
|
|||
use js::jsapi::JSObject;
|
||||
use js::rust::HandleObject;
|
||||
use js::typedarray::{ClampedU8, Uint8ClampedArray};
|
||||
use pixels::{Snapshot, SnapshotAlphaMode, SnapshotPixelFormat};
|
||||
|
||||
use super::bindings::buffer_source::{HeapBufferSource, create_heap_buffer_source_with_length};
|
||||
use crate::dom::bindings::buffer_source::create_buffer_source;
|
||||
|
@ -183,6 +184,18 @@ impl ImageData {
|
|||
pixels::rgba8_get_rect(unsafe { self.as_slice() }, self.get_size().to_u32(), rect)
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn get_snapshot_rect(&self, rect: Rect<u32>) -> Snapshot {
|
||||
Snapshot::from_vec(
|
||||
rect.size,
|
||||
SnapshotPixelFormat::RGBA,
|
||||
SnapshotAlphaMode::Transparent {
|
||||
premultiplied: false,
|
||||
},
|
||||
unsafe { self.get_rect(rect).into_owned() },
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn to_shared_memory(&self) -> IpcSharedMemory {
|
||||
// This is safe because we copy the slice content
|
||||
|
|
|
@ -6,11 +6,10 @@ use std::default::Default;
|
|||
use std::str::FromStr;
|
||||
|
||||
use euclid::default::{Point2D, Rect, Size2D, Transform2D};
|
||||
use ipc_channel::ipc::{IpcBytesReceiver, IpcSender};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use pixels::IpcSnapshot;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_bytes::ByteBuf;
|
||||
use strum::{Display, EnumString};
|
||||
use style::color::AbsoluteColor;
|
||||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
|
@ -110,7 +109,7 @@ pub enum Canvas2dMsg {
|
|||
LineTo(Point2D<f32>),
|
||||
MoveTo(Point2D<f32>),
|
||||
MeasureText(String, IpcSender<TextMetrics>),
|
||||
PutImageData(Rect<u32>, IpcBytesReceiver),
|
||||
PutImageData(Rect<u32>, IpcSnapshot),
|
||||
QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
|
||||
Rect(Rect<f32>),
|
||||
RestoreContext,
|
||||
|
@ -210,7 +209,7 @@ impl RadialGradientStyle {
|
|||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct SurfaceStyle {
|
||||
pub surface_data: ByteBuf,
|
||||
pub surface_data: IpcSnapshot,
|
||||
pub surface_size: Size2D<u32>,
|
||||
pub repeat_x: bool,
|
||||
pub repeat_y: bool,
|
||||
|
@ -219,14 +218,14 @@ pub struct SurfaceStyle {
|
|||
|
||||
impl SurfaceStyle {
|
||||
pub fn new(
|
||||
surface_data: Vec<u8>,
|
||||
surface_data: IpcSnapshot,
|
||||
surface_size: Size2D<u32>,
|
||||
repeat_x: bool,
|
||||
repeat_y: bool,
|
||||
transform: Transform2D<f32>,
|
||||
) -> Self {
|
||||
Self {
|
||||
surface_data: ByteBuf::from(surface_data),
|
||||
surface_data,
|
||||
surface_size,
|
||||
repeat_x,
|
||||
repeat_y,
|
||||
|
|
|
@ -1,76 +1,34 @@
|
|||
[canvas-display-p3-pattern-image.html]
|
||||
[sRGB-FF0000FF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000FF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000FF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000FF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000CC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000CC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000CC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FF0000CC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000FF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000FF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000FF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000FF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000CC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000CC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000CC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BB0000CC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000FF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000FF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000FF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000FF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000CC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000CC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000CC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FF0000CC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BB0000FF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -80,9 +38,6 @@
|
|||
[Display-P3-BB0000FF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BB0000FF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BB0000CC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -92,12 +47,6 @@
|
|||
[Display-P3-BB0000CC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BB0000CC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FF0000FF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FF0000FF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -107,9 +56,6 @@
|
|||
[Adobe-RGB-FF0000FF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FF0000CC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FF0000CC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -167,78 +113,36 @@
|
|||
[Generic-CMYK-BE000000.jpg, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000FFFF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000FFFF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000FFFF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000FFFF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000CCCC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000CCCC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000CCCC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-FFFF00000000CCCC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000FFFF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000FFFF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000FFFF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000FFFF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000CCCC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000CCCC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000CCCC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[sRGB-BBBC00000000CCCC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000FFFF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000FFFF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000FFFF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000FFFF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000CCCC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000CCCC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000CCCC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-FFFF00000000CCCC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BBBC00000000FFFF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -248,9 +152,6 @@
|
|||
[Display-P3-BBBC00000000FFFF.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BBBC00000000FFFF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BBBC00000000CCCC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -260,12 +161,6 @@
|
|||
[Display-P3-BBBC00000000CCCC.png, Context display-p3, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Display-P3-BBBC00000000CCCC.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FFFF00000000FFFF.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FFFF00000000FFFF.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -275,9 +170,6 @@
|
|||
[Adobe-RGB-FFFF00000000FFFF.png, Context display-p3, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FFFF00000000CCCC.png, Context srgb, ImageData srgb]
|
||||
expected: FAIL
|
||||
|
||||
[Adobe-RGB-FFFF00000000CCCC.png, Context srgb, ImageData display-p3]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue