Implement very basic canvas rendering context logic. No visual display present.

This commit is contained in:
Aalhad 2013-12-05 21:10:11 -05:00 committed by Ms2ger
parent a14d3b2102
commit f8ba2c1190
8 changed files with 411 additions and 8 deletions

View file

@ -4,18 +4,35 @@
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use dom::document::Document;
use dom::element::HTMLCanvasElementTypeId;
use dom::element::{Element, HTMLCanvasElementTypeId, AttributeHandlers};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use servo_util::str::DOMString;
use geom::size::Size2D;
use std::cell::Cell;
use std::num;
static DefaultWidth: u32 = 300;
static DefaultHeight: u32 = 150;
#[deriving(Encodable)]
pub struct HTMLCanvasElement {
pub htmlelement: HTMLElement,
context: Traceable<Cell<Option<JS<CanvasRenderingContext2D>>>>,
width: Traceable<Cell<u32>>,
height: Traceable<Cell<u32>>,
}
impl HTMLCanvasElementDerived for EventTarget {
@ -27,7 +44,10 @@ impl HTMLCanvasElementDerived for EventTarget {
impl HTMLCanvasElement {
pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLCanvasElement {
HTMLCanvasElement {
htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document)
htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document),
context: Traceable::new(Cell::new(None)),
width: Traceable::new(Cell::new(DefaultWidth)),
height: Traceable::new(Cell::new(DefaultHeight)),
}
}
@ -38,6 +58,106 @@ impl HTMLCanvasElement {
}
pub trait HTMLCanvasElementMethods {
fn Width(&self) -> u32;
fn SetWidth(&self, width: u32);
fn Height(&self) -> u32;
fn SetHeight(&self, height: u32);
fn GetContext(&self, id: DOMString) -> Option<Temporary<CanvasRenderingContext2D>>;
}
impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
fn Width(&self) -> u32 {
self.width.get()
}
fn SetWidth(&self, width: u32) {
let elem: &JSRef<Element> = ElementCast::from_ref(self);
elem.set_uint_attribute("width", width)
}
fn Height(&self) -> u32 {
self.height.get()
}
fn SetHeight(&self, height: u32) {
let elem: &JSRef<Element> = ElementCast::from_ref(self);
elem.set_uint_attribute("height", height)
}
fn GetContext(&self, id: DOMString) -> Option<Temporary<CanvasRenderingContext2D>> {
if id.as_slice() != "2d" {
return None;
}
if self.context.get().is_none() {
let window = window_from_node(self).root();
let (w, h) = (self.width.get() as i32, self.height.get() as i32);
let context = CanvasRenderingContext2D::new(&Window(*window), Size2D(w, h));
self.context.assign(Some(context));
}
self.context.get().map(|context| Temporary::new(context))
}
}
impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> {
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods+> {
let element: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
Some(element as &VirtualMethods+)
}
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
match self.super_type() {
Some(ref s) => s.before_remove_attr(name.clone(), value.clone()),
_ => (),
}
let recreate = match name.as_slice() {
"width" => {
self.width.set(DefaultWidth);
true
}
"height" => {
self.height.set(DefaultHeight);
true
}
_ => false,
};
if recreate {
let (w, h) = (self.width.get() as i32, self.height.get() as i32);
match self.context.get() {
Some(ref context) => context.root().recreate(Size2D(w, h)),
None => ()
}
}
}
fn after_set_attr(&self, name: DOMString, value: DOMString) {
match self.super_type() {
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
_ => (),
}
let recreate = match name.as_slice() {
"width" => {
self.width.set(num::from_str_radix(value.as_slice(), 10).unwrap());
true
}
"height" => {
self.height.set(num::from_str_radix(value.as_slice(), 10).unwrap());
true
}
_ => false,
};
if recreate {
let (w, h) = (self.width.get() as i32, self.height.get() as i32);
match self.context.get() {
Some(ref context) => context.root().recreate(Size2D(w, h)),
None => ()
}
}
}
}
impl Reflectable for HTMLCanvasElement {