Skip to content

Commit

Permalink
add SVGElement, SVGGraphicsElement interfaces and SVGSVGElement element
Browse files Browse the repository at this point in the history
  • Loading branch information
splav committed Oct 6, 2016
1 parent 318b23e commit 9876020
Show file tree
Hide file tree
Showing 13 changed files with 353 additions and 11 deletions.
53 changes: 46 additions & 7 deletions components/script/dom/create.rs
Expand Up @@ -76,21 +76,44 @@ use dom::htmltrackelement::HTMLTrackElement;
use dom::htmlulistelement::HTMLUListElement;
use dom::htmlunknownelement::HTMLUnknownElement;
use dom::htmlvideoelement::HTMLVideoElement;
use dom::svgsvgelement::SVGSVGElement;
use string_cache::{Atom, QualName};
use util::prefs::PREFS;

pub fn create_element(name: QualName,
prefix: Option<Atom>,
document: &Document,
creator: ElementCreator)
fn create_svg_element(name: QualName,
prefix: Option<DOMString>,
document: &Document)
-> Root<Element> {
// FIXME(ajeffrey): Convert directly from Atom to DOMString.
assert!(name.ns == ns!(svg));

let prefix = prefix.map(|p| DOMString::from(&*p));
macro_rules! make(
($ctor:ident) => ({
let obj = $ctor::new(name.local, prefix, document);
Root::upcast(obj)
});
($ctor:ident, $($arg:expr),+) => ({
let obj = $ctor::new(name.local, prefix, document, $($arg),+);
Root::upcast(obj)
})
);

if name.ns != ns!(html) {
if !PREFS.get("dom.svg.enabled").as_boolean().unwrap_or(false) {
return Element::new(name.local, name.ns, prefix, document);
}

match name.local {
atom!("svg") => make!(SVGSVGElement),
_ => Element::new(name.local, name.ns, prefix, document),
}
}

fn create_html_element(name: QualName,
prefix: Option<DOMString>,
document: &Document,
creator: ElementCreator)
-> Root<Element> {
assert!(name.ns == ns!(html));

macro_rules! make(
($ctor:ident) => ({
let obj = $ctor::new(name.local, prefix, document);
Expand Down Expand Up @@ -249,3 +272,19 @@ pub fn create_element(name: QualName,
_ => make!(HTMLUnknownElement),
}
}

pub fn create_element(name: QualName,
prefix: Option<Atom>,
document: &Document,
creator: ElementCreator)
-> Root<Element> {
// FIXME(ajeffrey): Convert directly from Atom to DOMString.

let prefix = prefix.map(|p| DOMString::from(&*p));

match name.ns {
ns!(html) => create_html_element(name, prefix, document, creator),
ns!(svg) => create_svg_element(name, prefix, document),
_ => Element::new(name.local, name.ns, prefix, document)
}
}
3 changes: 3 additions & 0 deletions components/script/dom/mod.rs
Expand Up @@ -391,6 +391,9 @@ pub mod storage;
pub mod storageevent;
pub mod stylesheet;
pub mod stylesheetlist;
pub mod svgelement;
pub mod svggraphicselement;
pub mod svgsvgelement;
pub mod testbinding;
pub mod testbindingiterable;
pub mod testbindingpairiterable;
Expand Down
16 changes: 13 additions & 3 deletions components/script/dom/node.rs
Expand Up @@ -23,6 +23,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::{Castable, CharacterDataTypeId, ElementTypeId};
use dom::bindings::inheritance::{EventTargetTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::inheritance::{SVGElementTypeId, SVGGraphicsElementTypeId};
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::Root;
use dom::bindings::js::RootedReference;
Expand All @@ -36,7 +37,7 @@ use dom::documenttype::DocumentType;
use dom::element::{Element, ElementCreator};
use dom::eventtarget::EventTarget;
use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlcanvaselement::LayoutHTMLCanvasElementHelpers;
use dom::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
Expand All @@ -46,6 +47,7 @@ use dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHel
use dom::nodelist::NodeList;
use dom::processinginstruction::ProcessingInstruction;
use dom::range::WeakRangeVec;
use dom::svgsvgelement::{SVGSVGElement, LayoutSVGSVGElementHelpers};
use dom::text::Text;
use dom::virtualmethods::{VirtualMethods, vtable_for};
use dom::window::Window;
Expand All @@ -59,7 +61,7 @@ use libc::{self, c_void, uintptr_t};
use msg::constellation_msg::PipelineId;
use parse::html::parse_html_fragment;
use ref_slice::ref_slice;
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData};
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
use script_layout_interface::message::Msg;
use script_traits::UntrustedNodeAddress;
Expand Down Expand Up @@ -955,6 +957,7 @@ pub trait LayoutNodeHelpers {
fn selection(&self) -> Option<Range<usize>>;
fn image_url(&self) -> Option<Url>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
fn svg_data(&self) -> Option<SVGSVGData>;
fn iframe_pipeline_id(&self) -> PipelineId;
fn opaque(&self) -> OpaqueNode;
}
Expand Down Expand Up @@ -1088,10 +1091,15 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
}

fn canvas_data(&self) -> Option<HTMLCanvasData> {
self.downcast()
self.downcast::<HTMLCanvasElement>()
.map(|canvas| canvas.data())
}

fn svg_data(&self) -> Option<SVGSVGData> {
self.downcast::<SVGSVGElement>()
.map(|svg| svg.data())
}

fn iframe_pipeline_id(&self) -> PipelineId {
let iframe_element = self.downcast::<HTMLIFrameElement>()
.expect("not an iframe element!");
Expand Down Expand Up @@ -2687,6 +2695,8 @@ impl Into<LayoutElementType> for ElementTypeId {
LayoutElementType::HTMLTableSectionElement,
ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement) =>
LayoutElementType::HTMLTextAreaElement,
ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(SVGGraphicsElementTypeId::SVGSVGElement)) =>
LayoutElementType::SVGSVGElement,
_ => LayoutElementType::Element,
}
}
Expand Down
48 changes: 48 additions & 0 deletions components/script/dom/svgelement.rs
@@ -0,0 +1,48 @@
/* 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/. */

use dom::bindings::codegen::Bindings::SVGElementBinding;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::Element;
use dom::node::Node;
use dom::virtualmethods::VirtualMethods;
use string_cache::Atom;
use style::element_state::ElementState;

#[dom_struct]
pub struct SVGElement {
element: Element,
}

impl SVGElement {
pub fn new_inherited(tag_name: Atom, prefix: Option<DOMString>,
document: &Document) -> SVGElement {
SVGElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document)
}

pub fn new_inherited_with_state(state: ElementState, tag_name: Atom,
prefix: Option<DOMString>, document: &Document)
-> SVGElement {
SVGElement {
element:
Element::new_inherited_with_state(state, tag_name, ns!(svg), prefix, document),
}
}

#[allow(unrooted_must_root)]
pub fn new(local_name: Atom, prefix: Option<DOMString>, document: &Document) -> Root<SVGElement> {
Node::reflect_node(box SVGElement::new_inherited(local_name, prefix, document),
document,
SVGElementBinding::Wrap)
}
}

impl VirtualMethods for SVGElement {
fn super_type(&self) -> Option<&VirtualMethods> {
Some(self.upcast::<Element>() as &VirtualMethods)
}
}
48 changes: 48 additions & 0 deletions components/script/dom/svggraphicselement.rs
@@ -0,0 +1,48 @@
/* 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/. */

use dom::bindings::codegen::Bindings::SVGGraphicsElementBinding;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::node::Node;
use dom::svgelement::SVGElement;
use dom::virtualmethods::VirtualMethods;
use string_cache::Atom;
use style::element_state::ElementState;

#[dom_struct]
pub struct SVGGraphicsElement {
svgelement: SVGElement,
}

impl SVGGraphicsElement {
pub fn new_inherited(tag_name: Atom, prefix: Option<DOMString>,
document: &Document) -> SVGGraphicsElement {
SVGGraphicsElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document)
}

pub fn new_inherited_with_state(state: ElementState, tag_name: Atom,
prefix: Option<DOMString>, document: &Document)
-> SVGGraphicsElement {
SVGGraphicsElement {
svgelement:
SVGElement::new_inherited_with_state(state, tag_name, prefix, document),
}
}

#[allow(unrooted_must_root)]
pub fn new(local_name: Atom, prefix: Option<DOMString>, document: &Document) -> Root<SVGGraphicsElement> {
Node::reflect_node(box SVGGraphicsElement::new_inherited(local_name, prefix, document),
document,
SVGGraphicsElementBinding::Wrap)
}
}

impl VirtualMethods for SVGGraphicsElement {
fn super_type(&self) -> Option<&VirtualMethods> {
Some(self.upcast::<SVGElement>() as &VirtualMethods)
}
}
83 changes: 83 additions & 0 deletions components/script/dom/svgsvgelement.rs
@@ -0,0 +1,83 @@
/* 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/. */

use dom::attr::Attr;
use dom::bindings::codegen::Bindings::SVGSVGElementBinding;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
use dom::node::Node;
use dom::svggraphicselement::SVGGraphicsElement;
use dom::virtualmethods::VirtualMethods;
use script_layout_interface::SVGSVGData;
use string_cache::Atom;
use style::attr::AttrValue;

const DEFAULT_WIDTH: u32 = 300;
const DEFAULT_HEIGHT: u32 = 150;

#[dom_struct]
pub struct SVGSVGElement {
svggraphicselement: SVGGraphicsElement
}

impl SVGSVGElement {
fn new_inherited(local_name: Atom,
prefix: Option<DOMString>,
document: &Document) -> SVGSVGElement {
SVGSVGElement {
svggraphicselement:
SVGGraphicsElement::new_inherited(local_name, prefix, document)
}
}

#[allow(unrooted_must_root)]
pub fn new(local_name: Atom,
prefix: Option<DOMString>,
document: &Document) -> Root<SVGSVGElement> {
Node::reflect_node(box SVGSVGElement::new_inherited(local_name, prefix, document),
document,
SVGSVGElementBinding::Wrap)
}
}

pub trait LayoutSVGSVGElementHelpers {
fn data(&self) -> SVGSVGData;
}

impl LayoutSVGSVGElementHelpers for LayoutJS<SVGSVGElement> {
#[allow(unsafe_code)]
fn data(&self) -> SVGSVGData {
unsafe {
let SVG = &*self.unsafe_get();

let width_attr = SVG.upcast::<Element>().get_attr_for_layout(&ns!(), &atom!("width"));
let height_attr = SVG.upcast::<Element>().get_attr_for_layout(&ns!(), &atom!("height"));
SVGSVGData {
width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()),
height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()),
}
}
}
}

impl VirtualMethods for SVGSVGElement {
fn super_type(&self) -> Option<&VirtualMethods> {
Some(self.upcast::<SVGGraphicsElement>() as &VirtualMethods)
}

fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
}

fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
match name {
&atom!("width") => AttrValue::from_u32(value.into(), DEFAULT_WIDTH),
&atom!("height") => AttrValue::from_u32(value.into(), DEFAULT_HEIGHT),
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
}
}
}
8 changes: 8 additions & 0 deletions components/script/dom/virtualmethods.rs
Expand Up @@ -7,6 +7,8 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::inheritance::ElementTypeId;
use dom::bindings::inheritance::HTMLElementTypeId;
use dom::bindings::inheritance::NodeTypeId;
use dom::bindings::inheritance::SVGElementTypeId;
use dom::bindings::inheritance::SVGGraphicsElementTypeId;
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
Expand Down Expand Up @@ -47,6 +49,7 @@ use dom::htmltemplateelement::HTMLTemplateElement;
use dom::htmltextareaelement::HTMLTextAreaElement;
use dom::htmltitleelement::HTMLTitleElement;
use dom::node::{ChildrenMutation, CloneChildrenFlag, Node, UnbindContext};
use dom::svgsvgelement::SVGSVGElement;
use string_cache::Atom;
use style::attr::AttrValue;

Expand Down Expand Up @@ -231,6 +234,11 @@ pub fn vtable_for(node: &Node) -> &VirtualMethods {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement)) => {
node.downcast::<HTMLTitleElement>().unwrap() as &VirtualMethods
}
NodeTypeId::Element(ElementTypeId::SVGElement(SVGElementTypeId::SVGGraphicsElement(
SVGGraphicsElementTypeId::SVGSVGElement
))) => {
node.downcast::<SVGSVGElement>().unwrap() as &VirtualMethods
}
NodeTypeId::Element(ElementTypeId::Element) => {
node.downcast::<Element>().unwrap() as &VirtualMethods
}
Expand Down
22 changes: 22 additions & 0 deletions components/script/dom/webidls/SVGElement.webidl
@@ -0,0 +1,22 @@
/* 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/. */

// https://svgwg.org/svg2-draft/types.html#InterfaceSVGElement
[Pref="dom.svg.enabled"]
interface SVGElement : Element {

//[SameObject] readonly attribute SVGAnimatedString className;

//[SameObject] readonly attribute DOMStringMap dataset;

//readonly attribute SVGSVGElement? ownerSVGElement;
//readonly attribute SVGElement? viewportElement;

//attribute long tabIndex;
//void focus();
//void blur();
};

//SVGElement implements GlobalEventHandlers;
//SVGElement implements SVGElementInstance;

0 comments on commit 9876020

Please sign in to comment.