Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement pattern fill style for canvas. #6157

Merged
merged 1 commit into from Jun 13, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -301,7 +301,22 @@ impl<'a> CanvasPaintTask<'a> {
}

fn fill_rect(&self, rect: &Rect<f32>) {
self.drawtarget.fill_rect(rect, self.state.fill_style.to_pattern_ref(),
let draw_rect = Rect(rect.origin,
match self.state.fill_style {
Pattern::Surface(ref surface) => {
let surface_size = surface.size();
match (surface.repeat_x, surface.repeat_y) {
(true, true) => rect.size,
(true, false) => Size2D(rect.size.width, surface_size.height as f32),
(false, true) => Size2D(surface_size.width as f32, rect.size.height),
(false, false) => Size2D(surface_size.width as f32, surface_size.height as f32),
}
},
_ => rect.size,
}
);

self.drawtarget.fill_rect(&draw_rect, self.state.fill_style.to_pattern_ref(),
Some(&self.state.draw_options));
}

@@ -17,6 +17,7 @@ use azure::azure::{AzFloat, AzColor};
use azure::azure_hl::{DrawTarget, Pattern, ColorPattern};
use azure::azure_hl::{GradientStop, LinearGradientPattern, RadialGradientPattern, ExtendMode};
use azure::azure_hl::{JoinStyle, CapStyle, CompositionOp};
use azure::azure_hl::{SurfacePattern, SurfaceFormat};
use cssparser::RGBA;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
@@ -176,11 +177,33 @@ impl RadialGradientStyle {
}
}

#[derive(Clone)]
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,
}
}
}


#[derive(Clone)]
pub enum FillOrStrokeStyle {
Color(RGBA),
LinearGradient(LinearGradientStyle),
RadialGradient(RadialGradientStyle),
Surface(SurfaceStyle),
}

impl FillOrStrokeStyle {
@@ -220,6 +243,18 @@ impl FillOrStrokeStyle {
radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat,
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
&Matrix2D::identity()))
},
FillOrStrokeStyle::Surface(ref surface_style) => {
let source_surface = drawtarget.create_source_surface_from_data(
&surface_style.surface_data,
surface_style.surface_size,
surface_style.surface_size.width * 4,
SurfaceFormat::B8G8R8A8);

Pattern::Surface(SurfacePattern::new(
source_surface.azure_source_surface,
surface_style.repeat_x,
surface_style.repeat_y))
}
}
}
@@ -277,6 +312,26 @@ impl LineJoinStyle {
}
}

#[derive(Copy, Clone, PartialEq)]
pub enum RepetitionStyle {
Repeat,
RepeatX,
RepeatY,
NoRepeat,
}

impl RepetitionStyle {
pub fn from_str(string: &str) -> Option<RepetitionStyle> {
match string {
"repeat" => Some(RepetitionStyle::Repeat),
"repeat-x" => Some(RepetitionStyle::RepeatX),
"repeat-y" => Some(RepetitionStyle::RepeatY),
"no-repeat" => Some(RepetitionStyle::NoRepeat),
_ => None
}
}
}

#[derive(Copy, Clone, PartialEq)]
pub enum CompositionStyle {
SrcIn,
@@ -35,11 +35,12 @@ use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
use script_task::ScriptChan;

use canvas_traits::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
use canvas_traits::{LineCapStyle, LineJoinStyle, CompositionOrBlending};
use canvas_traits::{LineCapStyle, LineJoinStyle, CompositionOrBlending, RepetitionStyle};
use cssparser::RGBA;
use encoding::types::EncodingRef;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use geom::size::Size2D;
use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers;
use hyper::method::Method;
@@ -249,6 +250,7 @@ no_jsmanaged_fields!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>);
no_jsmanaged_fields!(Receiver<T>);
no_jsmanaged_fields!(Rect<T>);
no_jsmanaged_fields!(Size2D<T>);
no_jsmanaged_fields!(Arc<T>);
no_jsmanaged_fields!(Image, ImageCacheChan, ImageCacheTask, ScriptControlChan);
no_jsmanaged_fields!(Atom, Namespace);
@@ -272,6 +274,7 @@ no_jsmanaged_fields!(Matrix2D<T>);
no_jsmanaged_fields!(StorageType);
no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
no_jsmanaged_fields!(RepetitionStyle);

impl JSTraceable for Box<ScriptChan+Send> {
#[inline]
@@ -2,12 +2,54 @@
* 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/. */

use dom::bindings::utils::Reflector;
use canvas_traits::{FillOrStrokeStyle, SurfaceStyle, RepetitionStyle};
use dom::bindings::codegen::Bindings::CanvasPatternBinding;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::ToFillOrStrokeStyle;
use geom::size::Size2D;

// https://html.spec.whatwg.org/multipage/#canvaspattern
#[dom_struct]
pub struct CanvasPattern {
reflector_: Reflector,
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat_x: bool,
repeat_y: bool,
}

impl CanvasPattern {
fn new_inherited(surface_data: Vec<u8>, surface_size: Size2D<i32>, repeat: RepetitionStyle) -> CanvasPattern {
let (x, y) = match repeat {
RepetitionStyle::Repeat => (true, true),
RepetitionStyle::RepeatX => (true, false),
RepetitionStyle::RepeatY => (false, true),
RepetitionStyle::NoRepeat => (false, false),
};

CanvasPattern {
reflector_: Reflector::new(),
surface_data: surface_data,
surface_size: surface_size,
repeat_x: x,
repeat_y: y,
}
}
pub fn new(global: GlobalRef,
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle)
-> Temporary<CanvasPattern> {
reflect_dom_object(box CanvasPattern::new_inherited(surface_data, surface_size, repeat),
global, CanvasPatternBinding::Wrap)
}
}

impl<'a> ToFillOrStrokeStyle for JSRef<'a, CanvasPattern> {
fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle {
FillOrStrokeStyle::Surface(
SurfaceStyle::new(self.surface_data.clone(), self.surface_size, self.repeat_x, self.repeat_y))
}
}
@@ -9,13 +9,14 @@ use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::codegen::UnionTypes::HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D;
use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use dom::bindings::error::Error::{IndexSize, NotSupported, Type, InvalidState};
use dom::bindings::error::Error::{IndexSize, NotSupported, Type, InvalidState, Syntax};
use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, LayoutJS, Rootable, Temporary, Unrooted};
use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle};
use dom::canvaspattern::CanvasPattern;
use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers};
use dom::htmlimageelement::{HTMLImageElement, HTMLImageElementHelpers};
use dom::imagedata::{ImageData, ImageDataHelpers};
@@ -29,7 +30,7 @@ use geom::rect::Rect;
use geom::size::Size2D;

use canvas_traits::{CanvasMsg, Canvas2dMsg, CanvasCommonMsg};
use canvas_traits::{FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
use canvas_traits::{FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle, RepetitionStyle};
use canvas_traits::{LineCapStyle, LineJoinStyle, CompositionOrBlending};
use canvas::canvas_paint_task::CanvasPaintTask;

@@ -865,7 +866,10 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
Canvas2dMsg::SetFillStyle(gradient_root.r().to_fill_or_stroke_style()));
self.renderer.send(msg).unwrap();
}
_ => {}
StringOrCanvasGradientOrCanvasPattern::eCanvasPattern(pattern) => {
self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle(
pattern.root().r().to_fill_or_stroke_style()))).unwrap();
}
}
}

@@ -997,6 +1001,44 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
RadialGradientStyle::new(x0, y0, r0, x1, y1, r1, Vec::new()))))
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
repetition: DOMString) -> Fallible<Temporary<CanvasPattern>> {
match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r();

let url = match image_element.get_url() {
Some(url) => url,
None => return Err(InvalidState),
};

let img = match self.request_image_from_cache(url) {
ImageResponse::Loaded(img) => img,
ImageResponse::PlaceholderLoaded(_) | ImageResponse::None => return Err(InvalidState),
};

let image_size = Size2D(img.width as f64, img.height as f64);
let image_data = match img.pixels {
PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
};

if let Some(rep) = RepetitionStyle::from_str(&repetition) {
return Ok(CanvasPattern::new(self.global.root().r(),
image_data,
Size2D(image_size.width as i32, image_size.height as i32),
rep));
}
return Err(Syntax);
},
_ => return Err(Type("Not implemented".to_owned())),
}
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
fn LineWidth(self) -> f64 {
let state = self.state.borrow();
@@ -62,7 +62,8 @@ interface CanvasRenderingContext2D {
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
[Throws]
CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
//CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);
[Throws]
CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);

// shadows
attribute unrestricted double shadowOffsetX; // (default 0)

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.