Add cargo feature to control canvas backend.

This commit is contained in:
Josh Matthews 2019-05-29 14:50:45 -04:00
parent 42bf1984be
commit 3243f1753b
11 changed files with 1077 additions and 816 deletions

6
Cargo.lock generated
View file

@ -1258,7 +1258,7 @@ dependencies = [
[[package]]
name = "failure"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1329,7 +1329,7 @@ dependencies = [
"dirs 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"float-ord 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -5692,7 +5692,7 @@ dependencies = [
"checksum euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7a4719a544a67ed3fc33784c2bd2c6581663dfe83b719a6ae05c6dabc3b51c73"
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
"checksum expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa"
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"

View file

@ -11,10 +11,13 @@ name = "canvas"
path = "lib.rs"
[features]
azure_backend = ["azure"]
default = ["azure_backend"]
webgl_backtrace = ["canvas_traits/webgl_backtrace"]
raqote_backend = ["raqote"]
[dependencies]
azure = {git = "https://github.com/servo/rust-azure"}
azure = {git = "https://github.com/servo/rust-azure", optional = true}
byteorder = "1"
canvas_traits = {path = "../canvas_traits"}
compositing = {path = "../compositing"}
@ -27,7 +30,7 @@ ipc-channel = "0.11"
log = "0.4"
num-traits = "0.2"
offscreen_gl_context = {version = "0.22", features = ["serde", "osmesa"]}
raqote = {git = "https://github.com/jrmuizel/raqote"}
raqote = {git = "https://github.com/jrmuizel/raqote", optional = true}
pixels = {path = "../pixels"}
serde_bytes = "0.10"
servo_config = {path = "../config"}

View file

@ -0,0 +1,744 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use cssparser::RGBA;
use crate::canvas_data::{
Backend, CanvasPaintState, Color, CompositionOp, DrawOptions, GenericDrawTarget,
GenericPathBuilder, Path, Pattern, StrokeOptions,
};
use crate::canvas_paint_thread::AntialiasMode;
use azure::azure::{AzFloat, AzGradientStop, AzIntSize, AzPoint};
use azure::azure_hl;
use azure::azure_hl::SurfacePattern;
use azure::azure_hl::{AsAzurePoint, CapStyle, JoinStyle};
use azure::azure_hl::{BackendType, ColorPattern, DrawTarget};
use azure::azure_hl::{LinearGradientPattern, RadialGradientPattern};
use euclid::{Point2D, Rect, Size2D, Transform2D, Vector2D};
pub struct AzureBackend;
impl Backend for AzureBackend {
fn get_composition_op(&self, opts: &DrawOptions) -> CompositionOp {
CompositionOp::Azure(opts.as_azure().composition)
}
fn need_to_draw_shadow(&self, color: &Color) -> bool {
self.state.shadow_color.as_azure().a != 0.0f32
}
fn size_from_pattern(&self, rect: &Rect<f32>, pattern: &Pattern) -> Option<Size2D<f32>> {
match pattern {
Pattern::Azure(azure_hl::Pattern::Surface(ref surface)) => {
let surface_size = surface.size();
let size = match (surface.repeat_x, surface.repeat_y) {
(true, true) => rect.size,
(true, false) => Size2D::new(rect.size.width, surface_size.height as f32),
(false, true) => Size2D::new(surface_size.width as f32, rect.size.height),
(false, false) => {
Size2D::new(surface_size.width as f32, surface_size.height as f32)
},
};
Some(size)
}
Pattern::Azure(_) => None
}
}
fn set_shadow_color<'a>(&mut self, color: RGBA, state: &mut CanvasPaintState<'a>) {
state.shadow_color = Color::Azure(color.to_azure_style());
}
fn set_fill_style<'a>(
&mut self,
style: FillOrStrokeStyle,
state: &mut CanvasPaintState<'a>,
drawtarget: &GenericDrawTarget,
) {
if let Some(pattern) = style.to_azure_pattern(drawtarget) {
state.fill_style = Pattern::Azure(pattern)
}
}
fn set_stroke_style<'a>(
&mut self,
style: FillOrStrokeStyle,
state: &mut CanvasPaintState<'a>,
drawtarget: &GenericDrawTarget)
{
if let Some(pattern) = style.to_azure_pattern(drawtarget) {
state.stroke_style = Pattern::Azure(pattern)
}
}
fn set_global_composition<'a>(&mut self, op: CompositionOrBlending, state: &mut CanvasPaintState<'a>) {
state
.draw_options
.as_azure_mut()
.set_composition_op(op.to_azure_style());
}
fn create_drawtarget(&self, size: Size2D<u64>) -> Box<GenericDrawTarget> {
// FIXME(nox): Why is the size made of i32 values?
Box::new(DrawTarget::new(
BackendType::Skia,
size.to_i32(),
azure_hl::SurfaceFormat::B8G8R8A8,
))
}
fn recreate_paint_state<'a>(&self, state: &CanvasPaintState<'a>) -> CanvasPaintState<'a> {
CanvasPaintState::new(AntialiasMode::from_azure(
self.state.draw_options.as_azure().antialias
))
}
}
impl<'a> CanvasPaintState<'a> {
pub fn new(antialias: AntialiasMode) -> CanvasPaintState<'a> {
CanvasPaintState {
draw_options: DrawOptions::Azure(azure_hl::DrawOptions::new(1.0, azure_hl::CompositionOp::Over, antialias.into_azure())),
fill_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black()))),
stroke_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black()))),
stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new(
1.0,
JoinStyle::MiterOrBevel,
CapStyle::Butt,
10.0,
&[],
)),
transform: Transform2D::identity(),
shadow_offset_x: 0.0,
shadow_offset_y: 0.0,
shadow_blur: 0.0,
shadow_color: Color::Azure(azure_hl::Color::transparent()),
}
}
}
impl GenericPathBuilder for azure_hl::PathBuilder {
fn arc(
&self,
origin: Point2D<f32>,
radius: f32,
start_angle: f32,
end_angle: f32,
anticlockwise: bool,
) {
self.arc(
origin as Point2D<AzFloat>,
radius as AzFloat,
start_angle as AzFloat,
end_angle as AzFloat,
anticlockwise,
);
}
fn bezier_curve_to(
&self,
control_point1: &Point2D<f32>,
control_point2: &Point2D<f32>,
control_point3: &Point2D<f32>,
) {
self.bezier_curve_to(
control_point1 as &Point2D<AzFloat>,
control_point2 as &Point2D<AzFloat>,
control_point3 as &Point2D<AzFloat>,
);
}
fn close(&self) {
self.close();
}
fn ellipse(
&self,
origin: Point2D<f32>,
radius_x: f32,
radius_y: f32,
rotation_angle: f32,
start_angle: f32,
end_angle: f32,
anticlockwise: bool,
) {
self.ellipse(
origin as Point2D<AzFloat>,
radius_x as AzFloat,
radius_y as AzFloat,
rotation_angle as AzFloat,
start_angle as AzFloat,
end_angle as AzFloat,
anticlockwise,
);
}
fn get_current_point(&self) -> Point2D<f32> {
let AzPoint { x, y } = self.get_current_point();
Point2D::new(x as f32, y as f32)
}
fn line_to(&self, point: Point2D<f32>) {
self.line_to(point as Point2D<AzFloat>);
}
fn move_to(&self, point: Point2D<f32>) {
self.move_to(point as Point2D<AzFloat>);
}
fn quadratic_curve_to(&self, control_point: &Point2D<f32>, end_point: &Point2D<f32>) {
self.quadratic_curve_to(
control_point as &Point2D<AzFloat>,
end_point as &Point2D<AzFloat>,
);
}
fn finish(&self) -> Path {
Path::Azure(self.finish())
}
}
impl GenericDrawTarget for azure_hl::DrawTarget {
fn clear_rect(&self, rect: &Rect<f32>) {
self.clear_rect(rect as &Rect<AzFloat>);
}
fn copy_surface(&self, surface: SourceSurface, source: Rect<i32>, destination: Point2D<i32>) {
self.copy_surface(surface.into_azure(), source, destination);
}
fn create_gradient_stops(
&self,
gradient_stops: Vec<GradientStop>,
extend_mode: ExtendMode,
) -> GradientStops {
let gradient_stops: Vec<AzGradientStop> =
gradient_stops.into_iter().map(|x| x.into_azure()).collect();
GradientStops::Azure(self.create_gradient_stops(&gradient_stops, extend_mode.into_azure()))
}
fn create_path_builder(&self) -> Box<GenericPathBuilder> {
Box::new(self.create_path_builder())
}
fn create_similar_draw_target(
&self,
size: &Size2D<i32>,
format: SurfaceFormat,
) -> Box<GenericDrawTarget> {
Box::new(self.create_similar_draw_target(size, format.into_azure()))
}
fn create_source_surface_from_data(
&self,
data: &[u8],
size: Size2D<i32>,
stride: i32,
) -> Option<SourceSurface> {
self.create_source_surface_from_data(data, size, stride, azure_hl::SurfaceFormat::B8G8R8A8)
.map(|s| SourceSurface::Azure(s))
}
fn draw_surface(
&self,
surface: SourceSurface,
dest: Rect<f64>,
source: Rect<f64>,
filter: Filter,
draw_options: &DrawOptions,
) {
let surf_options = azure_hl::DrawSurfaceOptions::new(filter.as_azure(), true);
let draw_options = azure_hl::DrawOptions::new(
draw_options.as_azure().alpha,
draw_options.as_azure().composition.into_azure(),
azure_hl::AntialiasMode::None
);
self.draw_surface(
surface.into_azure(),
dest as Rect<AzFloat>,
source as Rect<AzFloat>,
surf_options.into_azure(),
options.into_azure(),
);
}
fn draw_surface_with_shadow(
&self,
surface: SourceSurface,
dest: &Point2D<f32>,
color: &Color,
offset: &Vector2D<f32>,
sigma: f32,
operator: CompositionOp,
) {
self.draw_surface_with_shadow(
surface.into_azure(),
dest as &Point2D<AzFloat>,
color.as_azure(),
offset as &Vector2D<AzFloat>,
sigma as AzFloat,
operator.into_azure(),
);
}
fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) {
self.fill(
path.as_azure(),
pattern.as_azure().to_pattern_ref(),
draw_options.as_azure(),
);
}
fn fill_rect(&self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>) {
self.fill_rect(
rect as &Rect<AzFloat>,
pattern.as_azure().to_pattern_ref(),
draw_options.map(|x| x.as_azure()),
);
}
fn get_format(&self) -> SurfaceFormat {
SurfaceFormat::Azure(self.get_format())
}
fn get_size(&self) -> Size2D<i32> {
let size = self.get_size();
Size2D::new(size.width, size.height)
}
fn get_transform(&self) -> Transform2D<f32> {
self.get_transform() as Transform2D<f32>
}
fn pop_clip(&self) {
self.pop_clip();
}
fn push_clip(&self, path: &Path) {
self.push_clip(path.as_azure());
}
fn set_transform(&self, matrix: &Transform2D<f32>) {
self.set_transform(matrix as &Transform2D<AzFloat>);
}
fn snapshot(&self) -> SourceSurface {
SourceSurface::Azure(self.snapshot())
}
fn stroke(
&self,
path: &Path,
pattern: Pattern,
stroke_options: &StrokeOptions,
draw_options: &DrawOptions,
) {
self.stroke(
path.as_azure(),
pattern.as_azure().to_pattern_ref(),
stroke_options.as_azure(),
draw_options.as_azure(),
);
}
fn stroke_line(
&self,
start: Point2D<f32>,
end: Point2D<f32>,
pattern: Pattern,
stroke_options: &StrokeOptions,
draw_options: &DrawOptions,
) {
let stroke_options = stroke_options.as_azure();
let cap = match stroke_options.line_join {
JoinStyle::Round => CapStyle::Round,
_ => CapStyle::Butt,
};
let stroke_opts = azure_hl::StrokeOptions::new(
stroke_options.line_width,
stroke_options.line_join,
cap,
stroke_options.miter_limit,
stroke_options.mDashPattern,
);
self.stroke_line(
start,
end,
pattern.as_azure().to_pattern_ref(),
stroke_options.as_azure(),
draw_options.as_azure(),
);
}
fn stroke_rect(
&self,
rect: &Rect<f32>,
pattern: Pattern,
stroke_options: &StrokeOptions,
draw_options: &DrawOptions,
) {
self.stroke_rect(
rect as &Rect<AzFloat>,
pattern.as_azure().to_pattern_ref(),
stroke_options.as_azure(),
draw_options.as_azure(),
);
}
fn snapshot_data(&self) -> &[u8] {
unsafe {
self.snapshot().get_data_surface().data()
}
}
}
impl AntialiasMode {
fn into_azure(self) -> azure_hl::AntialiasMode {
match self {
AntialiasMode::Default => azure_hl::AntialiasMode::Default,
AntialiasMode::None => azure_hl::AntialiasMode::None,
}
}
fn from_azure(val: azure_hl::AntialiasMode) {
match val {
azure_hl::AntialiasMode::Default => AntialiasMode::Default,
azure_hl::AntialiasMode::None => AntialiasMode::None,
}
}
}
impl ExtendMode {
fn into_azure(self) -> azure_hl::ExtendMode {
match self {
ExtendMode::Azure(m) => m,
}
}
}
impl GradientStop {
fn into_azure(self) -> AzGradientStop {
match self {
GradientStop::Azure(s) => s,
}
}
}
impl GradientStops {
fn into_azure(self) -> azure_hl::GradientStops {
match self {
GradientStops::Azure(s) => s,
}
}
}
impl Color {
fn as_azure(&self) -> &azure_hl::Color {
match self {
Color::Azure(s) => s,
}
}
}
impl CompositionOp {
fn into_azure(self) -> azure_hl::CompositionOp {
match self {
CompositionOp::Azure(s) => s,
}
}
}
impl SurfaceFormat {
fn into_azure(self) -> azure_hl::SurfaceFormat {
match self {
SurfaceFormat::Azure(s) => s,
}
}
}
impl SourceSurface {
fn into_azure(self) -> azure_hl::SourceSurface {
match self {
SourceSurface::Azure(s) => s,
}
}
}
impl IntSize {
fn into_azure(self) -> AzIntSize {
match self {
IntSize::Azure(s) => s,
}
}
}
impl Path {
fn as_azure(&self) -> &azure_hl::Path {
match self {
Path::Azure(p) => p,
}
}
}
impl Pattern {
fn as_azure(&self) -> &azure_hl::Pattern {
match self {
Pattern::Azure(p) => p,
}
}
}
impl DrawSurfaceOptions {
fn into_azure(self) -> azure_hl::DrawSurfaceOptions {
match self {
DrawSurfaceOptions::Azure(options) => options,
}
}
}
impl DrawOptions {
fn as_azure(&self) -> &azure_hl::DrawOptions {
match self {
DrawOptions::Azure(options) => options,
}
}
fn as_azure_mut(&mut self) -> &mut azure_hl::DrawOptions {
match self {
DrawOptions::Azure(options) => options,
}
}
fn into_azure(self) -> azure_hl::DrawOptions {
match self {
DrawOptions::Azure(options) => options,
}
}
pub fn set_alpha(&mut self, val: f32) {
match self {
DrawOptions::Azure(options) => options.alpha = val as AzFloat,
}
}
}
impl<'a> StrokeOptions<'a> {
pub fn as_azure(&self) -> &azure_hl::StrokeOptions<'a> {
match self {
StrokeOptions::Azure(options) => options,
}
}
pub fn set_line_width(&mut self, val: f32) {
match self {
StrokeOptions::Azure(options) => options.line_width = val as AzFloat,
}
}
pub fn set_miter_limit(&mut self, val: f32) {
match self {
StrokeOptions::Azure(options) => options.miter_limit = val as AzFloat,
}
}
pub fn set_line_join(&mut self, val: LineJoinStyle) {
match self {
StrokeOptions::Azure(options) => options.line_join = val.to_azure_style(),
}
}
pub fn set_line_cap(&mut self, val: LineCapStyle) {
match self {
StrokeOptions::Azure(options) => options.line_cap = val.to_azure_style(),
}
}
}
pub trait ToAzureStyle {
type Target;
fn to_azure_style(self) -> Self::Target;
}
impl ToAzureStyle for Rect<f64> {
type Target = Rect<f32>;
fn to_azure_style(self) -> Rect<f32> {
Rect::new(
Point2D::new(self.origin.x as f32, self.origin.y as f32),
Size2D::new(self.size.width as f32, self.size.height as f32),
)
}
}
impl ToAzureStyle for LineCapStyle {
type Target = CapStyle;
fn to_azure_style(self) -> CapStyle {
match self {
LineCapStyle::Butt => CapStyle::Butt,
LineCapStyle::Round => CapStyle::Round,
LineCapStyle::Square => CapStyle::Square,
}
}
}
impl ToAzureStyle for LineJoinStyle {
type Target = JoinStyle;
fn to_azure_style(self) -> JoinStyle {
match self {
LineJoinStyle::Round => JoinStyle::Round,
LineJoinStyle::Bevel => JoinStyle::Bevel,
LineJoinStyle::Miter => JoinStyle::Miter,
}
}
}
impl ToAzureStyle for CompositionStyle {
type Target = azure_hl::CompositionOp;
fn to_azure_style(self) -> azure_hl::CompositionOp {
match self {
CompositionStyle::SrcIn => azure_hl::CompositionOp::In,
CompositionStyle::SrcOut => azure_hl::CompositionOp::Out,
CompositionStyle::SrcOver => azure_hl::CompositionOp::Over,
CompositionStyle::SrcAtop => azure_hl::CompositionOp::Atop,
CompositionStyle::DestIn => azure_hl::CompositionOp::DestIn,
CompositionStyle::DestOut => azure_hl::CompositionOp::DestOut,
CompositionStyle::DestOver => azure_hl::CompositionOp::DestOver,
CompositionStyle::DestAtop => azure_hl::CompositionOp::DestAtop,
CompositionStyle::Copy => azure_hl::CompositionOp::Source,
CompositionStyle::Lighter => azure_hl::CompositionOp::Add,
CompositionStyle::Xor => azure_hl::CompositionOp::Xor,
}
}
}
impl ToAzureStyle for BlendingStyle {
type Target = azure_hl::CompositionOp;
fn to_azure_style(self) -> azure_hl::CompositionOp {
match self {
BlendingStyle::Multiply => azure_hl::CompositionOp::Multiply,
BlendingStyle::Screen => azure_hl::CompositionOp::Screen,
BlendingStyle::Overlay => azure_hl::CompositionOp::Overlay,
BlendingStyle::Darken => azure_hl::CompositionOp::Darken,
BlendingStyle::Lighten => azure_hl::CompositionOp::Lighten,
BlendingStyle::ColorDodge => azure_hl::CompositionOp::ColorDodge,
BlendingStyle::ColorBurn => azure_hl::CompositionOp::ColorBurn,
BlendingStyle::HardLight => azure_hl::CompositionOp::HardLight,
BlendingStyle::SoftLight => azure_hl::CompositionOp::SoftLight,
BlendingStyle::Difference => azure_hl::CompositionOp::Difference,
BlendingStyle::Exclusion => azure_hl::CompositionOp::Exclusion,
BlendingStyle::Hue => azure_hl::CompositionOp::Hue,
BlendingStyle::Saturation => azure_hl::CompositionOp::Saturation,
BlendingStyle::Color => azure_hl::CompositionOp::Color,
BlendingStyle::Luminosity => azure_hl::CompositionOp::Luminosity,
}
}
}
impl ToAzureStyle for CompositionOrBlending {
type Target = azure_hl::CompositionOp;
fn to_azure_style(self) -> azure_hl::CompositionOp {
match self {
CompositionOrBlending::Composition(op) => op.to_azure_style(),
CompositionOrBlending::Blending(op) => op.to_azure_style(),
}
}
}
pub trait ToAzurePattern {
fn to_azure_pattern(&self, drawtarget: &GenericDrawTarget) -> Option<azure_hl::Pattern>;
}
impl ToAzurePattern for FillOrStrokeStyle {
fn to_azure_pattern(&self, drawtarget: &GenericDrawTarget) -> Option<azure_hl::Pattern> {
Some(match *self {
FillOrStrokeStyle::Color(ref color) => {
azure_hl::Pattern::Color(ColorPattern::new(color.to_azure_style()))
},
FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => {
let gradient_stops: Vec<GradientStop> = linear_gradient_style
.stops
.iter()
.map(|s| GradientStop::Azure(azure_hl::GradientStop {
offset: s.offset as f32,
color: s.color.to_azure_style(),
}))
.collect();
azure_hl::Pattern::LinearGradient(LinearGradientPattern::new(
&Point2D::new(
linear_gradient_style.x0 as f32,
linear_gradient_style.y0 as f32,
),
&Point2D::new(
linear_gradient_style.x1 as f32,
linear_gradient_style.y1 as f32,
),
drawtarget.create_gradient_stops(gradient_stops, ExtendMode::Azure(azure_hl::ExtendMode::Clamp)).into_azure(),
&Transform2D::identity(),
))
},
FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
let gradient_stops: Vec<GradientStop> = radial_gradient_style
.stops
.iter()
.map(|s| GradientStop::Azure(azure_hl::GradientStop {
offset: s.offset as f32,
color: s.color.to_azure_style(),
}))
.collect();
azure_hl::Pattern::RadialGradient(RadialGradientPattern::new(
&Point2D::new(
radial_gradient_style.x0 as f32,
radial_gradient_style.y0 as f32,
),
&Point2D::new(
radial_gradient_style.x1 as f32,
radial_gradient_style.y1 as f32,
),
radial_gradient_style.r0 as f32,
radial_gradient_style.r1 as f32,
drawtarget.create_gradient_stops(gradient_stops, ExtendMode::Azure(azure_hl::ExtendMode::Clamp)).into_azure(),
&Transform2D::identity(),
))
},
FillOrStrokeStyle::Surface(ref surface_style) => {
let source_surface = drawtarget.create_source_surface_from_data(
&surface_style.surface_data,
// FIXME(nox): Why are those i32 values?
surface_style.surface_size.to_i32(),
surface_style.surface_size.width as i32 * 4,
)?.into_azure();
azure_hl::Pattern::Surface(SurfacePattern::new(
source_surface.azure_source_surface,
surface_style.repeat_x,
surface_style.repeat_y,
&Transform2D::identity(),
))
},
})
}
}
impl ToAzureStyle for RGBA {
type Target = azure_hl::Color;
fn to_azure_style(self) -> azure_hl::Color {
azure_hl::Color::rgba(
self.red_f32() as f32,
self.green_f32() as f32,
self.blue_f32() as f32,
self.alpha_f32() as f32,
)
}
}
impl Pattern {
pub fn is_zero_size_gradient(&self) -> bool {
match *self {
Pattern::Azure(azure_hl::Pattern::LinearGradient(ref az_pattern)) => {
gradient.is_zero_size()
}
_ => false,
}
}
}
impl Filter {
fn as_azure(&self) -> azure_hl::Filter {
match *self {
Filter::Linear => azure_hl::Filter::Linear,
Filter::Point => azure_hl::Filter::Point,
}
}
}
impl Path {
pub fn transformed_copy_to_builder(&self, transform: &Transform2D<f32>) -> Box<GenericPathBuilder> {
Box::new(self.as_azure().transformed_copy_to_builder(transform))
}
pub fn contains_point(&self, x: f64, y: f64, path_transform: &Transform2D<f32>) -> bool {
self.as_azure().contains_point(x, y, path_transform)
}
pub fn copy_to_builder(&self) -> Box<GenericPathBuilder> {
self.as_azure().copy_to_builder()
}
}

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::canvas_data::*;
use azure::azure_hl::AntialiasMode;
use canvas_traits::canvas::*;
use euclid::Size2D;
use ipc_channel::ipc::{self, IpcSender};
@ -11,6 +10,11 @@ use std::borrow::ToOwned;
use std::collections::HashMap;
use std::thread;
pub enum AntialiasMode {
Default,
None,
}
pub struct CanvasPaintThread<'a> {
canvases: HashMap<CanvasId, CanvasData<'a>>,
next_canvas_id: CanvasId,
@ -195,9 +199,9 @@ impl<'a> CanvasPaintThread<'a> {
self.canvas(canvas_id).set_shadow_offset_y(value)
},
Canvas2dMsg::SetShadowBlur(value) => self.canvas(canvas_id).set_shadow_blur(value),
Canvas2dMsg::SetShadowColor(ref color) => self
Canvas2dMsg::SetShadowColor(color) => self
.canvas(canvas_id)
.set_shadow_color(Color::Azure(color.to_azure_style())),
.set_shadow_color(color),
}
}

View file

@ -7,6 +7,12 @@
#[macro_use]
extern crate log;
#[cfg(feature = "azure_backend")]
mod azure_backend;
#[cfg(feature = "raqote_backend")]
mod raqote_backend;
pub mod canvas_data;
pub mod canvas_paint_thread;
pub mod gl_context;

View file

@ -0,0 +1,124 @@
/* 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 https://mozilla.org/MPL/2.0/. */
use cssparser::RGBA;
use crate::canvas_data::{
Backend, CanvasPaintState, Color, CompositionOp, DrawOptions, GenericDrawTarget,
GenericPathBuilder, Path, Pattern, StrokeOptions,
};
use crate::canvas_paint_thread::AntialiasMode;
use canvas_traits::canvas::*;
use euclid::{Rect, Size2D, Transform2D};
use std::marker::PhantomData;
pub struct RaqoteBackend;
impl Backend for RaqoteBackend {
fn get_composition_op(&self, _opts: &DrawOptions) -> CompositionOp {
unimplemented!()
}
fn need_to_draw_shadow(&self, _color: &Color) -> bool {
unimplemented!()
}
fn size_from_pattern(&self, _rect: &Rect<f32>, _pattern: &Pattern) -> Option<Size2D<f32>> {
unimplemented!()
}
fn set_shadow_color<'a>(&mut self, _color: RGBA, _state: &mut CanvasPaintState<'a>) {
unimplemented!()
}
fn set_fill_style<'a>(
&mut self,
_style: FillOrStrokeStyle,
_state: &mut CanvasPaintState<'a>,
_drawtarget: &GenericDrawTarget,
) {
unimplemented!()
}
fn set_stroke_style<'a>(
&mut self,
_style: FillOrStrokeStyle,
_state: &mut CanvasPaintState<'a>,
_drawtarget: &GenericDrawTarget)
{
unimplemented!()
}
fn set_global_composition<'a>(&mut self, _op: CompositionOrBlending, _state: &mut CanvasPaintState<'a>) {
unimplemented!()
}
fn create_drawtarget(&self, _size: Size2D<u64>) -> Box<GenericDrawTarget> {
unimplemented!()
}
fn recreate_paint_state<'a>(&self, _state: &CanvasPaintState<'a>) -> CanvasPaintState<'a> {
CanvasPaintState::new(AntialiasMode::Default)
}
}
impl<'a> CanvasPaintState<'a> {
pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> {
CanvasPaintState {
draw_options: DrawOptions::Raqote(()),
fill_style: Pattern::Raqote(()),
stroke_style: Pattern::Raqote(()),
stroke_opts: StrokeOptions::Raqote(PhantomData),
transform: Transform2D::identity(),
shadow_offset_x: 0.0,
shadow_offset_y: 0.0,
shadow_blur: 0.0,
shadow_color: Color::Raqote(()),
}
}
}
impl Pattern {
pub fn is_zero_size_gradient(&self) -> bool {
match *self {
Pattern::Raqote(()) => unimplemented!(),
}
}
}
impl<'a> StrokeOptions<'a> {
pub fn set_line_width(&mut self, _val: f32) {
unimplemented!()
}
pub fn set_miter_limit(&mut self, _val: f32) {
unimplemented!()
}
pub fn set_line_join(&mut self, _val: LineJoinStyle) {
unimplemented!()
}
pub fn set_line_cap(&mut self, _val: LineCapStyle) {
unimplemented!()
}
}
impl DrawOptions {
pub fn set_alpha(&mut self, _val: f32) {
match self {
DrawOptions::Raqote(()) => unimplemented!(),
}
}
}
impl Path {
pub fn transformed_copy_to_builder(&self, _transform: &Transform2D<f32>) -> Box<GenericPathBuilder> {
unimplemented!()
}
pub fn contains_point(&self, _x: f64, _y: f64, _path_transform: &Transform2D<f32>) -> bool {
unimplemented!()
}
pub fn copy_to_builder(&self) -> Box<GenericPathBuilder> {
unimplemented!()
}
}

View file

@ -10,11 +10,15 @@ publish = false
name = "constellation"
path = "lib.rs"
[features]
azure_backend = ["canvas/azure_backend"]
raqote_backend = ["canvas/raqote_backend"]
[dependencies]
background_hang_monitor = { path = "../background_hang_monitor"}
backtrace = "0.3"
bluetooth_traits = { path = "../bluetooth_traits" }
canvas = {path = "../canvas"}
canvas = {path = "../canvas", default-features = false}
clipboard = "0.5"
canvas_traits = {path = "../canvas_traits"}
compositing = {path = "../compositing"}

View file

@ -12,14 +12,15 @@ path = "lib.rs"
crate-type = ["rlib"]
[features]
max_log_level = ["log/release_max_level_info"]
webdriver = ["webdriver_server"]
energy-profiling = ["profile_traits/energy-profiling"]
azure_backend = ["canvas/azure_backend"]
debugmozjs = ["script/debugmozjs"]
energy-profiling = ["profile_traits/energy-profiling"]
profilemozjs = ["script/profilemozjs"]
googlevr = ["webvr/googlevr"]
js_backtrace = ["script/js_backtrace"]
max_log_level = ["log/release_max_level_info"]
native-bluetooth = ["bluetooth/native-bluetooth"]
raqote_backend = ["canvas/raqote_backend"]
webrender_debugger = ["webrender/debugger"]
no_static_freetype = ["webrender/no_static_freetype"]
oculusvr = ["webvr/oculusvr"]
@ -28,6 +29,7 @@ unstable = [
"profile/unstable",
"script/unstable",
]
webdriver = ["webdriver_server"]
webgl_backtrace = [
"script/webgl_backtrace",
"canvas/webgl_backtrace",
@ -38,7 +40,7 @@ webgl_backtrace = [
background_hang_monitor = {path = "../background_hang_monitor"}
bluetooth_traits = {path = "../bluetooth_traits"}
bluetooth = {path = "../bluetooth"}
canvas = {path = "../canvas"}
canvas = {path = "../canvas", default-features = false}
canvas_traits = {path = "../canvas_traits"}
compositing = {path = "../compositing", features = ["gl"]}
constellation = {path = "../constellation"}

View file

@ -27,18 +27,20 @@ OriginalFilename = "servo.exe"
ProductName = "Servo"
[features]
azure_backend = ["libservo/azure_backend"]
default = ["unstable", "default-except-unstable"]
default-except-unstable = ["webdriver", "max_log_level"]
native-bluetooth = ["libservo/native-bluetooth"]
max_log_level = ["log/release_max_level_info"]
webdriver = ["libservo/webdriver"]
energy-profiling = ["libservo/energy-profiling"]
debugmozjs = ["libservo/debugmozjs"]
js_backtrace = ["libservo/js_backtrace"]
max_log_level = ["log/release_max_level_info"]
native-bluetooth = ["libservo/native-bluetooth"]
profilemozjs = ["libservo/profilemozjs"]
raqote_backend = ["libservo/raqote_backend"]
unstable = ["libservo/unstable"]
webdriver = ["libservo/webdriver"]
webgl_backtrace = ["libservo/webgl_backtrace"]
webrender_debugger = ["libservo/webrender_debugger"]
js_backtrace = ["libservo/js_backtrace"]
[target.'cfg(not(target_os = "android"))'.dependencies]
backtrace = "0.3"

View file

@ -296,6 +296,9 @@ class MachCommands(CommandBase):
if self.config["build"]["dom-backtrace"]:
features += ["dom-backtrace"]
if "raqote_backend" not in features:
features += ["azure_backend"]
if features:
opts += ["--features", "%s" % ' '.join(features)]