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

Support SVG element #13589

Merged
merged 4 commits into from Oct 7, 2016
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

add SVGElement, SVGGraphicsElement interfaces and SVGSVGElement element

  • Loading branch information
splav committed Oct 6, 2016
commit 9876020c2258ef833044596944ab0aa5370b0a74
@@ -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)
})
);

This comment has been minimized.

Copy link
@wafflespeanut

wafflespeanut Oct 5, 2016

Member

Instead of duplicating the macro, it could be moved outside the function :)

This comment has been minimized.

Copy link
@splav

splav Oct 5, 2016

Author Contributor

Actually it's not so obvious. If I move macro out of scope I'll lose name.local, prefix, document local vars and should make them arguments. That makes macro mostly useless.

This comment has been minimized.

Copy link
@Ms2ger

Ms2ger Oct 6, 2016

Contributor

Alright, let's keep it duplicated for now.


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);
@@ -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)
}
}
@@ -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;
@@ -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;
@@ -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};
@@ -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;
@@ -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;
@@ -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;
}
@@ -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!");
@@ -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,
}
}
@@ -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)
}
}
@@ -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)
}
}
@@ -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),
}
}
}
@@ -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};
@@ -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;

@@ -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
}
@@ -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;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.