2015-05-20 23:42:06 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#![crate_name = "canvas_traits"]
|
|
|
|
#![crate_type = "rlib"]
|
2015-07-25 10:50:31 +03:00
|
|
|
#![feature(custom_derive)]
|
|
|
|
#![feature(plugin)]
|
2016-10-10 04:12:38 +03:00
|
|
|
#![feature(proc_macro)]
|
|
|
|
#![feature(rustc_attrs)]
|
|
|
|
#![plugin(heapsize_plugin, plugins)]
|
2015-07-25 10:50:31 +03:00
|
|
|
|
2016-03-20 05:30:53 +03:00
|
|
|
#![deny(unsafe_code)]
|
|
|
|
|
2015-05-20 23:42:06 +03:00
|
|
|
extern crate azure;
|
2015-09-24 00:02:56 +03:00
|
|
|
extern crate core;
|
2015-05-20 23:42:06 +03:00
|
|
|
extern crate cssparser;
|
2015-09-24 00:02:56 +03:00
|
|
|
extern crate euclid;
|
2016-02-05 01:10:36 +03:00
|
|
|
extern crate heapsize;
|
2015-07-25 02:14:59 +03:00
|
|
|
extern crate ipc_channel;
|
2015-07-25 10:50:31 +03:00
|
|
|
extern crate serde;
|
2016-10-10 04:12:38 +03:00
|
|
|
#[macro_use]
|
|
|
|
extern crate serde_derive;
|
2016-02-18 22:24:06 +03:00
|
|
|
extern crate webrender_traits;
|
2015-05-20 23:42:06 +03:00
|
|
|
|
2016-10-31 22:58:03 +03:00
|
|
|
use azure::azure::AzFloat;
|
2015-09-24 00:02:56 +03:00
|
|
|
use azure::azure_hl::{CapStyle, CompositionOp, JoinStyle};
|
2016-10-31 22:58:03 +03:00
|
|
|
use azure::azure_hl::{Color, ColorPattern, DrawTarget, Pattern};
|
2015-09-24 00:02:56 +03:00
|
|
|
use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern};
|
|
|
|
use azure::azure_hl::{SurfaceFormat, SurfacePattern};
|
2015-05-20 23:42:06 +03:00
|
|
|
use cssparser::RGBA;
|
2015-06-19 05:50:22 +03:00
|
|
|
use euclid::matrix2d::Matrix2D;
|
|
|
|
use euclid::point::Point2D;
|
|
|
|
use euclid::rect::Rect;
|
|
|
|
use euclid::size::Size2D;
|
2015-07-25 10:50:31 +03:00
|
|
|
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
2015-09-03 21:36:23 +03:00
|
|
|
use std::default::Default;
|
|
|
|
use std::str::FromStr;
|
2016-03-31 23:27:20 +03:00
|
|
|
use webrender_traits::{WebGLCommand, WebGLContextId};
|
2016-02-18 22:24:06 +03:00
|
|
|
|
2015-12-06 04:49:23 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
|
|
pub enum FillRule {
|
|
|
|
Nonzero,
|
|
|
|
Evenodd,
|
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum CanvasMsg {
|
|
|
|
Canvas2d(Canvas2dMsg),
|
|
|
|
Common(CanvasCommonMsg),
|
2015-07-25 10:50:31 +03:00
|
|
|
FromLayout(FromLayoutMsg),
|
2016-03-31 23:27:20 +03:00
|
|
|
WebGL(WebGLCommand),
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
servo: Merge #6380 - Refactor WebGL implementation to move logic inside the DOM interfaces (from emilio:webgl-refactoring); r=jdm
This improves the encapsulation and consistency in our WebGL
implementation.
Also allows to implement new methods such as `getShaderSource()`.
It will also allow us to use `delete()` in the destructors of them (note
that we will probably want to keep track of them from the context before).
Some concerns:
**Trait method repetition**:
I'm aware that the traits `WebGL{Buffer,Renderbuffer,Framebuffer,Texture}Helpers` are basically the same, but `delete()` and `id()` methods are everywhere. I've thought something like:
```rust
pub trait WebGLIdentifiable {
type WebGLId; // id is sometimes i32 (see WebGLUniformLocation)
fn id(&self) -> Self::WebGLId;
}
pub trait WebGLBindable {
fn bind(&self);
}
pub trait WebGLDeletable {
fn delete(&self);
}
```
But I'd want to know your opinion first.
**`renderer` repetition**:
Thought of moving the field: `renderer: Sender<CanvasMsg>` to `WebGLObject`, but I think it makes it way more complicated to read, and also a bit unnecessary, at least IMO (`WebGLObject` will never interact with the field directly). It would also mean that all `WebGLObject`s should have one, which is true at this moment, but maybe not with WebGL 2, for example.
Source-Repo: https://github.com/servo/servo
Source-Revision: 0f8095b950dd144497919cfea65a1f154ed3ae9a
2015-07-06 18:12:59 +03:00
|
|
|
pub enum CanvasCommonMsg {
|
|
|
|
Close,
|
|
|
|
Recreate(Size2D<i32>),
|
2015-07-25 10:50:31 +03:00
|
|
|
}
|
|
|
|
|
2016-02-18 22:24:06 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
|
|
pub enum CanvasData {
|
|
|
|
Pixels(CanvasPixelData),
|
|
|
|
WebGL(WebGLContextId),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
|
|
pub struct CanvasPixelData {
|
|
|
|
pub image_data: IpcSharedMemory,
|
2016-10-18 03:22:20 +03:00
|
|
|
pub image_key: webrender_traits::ImageKey,
|
2016-02-18 22:24:06 +03:00
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
|
|
pub enum FromLayoutMsg {
|
2016-02-18 22:24:06 +03:00
|
|
|
SendData(IpcSender<CanvasData>),
|
servo: Merge #6380 - Refactor WebGL implementation to move logic inside the DOM interfaces (from emilio:webgl-refactoring); r=jdm
This improves the encapsulation and consistency in our WebGL
implementation.
Also allows to implement new methods such as `getShaderSource()`.
It will also allow us to use `delete()` in the destructors of them (note
that we will probably want to keep track of them from the context before).
Some concerns:
**Trait method repetition**:
I'm aware that the traits `WebGL{Buffer,Renderbuffer,Framebuffer,Texture}Helpers` are basically the same, but `delete()` and `id()` methods are everywhere. I've thought something like:
```rust
pub trait WebGLIdentifiable {
type WebGLId; // id is sometimes i32 (see WebGLUniformLocation)
fn id(&self) -> Self::WebGLId;
}
pub trait WebGLBindable {
fn bind(&self);
}
pub trait WebGLDeletable {
fn delete(&self);
}
```
But I'd want to know your opinion first.
**`renderer` repetition**:
Thought of moving the field: `renderer: Sender<CanvasMsg>` to `WebGLObject`, but I think it makes it way more complicated to read, and also a bit unnecessary, at least IMO (`WebGLObject` will never interact with the field directly). It would also mean that all `WebGLObject`s should have one, which is true at this moment, but maybe not with WebGL 2, for example.
Source-Repo: https://github.com/servo/servo
Source-Revision: 0f8095b950dd144497919cfea65a1f154ed3ae9a
2015-07-06 18:12:59 +03:00
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum Canvas2dMsg {
|
|
|
|
Arc(Point2D<f32>, f32, f32, f32, bool),
|
|
|
|
ArcTo(Point2D<f32>, Point2D<f32>, f32),
|
|
|
|
DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
|
|
|
DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
|
2016-06-17 10:07:37 +03:00
|
|
|
DrawImageInOther(
|
|
|
|
IpcSender<CanvasMsg>, Size2D<f64>, Rect<f64>, Rect<f64>, bool, IpcSender<()>),
|
2015-05-20 23:42:06 +03:00
|
|
|
BeginPath,
|
|
|
|
BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
|
|
|
|
ClearRect(Rect<f32>),
|
|
|
|
Clip,
|
|
|
|
ClosePath,
|
|
|
|
Fill,
|
|
|
|
FillRect(Rect<f32>),
|
2015-08-09 15:32:30 +03:00
|
|
|
GetImageData(Rect<i32>, Size2D<f64>, IpcSender<Vec<u8>>),
|
2015-12-06 04:49:23 +03:00
|
|
|
IsPointInPath(f64, f64, FillRule, IpcSender<bool>),
|
2015-05-20 23:42:06 +03:00
|
|
|
LineTo(Point2D<f32>),
|
|
|
|
MoveTo(Point2D<f32>),
|
2015-08-09 16:00:56 +03:00
|
|
|
PutImageData(Vec<u8>, Point2D<f64>, Size2D<f64>, Rect<f64>),
|
2015-05-20 23:42:06 +03:00
|
|
|
QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
|
|
|
|
Rect(Rect<f32>),
|
|
|
|
RestoreContext,
|
|
|
|
SaveContext,
|
|
|
|
StrokeRect(Rect<f32>),
|
|
|
|
Stroke,
|
|
|
|
SetFillStyle(FillOrStrokeStyle),
|
|
|
|
SetStrokeStyle(FillOrStrokeStyle),
|
|
|
|
SetLineWidth(f32),
|
|
|
|
SetLineCap(LineCapStyle),
|
|
|
|
SetLineJoin(LineJoinStyle),
|
|
|
|
SetMiterLimit(f32),
|
|
|
|
SetGlobalAlpha(f32),
|
|
|
|
SetGlobalComposition(CompositionOrBlending),
|
|
|
|
SetTransform(Matrix2D<f32>),
|
2015-06-12 12:27:07 +03:00
|
|
|
SetShadowOffsetX(f64),
|
|
|
|
SetShadowOffsetY(f64),
|
|
|
|
SetShadowBlur(f64),
|
2015-06-12 19:22:54 +03:00
|
|
|
SetShadowColor(RGBA),
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub struct CanvasGradientStop {
|
|
|
|
pub offset: f64,
|
|
|
|
pub color: RGBA,
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
2015-06-13 10:49:50 +03:00
|
|
|
pub struct SurfaceStyle {
|
|
|
|
pub surface_data: Vec<u8>,
|
|
|
|
pub surface_size: Size2D<i32>,
|
|
|
|
pub repeat_x: bool,
|
|
|
|
pub repeat_y: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SurfaceStyle {
|
|
|
|
pub fn new(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat_x: bool, repeat_y: bool)
|
|
|
|
-> SurfaceStyle {
|
|
|
|
SurfaceStyle {
|
|
|
|
surface_data: surface_data,
|
|
|
|
surface_size: surface_size,
|
|
|
|
repeat_x: repeat_x,
|
|
|
|
repeat_y: repeat_y,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum FillOrStrokeStyle {
|
|
|
|
Color(RGBA),
|
|
|
|
LinearGradient(LinearGradientStyle),
|
|
|
|
RadialGradient(RadialGradientStyle),
|
2015-06-13 10:49:50 +03:00
|
|
|
Surface(SurfaceStyle),
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FillOrStrokeStyle {
|
2015-10-01 09:08:34 +03:00
|
|
|
pub fn to_azure_pattern(&self, drawtarget: &DrawTarget) -> Option<Pattern> {
|
2015-05-20 23:42:06 +03:00
|
|
|
match *self {
|
|
|
|
FillOrStrokeStyle::Color(ref color) => {
|
2016-10-31 22:58:03 +03:00
|
|
|
Some(Pattern::Color(ColorPattern::new(color.to_azcolor())))
|
2015-05-20 23:42:06 +03:00
|
|
|
},
|
|
|
|
FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => {
|
|
|
|
let gradient_stops: Vec<GradientStop> = linear_gradient_style.stops.iter().map(|s| {
|
|
|
|
GradientStop {
|
|
|
|
offset: s.offset as AzFloat,
|
2016-10-31 22:58:03 +03:00
|
|
|
color: s.color.to_azcolor()
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
|
2015-10-01 09:08:34 +03:00
|
|
|
Some(Pattern::LinearGradient(LinearGradientPattern::new(
|
2015-06-13 22:52:07 +03:00
|
|
|
&Point2D::new(linear_gradient_style.x0 as AzFloat, linear_gradient_style.y0 as AzFloat),
|
|
|
|
&Point2D::new(linear_gradient_style.x1 as AzFloat, linear_gradient_style.y1 as AzFloat),
|
2015-05-20 23:42:06 +03:00
|
|
|
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
|
2015-10-01 09:08:34 +03:00
|
|
|
&Matrix2D::identity())))
|
2015-05-20 23:42:06 +03:00
|
|
|
},
|
|
|
|
FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
|
|
|
|
let gradient_stops: Vec<GradientStop> = radial_gradient_style.stops.iter().map(|s| {
|
|
|
|
GradientStop {
|
|
|
|
offset: s.offset as AzFloat,
|
2016-10-31 22:58:03 +03:00
|
|
|
color: s.color.to_azcolor()
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
|
2015-10-01 09:08:34 +03:00
|
|
|
Some(Pattern::RadialGradient(RadialGradientPattern::new(
|
2015-06-13 22:52:07 +03:00
|
|
|
&Point2D::new(radial_gradient_style.x0 as AzFloat, radial_gradient_style.y0 as AzFloat),
|
|
|
|
&Point2D::new(radial_gradient_style.x1 as AzFloat, radial_gradient_style.y1 as AzFloat),
|
2015-05-20 23:42:06 +03:00
|
|
|
radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat,
|
|
|
|
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
|
2015-10-01 09:08:34 +03:00
|
|
|
&Matrix2D::identity())))
|
2015-06-13 10:49:50 +03:00
|
|
|
},
|
|
|
|
FillOrStrokeStyle::Surface(ref surface_style) => {
|
2015-10-01 09:08:34 +03:00
|
|
|
drawtarget.create_source_surface_from_data(&surface_style.surface_data,
|
|
|
|
surface_style.surface_size,
|
|
|
|
surface_style.surface_size.width * 4,
|
|
|
|
SurfaceFormat::B8G8R8A8)
|
|
|
|
.map(|source_surface| {
|
|
|
|
Pattern::Surface(SurfacePattern::new(
|
|
|
|
source_surface.azure_source_surface,
|
|
|
|
surface_style.repeat_x,
|
|
|
|
surface_style.repeat_y,
|
|
|
|
&Matrix2D::identity()))
|
|
|
|
})
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum LineCapStyle {
|
|
|
|
Butt = 0,
|
|
|
|
Round = 1,
|
|
|
|
Square = 2,
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl FromStr for LineCapStyle {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(string: &str) -> Result<LineCapStyle, ()> {
|
|
|
|
match string {
|
|
|
|
"butt" => Ok(LineCapStyle::Butt),
|
|
|
|
"round" => Ok(LineCapStyle::Round),
|
|
|
|
"square" => Ok(LineCapStyle::Square),
|
|
|
|
_ => Err(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 23:42:06 +03:00
|
|
|
impl LineCapStyle {
|
|
|
|
pub fn to_azure_style(&self) -> CapStyle {
|
|
|
|
match *self {
|
|
|
|
LineCapStyle::Butt => CapStyle::Butt,
|
|
|
|
LineCapStyle::Round => CapStyle::Round,
|
|
|
|
LineCapStyle::Square => CapStyle::Square,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum LineJoinStyle {
|
|
|
|
Round = 0,
|
|
|
|
Bevel = 1,
|
|
|
|
Miter = 2,
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl FromStr for LineJoinStyle {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(string: &str) -> Result<LineJoinStyle, ()> {
|
|
|
|
match string {
|
|
|
|
"round" => Ok(LineJoinStyle::Round),
|
|
|
|
"bevel" => Ok(LineJoinStyle::Bevel),
|
|
|
|
"miter" => Ok(LineJoinStyle::Miter),
|
|
|
|
_ => Err(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 23:42:06 +03:00
|
|
|
impl LineJoinStyle {
|
|
|
|
pub fn to_azure_style(&self) -> JoinStyle {
|
|
|
|
match *self {
|
|
|
|
LineJoinStyle::Round => JoinStyle::Round,
|
|
|
|
LineJoinStyle::Bevel => JoinStyle::Bevel,
|
|
|
|
LineJoinStyle::Miter => JoinStyle::Miter,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-25 10:50:31 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
|
2015-06-13 10:49:50 +03:00
|
|
|
pub enum RepetitionStyle {
|
|
|
|
Repeat,
|
|
|
|
RepeatX,
|
|
|
|
RepeatY,
|
|
|
|
NoRepeat,
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl FromStr for RepetitionStyle {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(string: &str) -> Result<RepetitionStyle, ()> {
|
2015-06-13 10:49:50 +03:00
|
|
|
match string {
|
2015-09-03 21:36:23 +03:00
|
|
|
"repeat" => Ok(RepetitionStyle::Repeat),
|
|
|
|
"repeat-x" => Ok(RepetitionStyle::RepeatX),
|
|
|
|
"repeat-y" => Ok(RepetitionStyle::RepeatY),
|
|
|
|
"no-repeat" => Ok(RepetitionStyle::NoRepeat),
|
|
|
|
_ => Err(()),
|
2015-06-13 10:49:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum CompositionStyle {
|
|
|
|
SrcIn,
|
|
|
|
SrcOut,
|
|
|
|
SrcOver,
|
|
|
|
SrcAtop,
|
|
|
|
DestIn,
|
|
|
|
DestOut,
|
|
|
|
DestOver,
|
|
|
|
DestAtop,
|
|
|
|
Copy,
|
|
|
|
Lighter,
|
|
|
|
Xor,
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl FromStr for CompositionStyle {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(string: &str) -> Result<CompositionStyle, ()> {
|
|
|
|
match string {
|
|
|
|
"source-in" => Ok(CompositionStyle::SrcIn),
|
|
|
|
"source-out" => Ok(CompositionStyle::SrcOut),
|
|
|
|
"source-over" => Ok(CompositionStyle::SrcOver),
|
|
|
|
"source-atop" => Ok(CompositionStyle::SrcAtop),
|
|
|
|
"destination-in" => Ok(CompositionStyle::DestIn),
|
|
|
|
"destination-out" => Ok(CompositionStyle::DestOut),
|
|
|
|
"destination-over" => Ok(CompositionStyle::DestOver),
|
|
|
|
"destination-atop" => Ok(CompositionStyle::DestAtop),
|
|
|
|
"copy" => Ok(CompositionStyle::Copy),
|
|
|
|
"lighter" => Ok(CompositionStyle::Lighter),
|
|
|
|
"xor" => Ok(CompositionStyle::Xor),
|
|
|
|
_ => Err(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 23:42:06 +03:00
|
|
|
impl CompositionStyle {
|
|
|
|
pub 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 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",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum BlendingStyle {
|
|
|
|
Multiply,
|
|
|
|
Screen,
|
|
|
|
Overlay,
|
|
|
|
Darken,
|
|
|
|
Lighten,
|
|
|
|
ColorDodge,
|
|
|
|
ColorBurn,
|
|
|
|
HardLight,
|
|
|
|
SoftLight,
|
|
|
|
Difference,
|
|
|
|
Exclusion,
|
|
|
|
Hue,
|
|
|
|
Saturation,
|
|
|
|
Color,
|
|
|
|
Luminosity,
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl FromStr for BlendingStyle {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(string: &str) -> Result<BlendingStyle, ()> {
|
|
|
|
match string {
|
|
|
|
"multiply" => Ok(BlendingStyle::Multiply),
|
|
|
|
"screen" => Ok(BlendingStyle::Screen),
|
|
|
|
"overlay" => Ok(BlendingStyle::Overlay),
|
|
|
|
"darken" => Ok(BlendingStyle::Darken),
|
|
|
|
"lighten" => Ok(BlendingStyle::Lighten),
|
|
|
|
"color-dodge" => Ok(BlendingStyle::ColorDodge),
|
|
|
|
"color-burn" => Ok(BlendingStyle::ColorBurn),
|
|
|
|
"hard-light" => Ok(BlendingStyle::HardLight),
|
|
|
|
"soft-light" => Ok(BlendingStyle::SoftLight),
|
|
|
|
"difference" => Ok(BlendingStyle::Difference),
|
|
|
|
"exclusion" => Ok(BlendingStyle::Exclusion),
|
|
|
|
"hue" => Ok(BlendingStyle::Hue),
|
|
|
|
"saturation" => Ok(BlendingStyle::Saturation),
|
|
|
|
"color" => Ok(BlendingStyle::Color),
|
|
|
|
"luminosity" => Ok(BlendingStyle::Luminosity),
|
|
|
|
_ => Err(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 23:42:06 +03:00
|
|
|
impl BlendingStyle {
|
|
|
|
pub 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 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",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:16:14 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
2015-05-20 23:42:06 +03:00
|
|
|
pub enum CompositionOrBlending {
|
|
|
|
Composition(CompositionStyle),
|
|
|
|
Blending(BlendingStyle),
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
impl Default for CompositionOrBlending {
|
|
|
|
fn default() -> CompositionOrBlending {
|
2015-05-20 23:42:06 +03:00
|
|
|
CompositionOrBlending::Composition(CompositionStyle::SrcOver)
|
|
|
|
}
|
2015-09-03 21:36:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for CompositionOrBlending {
|
|
|
|
type Err = ();
|
2015-05-20 23:42:06 +03:00
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
fn from_str(string: &str) -> Result<CompositionOrBlending, ()> {
|
|
|
|
if let Ok(op) = CompositionStyle::from_str(string) {
|
|
|
|
return Ok(CompositionOrBlending::Composition(op));
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
if let Ok(op) = BlendingStyle::from_str(string) {
|
|
|
|
return Ok(CompositionOrBlending::Blending(op));
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
|
2015-09-03 21:36:23 +03:00
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CompositionOrBlending {
|
|
|
|
pub fn to_azure_style(&self) -> CompositionOp {
|
|
|
|
match *self {
|
|
|
|
CompositionOrBlending::Composition(op) => op.to_azure_style(),
|
|
|
|
CompositionOrBlending::Blending(op) => op.to_azure_style(),
|
|
|
|
}
|
2015-05-20 23:42:06 +03:00
|
|
|
}
|
|
|
|
}
|
2015-06-12 19:22:54 +03:00
|
|
|
|
|
|
|
pub trait ToAzColor {
|
2016-10-31 22:58:03 +03:00
|
|
|
fn to_azcolor(&self) -> Color;
|
2015-06-12 19:22:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ToAzColor for RGBA {
|
2016-10-31 22:58:03 +03:00
|
|
|
fn to_azcolor(&self) -> Color {
|
|
|
|
Color::rgba(self.red as AzFloat,
|
2015-06-12 19:22:54 +03:00
|
|
|
self.green as AzFloat,
|
|
|
|
self.blue as AzFloat,
|
|
|
|
self.alpha as AzFloat)
|
|
|
|
}
|
|
|
|
}
|
2016-07-04 22:57:00 +03:00
|
|
|
|
|
|
|
// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
|
|
|
|
pub fn byte_swap(data: &mut [u8]) {
|
|
|
|
let length = data.len();
|
|
|
|
// FIXME(rust #27741): Range::step_by is not stable yet as of this writing.
|
|
|
|
let mut i = 0;
|
|
|
|
while i < length {
|
|
|
|
let r = data[i + 2];
|
|
|
|
data[i + 2] = data[i + 0];
|
|
|
|
data[i + 0] = r;
|
|
|
|
i += 4;
|
|
|
|
}
|
|
|
|
}
|
2016-08-30 06:59:28 +03:00
|
|
|
|
|
|
|
pub fn byte_swap_and_premultiply(data: &mut [u8]) {
|
|
|
|
let length = data.len();
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
while i < length {
|
|
|
|
let r = data[i + 2];
|
|
|
|
let g = data[i + 1];
|
|
|
|
let b = data[i + 0];
|
|
|
|
let a = data[i + 3];
|
|
|
|
|
|
|
|
data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
|
|
|
|
data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
|
|
|
|
data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
|
|
|
|
|
|
|
|
i += 4;
|
|
|
|
}
|
|
|
|
}
|