mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Layerize canvas
Note that this keeps using readback right now, `NativeSurface` painting will be implemented soon. Also see https://github.com/servo/servo/issues/6142
This commit is contained in:
parent
6481058309
commit
3350522306
35 changed files with 769 additions and 500 deletions
|
@ -5,19 +5,18 @@
|
|||
use azure::azure::AzFloat;
|
||||
use azure::azure_hl::{DrawTarget, SurfaceFormat, BackendType, StrokeOptions, DrawOptions, Pattern};
|
||||
use azure::azure_hl::{ColorPattern, PathBuilder, DrawSurfaceOptions, Filter};
|
||||
use azure::azure_hl::{GradientStop, LinearGradientPattern, RadialGradientPattern, ExtendMode};
|
||||
use azure::azure_hl::{JoinStyle, CapStyle, CompositionOp};
|
||||
use canvas_msg::{CanvasMsg, Canvas2dMsg, CanvasCommonMsg};
|
||||
use azure::azure_hl::{JoinStyle, CapStyle};
|
||||
use canvas_traits::*;
|
||||
use geom::matrix2d::Matrix2D;
|
||||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use gfx::color;
|
||||
use layers::platform::surface::NativeSurface;
|
||||
use gfx_traits::color;
|
||||
use num::ToPrimitive;
|
||||
use util::task::spawn_named;
|
||||
use util::vec::byte_swap;
|
||||
|
||||
use cssparser::RGBA;
|
||||
use std::borrow::ToOwned;
|
||||
use std::mem;
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
|
@ -257,6 +256,8 @@ impl<'a> CanvasPaintTask<'a> {
|
|||
CanvasCommonMsg::Recreate(size) => painter.recreate(size),
|
||||
CanvasCommonMsg::SendPixelContents(chan) =>
|
||||
painter.send_pixel_contents(chan),
|
||||
CanvasCommonMsg::SendNativeSurface(chan) =>
|
||||
painter.send_native_surface(chan),
|
||||
}
|
||||
},
|
||||
CanvasMsg::WebGL(_) => panic!("Wrong message sent to Canvas2D task"),
|
||||
|
@ -497,6 +498,14 @@ impl<'a> CanvasPaintTask<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn send_native_surface(&self, chan: Sender<NativeSurface>) {
|
||||
let mut native_surface: NativeSurface =
|
||||
NativeSurface::from_draw_target_backing(self.drawtarget.backing.clone());
|
||||
native_surface.mark_wont_leak();
|
||||
|
||||
chan.send(native_surface).unwrap();
|
||||
}
|
||||
|
||||
fn get_image_data(&self, mut dest_rect: Rect<f64>, canvas_size: Size2D<f64>, chan: Sender<Vec<u8>>) {
|
||||
if dest_rect.size.width < 0.0 {
|
||||
dest_rect.size.width = -dest_rect.size.width;
|
||||
|
@ -566,340 +575,6 @@ impl<'a> CanvasPaintTask<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CanvasGradientStop {
|
||||
pub offset: f64,
|
||||
pub color: RGBA,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LinearGradientStyle {
|
||||
pub x0: f64,
|
||||
pub y0: f64,
|
||||
pub x1: f64,
|
||||
pub y1: f64,
|
||||
pub stops: Vec<CanvasGradientStop>
|
||||
}
|
||||
|
||||
impl LinearGradientStyle {
|
||||
pub fn new(x0: f64, y0: f64, x1: f64, y1: f64, stops: Vec<CanvasGradientStop>)
|
||||
-> LinearGradientStyle {
|
||||
LinearGradientStyle {
|
||||
x0: x0,
|
||||
y0: y0,
|
||||
x1: x1,
|
||||
y1: y1,
|
||||
stops: stops,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RadialGradientStyle {
|
||||
pub x0: f64,
|
||||
pub y0: f64,
|
||||
pub r0: f64,
|
||||
pub x1: f64,
|
||||
pub y1: f64,
|
||||
pub r1: f64,
|
||||
pub stops: Vec<CanvasGradientStop>
|
||||
}
|
||||
|
||||
impl RadialGradientStyle {
|
||||
pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64, stops: Vec<CanvasGradientStop>)
|
||||
-> RadialGradientStyle {
|
||||
RadialGradientStyle {
|
||||
x0: x0,
|
||||
y0: y0,
|
||||
r0: r0,
|
||||
x1: x1,
|
||||
y1: y1,
|
||||
r1: r1,
|
||||
stops: stops,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum FillOrStrokeStyle {
|
||||
Color(RGBA),
|
||||
LinearGradient(LinearGradientStyle),
|
||||
RadialGradient(RadialGradientStyle),
|
||||
}
|
||||
|
||||
impl FillOrStrokeStyle {
|
||||
fn to_azure_pattern(&self, drawtarget: &DrawTarget) -> Pattern {
|
||||
match *self {
|
||||
FillOrStrokeStyle::Color(ref color) => {
|
||||
Pattern::Color(ColorPattern::new(color::new(color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha)))
|
||||
},
|
||||
FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => {
|
||||
let gradient_stops: Vec<GradientStop> = linear_gradient_style.stops.iter().map(|s| {
|
||||
GradientStop {
|
||||
offset: s.offset as AzFloat,
|
||||
color: color::new(s.color.red, s.color.green, s.color.blue, s.color.alpha)
|
||||
}
|
||||
}).collect();
|
||||
|
||||
Pattern::LinearGradient(LinearGradientPattern::new(
|
||||
&Point2D(linear_gradient_style.x0 as AzFloat, linear_gradient_style.y0 as AzFloat),
|
||||
&Point2D(linear_gradient_style.x1 as AzFloat, linear_gradient_style.y1 as AzFloat),
|
||||
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
|
||||
&Matrix2D::identity()))
|
||||
},
|
||||
FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
|
||||
let gradient_stops: Vec<GradientStop> = radial_gradient_style.stops.iter().map(|s| {
|
||||
GradientStop {
|
||||
offset: s.offset as AzFloat,
|
||||
color: color::new(s.color.red, s.color.green, s.color.blue, s.color.alpha)
|
||||
}
|
||||
}).collect();
|
||||
|
||||
Pattern::RadialGradient(RadialGradientPattern::new(
|
||||
&Point2D(radial_gradient_style.x0 as AzFloat, radial_gradient_style.y0 as AzFloat),
|
||||
&Point2D(radial_gradient_style.x1 as AzFloat, radial_gradient_style.y1 as AzFloat),
|
||||
radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat,
|
||||
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
|
||||
&Matrix2D::identity()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum LineCapStyle {
|
||||
Butt = 0,
|
||||
Round = 1,
|
||||
Square = 2,
|
||||
}
|
||||
|
||||
impl LineCapStyle {
|
||||
fn to_azure_style(&self) -> CapStyle {
|
||||
match *self {
|
||||
LineCapStyle::Butt => CapStyle::Butt,
|
||||
LineCapStyle::Round => CapStyle::Round,
|
||||
LineCapStyle::Square => CapStyle::Square,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Option<LineCapStyle> {
|
||||
match string {
|
||||
"butt" => Some(LineCapStyle::Butt),
|
||||
"round" => Some(LineCapStyle::Round),
|
||||
"square" => Some(LineCapStyle::Square),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum LineJoinStyle {
|
||||
Round = 0,
|
||||
Bevel = 1,
|
||||
Miter = 2,
|
||||
}
|
||||
|
||||
impl LineJoinStyle {
|
||||
fn to_azure_style(&self) -> JoinStyle {
|
||||
match *self {
|
||||
LineJoinStyle::Round => JoinStyle::Round,
|
||||
LineJoinStyle::Bevel => JoinStyle::Bevel,
|
||||
LineJoinStyle::Miter => JoinStyle::Miter,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Option<LineJoinStyle> {
|
||||
match string {
|
||||
"round" => Some(LineJoinStyle::Round),
|
||||
"bevel" => Some(LineJoinStyle::Bevel),
|
||||
"miter" => Some(LineJoinStyle::Miter),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum CompositionStyle {
|
||||
SrcIn,
|
||||
SrcOut,
|
||||
SrcOver,
|
||||
SrcAtop,
|
||||
DestIn,
|
||||
DestOut,
|
||||
DestOver,
|
||||
DestAtop,
|
||||
Copy,
|
||||
Lighter,
|
||||
Xor,
|
||||
}
|
||||
|
||||
impl CompositionStyle {
|
||||
fn to_azure_style(&self) -> CompositionOp {
|
||||
match *self {
|
||||
CompositionStyle::SrcIn => CompositionOp::In,
|
||||
CompositionStyle::SrcOut => CompositionOp::Out,
|
||||
CompositionStyle::SrcOver => CompositionOp::Over,
|
||||
CompositionStyle::SrcAtop => CompositionOp::Atop,
|
||||
CompositionStyle::DestIn => CompositionOp::DestIn,
|
||||
CompositionStyle::DestOut => CompositionOp::DestOut,
|
||||
CompositionStyle::DestOver => CompositionOp::DestOver,
|
||||
CompositionStyle::DestAtop => CompositionOp::DestAtop,
|
||||
CompositionStyle::Copy => CompositionOp::Source,
|
||||
CompositionStyle::Lighter => CompositionOp::Add,
|
||||
CompositionStyle::Xor => CompositionOp::Xor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Option<CompositionStyle> {
|
||||
match string {
|
||||
"source-in" => Some(CompositionStyle::SrcIn),
|
||||
"source-out" => Some(CompositionStyle::SrcOut),
|
||||
"source-over" => Some(CompositionStyle::SrcOver),
|
||||
"source-atop" => Some(CompositionStyle::SrcAtop),
|
||||
"destination-in" => Some(CompositionStyle::DestIn),
|
||||
"destination-out" => Some(CompositionStyle::DestOut),
|
||||
"destination-over" => Some(CompositionStyle::DestOver),
|
||||
"destination-atop" => Some(CompositionStyle::DestAtop),
|
||||
"copy" => Some(CompositionStyle::Copy),
|
||||
"lighter" => Some(CompositionStyle::Lighter),
|
||||
"xor" => Some(CompositionStyle::Xor),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> &str {
|
||||
match *self {
|
||||
CompositionStyle::SrcIn => "source-in",
|
||||
CompositionStyle::SrcOut => "source-out",
|
||||
CompositionStyle::SrcOver => "source-over",
|
||||
CompositionStyle::SrcAtop => "source-atop",
|
||||
CompositionStyle::DestIn => "destination-in",
|
||||
CompositionStyle::DestOut => "destination-out",
|
||||
CompositionStyle::DestOver => "destination-over",
|
||||
CompositionStyle::DestAtop => "destination-atop",
|
||||
CompositionStyle::Copy => "copy",
|
||||
CompositionStyle::Lighter => "lighter",
|
||||
CompositionStyle::Xor => "xor",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum BlendingStyle {
|
||||
Multiply,
|
||||
Screen,
|
||||
Overlay,
|
||||
Darken,
|
||||
Lighten,
|
||||
ColorDodge,
|
||||
ColorBurn,
|
||||
HardLight,
|
||||
SoftLight,
|
||||
Difference,
|
||||
Exclusion,
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
Luminosity,
|
||||
}
|
||||
|
||||
impl BlendingStyle {
|
||||
fn to_azure_style(&self) -> CompositionOp {
|
||||
match *self {
|
||||
BlendingStyle::Multiply => CompositionOp::Multiply,
|
||||
BlendingStyle::Screen => CompositionOp::Screen,
|
||||
BlendingStyle::Overlay => CompositionOp::Overlay,
|
||||
BlendingStyle::Darken => CompositionOp::Darken,
|
||||
BlendingStyle::Lighten => CompositionOp::Lighten,
|
||||
BlendingStyle::ColorDodge => CompositionOp::ColorDodge,
|
||||
BlendingStyle::ColorBurn => CompositionOp::ColorBurn,
|
||||
BlendingStyle::HardLight => CompositionOp::HardLight,
|
||||
BlendingStyle::SoftLight => CompositionOp::SoftLight,
|
||||
BlendingStyle::Difference => CompositionOp::Difference,
|
||||
BlendingStyle::Exclusion => CompositionOp::Exclusion,
|
||||
BlendingStyle::Hue => CompositionOp::Hue,
|
||||
BlendingStyle::Saturation => CompositionOp::Saturation,
|
||||
BlendingStyle::Color => CompositionOp::Color,
|
||||
BlendingStyle::Luminosity => CompositionOp::Luminosity,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Option<BlendingStyle> {
|
||||
match string {
|
||||
"multiply" => Some(BlendingStyle::Multiply),
|
||||
"screen" => Some(BlendingStyle::Screen),
|
||||
"overlay" => Some(BlendingStyle::Overlay),
|
||||
"darken" => Some(BlendingStyle::Darken),
|
||||
"lighten" => Some(BlendingStyle::Lighten),
|
||||
"color-dodge" => Some(BlendingStyle::ColorDodge),
|
||||
"color-burn" => Some(BlendingStyle::ColorBurn),
|
||||
"hard-light" => Some(BlendingStyle::HardLight),
|
||||
"soft-light" => Some(BlendingStyle::SoftLight),
|
||||
"difference" => Some(BlendingStyle::Difference),
|
||||
"exclusion" => Some(BlendingStyle::Exclusion),
|
||||
"hue" => Some(BlendingStyle::Hue),
|
||||
"saturation" => Some(BlendingStyle::Saturation),
|
||||
"color" => Some(BlendingStyle::Color),
|
||||
"luminosity" => Some(BlendingStyle::Luminosity),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> &str {
|
||||
match *self {
|
||||
BlendingStyle::Multiply => "multiply",
|
||||
BlendingStyle::Screen => "screen",
|
||||
BlendingStyle::Overlay => "overlay",
|
||||
BlendingStyle::Darken => "darken",
|
||||
BlendingStyle::Lighten => "lighten",
|
||||
BlendingStyle::ColorDodge => "color-dodge",
|
||||
BlendingStyle::ColorBurn => "color-burn",
|
||||
BlendingStyle::HardLight => "hard-light",
|
||||
BlendingStyle::SoftLight => "soft-light",
|
||||
BlendingStyle::Difference => "difference",
|
||||
BlendingStyle::Exclusion => "exclusion",
|
||||
BlendingStyle::Hue => "hue",
|
||||
BlendingStyle::Saturation => "saturation",
|
||||
BlendingStyle::Color => "color",
|
||||
BlendingStyle::Luminosity => "luminosity",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum CompositionOrBlending {
|
||||
Composition(CompositionStyle),
|
||||
Blending(BlendingStyle),
|
||||
}
|
||||
|
||||
impl CompositionOrBlending {
|
||||
fn to_azure_style(&self) -> CompositionOp {
|
||||
match *self {
|
||||
CompositionOrBlending::Composition(op) => op.to_azure_style(),
|
||||
CompositionOrBlending::Blending(op) => op.to_azure_style(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default() -> CompositionOrBlending {
|
||||
CompositionOrBlending::Composition(CompositionStyle::SrcOver)
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Option<CompositionOrBlending> {
|
||||
if let Some(op) = CompositionStyle::from_str(string) {
|
||||
return Some(CompositionOrBlending::Composition(op));
|
||||
}
|
||||
|
||||
if let Some(op) = BlendingStyle::from_str(string) {
|
||||
return Some(CompositionOrBlending::Blending(op));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by drawImage to get rid of the extra pixels of the image data that
|
||||
/// won't be copied to the canvas
|
||||
/// image_data: Color pixel data of the image
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue