mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Implement very basic canvas rendering context logic. No visual display present.
This commit is contained in:
parent
a14d3b2102
commit
f8ba2c1190
8 changed files with 411 additions and 8 deletions
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue