Commit a545fd77 authored by Federico Mena Quintero's avatar Federico Mena Quintero

Merge branch 'split-defs'

parents 07217cf3 716e0547
Pipeline #50011 passed with stages
in 25 minutes and 20 seconds
......@@ -110,6 +110,12 @@ impl AllowedUrl {
}
}
impl fmt::Display for AllowedUrl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl error::Error for AllowedUrlError {
fn description(&self) -> &str {
match *self {
......
......@@ -6,7 +6,6 @@ use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::ParseValue;
use property_bag::PropertyBag;
......@@ -79,7 +78,7 @@ impl NodeClipPath {
}
impl NodeTrait for NodeClipPath {
fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag<'_>) -> NodeResult {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
Attribute::ClipPathUnits => self.units.set(attr.parse(value, ())?),
......
......@@ -2,7 +2,6 @@ use std::collections::HashMap;
use attributes::Attribute;
use clip_path::NodeClipPath;
use defs::Defs;
use filters::{
blend::Blend,
color_matrix::ColorMatrix,
......@@ -271,7 +270,7 @@ pub fn create_node_and_register_id(
name: &str,
parent: Option<&RsvgNode>,
pbag: &PropertyBag,
defs: &mut Defs,
ids: &mut HashMap<String, RsvgNode>,
) -> RsvgNode {
let mut id = None;
let mut class = None;
......@@ -298,8 +297,9 @@ pub fn create_node_and_register_id(
let node = create_fn(id, class, parent);
if id.is_some() {
defs.insert(id.unwrap(), &node);
if let Some(id) = id {
// This is so we don't overwrite an existing id
ids.entry(id.to_string()).or_insert(node.clone());
}
node
......
......@@ -4,13 +4,15 @@ use std::ptr;
use std::str::{self, FromStr};
use libc;
use url::Url;
use glib::translate::*;
use glib_sys::{gboolean, gpointer, GList};
use allowed_url::AllowedUrl;
use attributes::Attribute;
use croco::*;
use handle::{self, RsvgHandle};
use handle;
use state::State;
use util::utf8_cstr;
......@@ -79,7 +81,7 @@ impl CssStyles {
}
struct DocHandlerData<'a> {
handle: *mut RsvgHandle,
base_url: Option<Url>,
css_styles: &'a mut CssStyles,
selector: *mut CRSelector,
}
......@@ -90,14 +92,14 @@ macro_rules! get_doc_handler_data {
};
}
pub fn parse_into_css_styles(css_styles: &mut CssStyles, handle: *mut RsvgHandle, buf: &str) {
pub fn parse_into_css_styles(css_styles: &mut CssStyles, base_url: Option<Url>, buf: &str) {
if buf.len() == 0 {
return; // libcroco doesn't like empty strings :(
}
unsafe {
let mut handler_data = DocHandlerData {
handle,
base_url,
css_styles,
selector: ptr::null_mut(),
};
......@@ -151,7 +153,12 @@ unsafe extern "C" fn css_import_style(
let raw_uri = cr_string_peek_raw_str(a_uri);
let uri = utf8_cstr(raw_uri);
handle::load_css(handler_data.css_styles, handler_data.handle, uri);
if let Ok(aurl) = AllowedUrl::from_href(uri, handler_data.base_url.as_ref()) {
// FIXME: handle CSS errors
let _ = handle::load_css(handler_data.css_styles, &aurl);
} else {
rsvg_log!("disallowed URL \"{}\" for importing CSS", uri);
}
}
unsafe extern "C" fn css_start_selector(
......
......@@ -5,61 +5,45 @@ use std::rc::Rc;
use allowed_url::AllowedUrl;
use error::ValueErrorKind;
use handle::{self, RsvgHandle};
use handle::{self, LoadOptions, RsvgHandle};
use node::Node;
use parsers::ParseError;
pub struct Defs {
nodes: HashMap<String, Rc<Node>>,
externs: HashMap<AllowedUrl, *const RsvgHandle>,
}
impl Defs {
pub fn new() -> Defs {
Defs {
nodes: Default::default(),
externs: Default::default(),
}
}
pub fn insert(&mut self, id: &str, node: &Rc<Node>) {
self.nodes.entry(id.to_string()).or_insert(node.clone());
}
pub fn lookup_fragment_id(&self, id: &str) -> Option<Rc<Node>> {
self.nodes.get(id).map(|n| (*n).clone())
}
/// Returns a node referenced by a fragment ID
///
/// If the `Fragment`'s URL is `None`, then the fragment ID refers
/// to the RSVG handle in question. Otherwise, it will refer to
/// an externally-loaded SVG file that is referenced by the
/// current one. If the element's id is not found, returns
/// `None`.
pub fn lookup(&mut self, handle: *const RsvgHandle, fragment: &Fragment) -> Option<Rc<Node>> {
/// Returns a node referenced by a fragment ID, from an
/// externally-loaded SVG file.
pub fn lookup(&mut self, load_options: &LoadOptions, fragment: &Fragment) -> Option<Rc<Node>> {
if let Some(ref href) = fragment.uri() {
match self.get_extern_handle(handle, href) {
Ok(extern_handle) => handle::lookup_fragment_id(extern_handle, fragment),
match self.get_extern_handle(load_options, href) {
Ok(extern_handle) => handle::lookup_fragment_id(extern_handle, fragment.fragment()),
Err(()) => None,
}
} else {
self.lookup_fragment_id(fragment.fragment())
unreachable!();
}
}
fn get_extern_handle(
&mut self,
handle: *const RsvgHandle,
load_options: &LoadOptions,
href: &str,
) -> Result<*const RsvgHandle, ()> {
let aurl =
AllowedUrl::from_href(href, handle::get_base_url(handle).as_ref()).map_err(|_| ())?;
let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref()).map_err(|_| ())?;
match self.externs.entry(aurl) {
Entry::Occupied(e) => Ok(*(e.get())),
Entry::Vacant(e) => {
let extern_handle = handle::load_extern(handle, e.key())?;
let extern_handle = handle::load_extern(load_options, e.key())?;
e.insert(extern_handle);
Ok(extern_handle)
}
......
......@@ -13,7 +13,6 @@ use dpi::Dpi;
use error::RenderingError;
use filters;
use gradient::NodeGradient;
use handle::{self, RsvgHandle};
use length::Dasharray;
use mask::NodeMask;
use node::{CascadedValues, NodeType, RsvgNode};
......@@ -31,6 +30,7 @@ use state::{
StrokeLinecap,
StrokeLinejoin,
};
use svg::Svg;
use unit_interval::UnitInterval;
use viewbox::ViewBox;
......@@ -92,7 +92,7 @@ impl Drop for ViewParams {
}
pub struct DrawingCtx {
handle: *const RsvgHandle,
svg: Rc<Svg>,
rect: cairo::Rectangle,
dpi: Dpi,
......@@ -123,17 +123,20 @@ pub struct DrawingCtx {
drawsub_stack: Vec<RsvgNode>,
acquired_nodes: Rc<RefCell<Vec<RsvgNode>>>,
testing: bool,
}
impl DrawingCtx {
pub fn new(
handle: *const RsvgHandle,
svg: Rc<Svg>,
cr: &cairo::Context,
width: f64,
height: f64,
vb_width: f64,
vb_height: f64,
dpi: Dpi,
testing: bool,
) -> DrawingCtx {
let mut affine = cr.get_matrix();
let rect = cairo::Rectangle {
......@@ -160,7 +163,7 @@ impl DrawingCtx {
view_box_stack.push(ViewBox::new(0.0, 0.0, vb_width, vb_height));
DrawingCtx {
handle,
svg: svg.clone(),
rect,
dpi,
num_elements_rendered_through_use: 0,
......@@ -173,11 +176,12 @@ impl DrawingCtx {
bbox_stack: Vec::new(),
drawsub_stack: Vec::new(),
acquired_nodes: Rc::new(RefCell::new(Vec::new())),
testing,
}
}
pub fn is_testing(&self) -> bool {
handle::is_testing(self.handle)
self.testing
}
pub fn get_cairo_context(&self) -> cairo::Context {
......@@ -259,7 +263,7 @@ impl DrawingCtx {
// acquire it again. If you acquire a node "#foo" and don't release it before
// trying to acquire "foo" again, you will obtain a %NULL the second time.
pub fn get_acquired_node(&mut self, fragment: &Fragment) -> Option<AcquiredNode> {
if let Some(node) = handle::lookup_node(self.handle, fragment) {
if let Some(node) = self.svg.lookup(fragment) {
if !self.acquired_nodes_contains(&node) {
self.acquired_nodes.borrow_mut().push(node.clone());
let acq = AcquiredNode(self.acquired_nodes.clone(), node.clone());
......
......@@ -155,6 +155,7 @@ pub enum LoadingError {
CouldNotCreateXmlParser,
BadUrl,
BadDataUrl,
BadCss,
Cairo(cairo::Status),
EmptyData,
SvgHasNoElements,
......@@ -171,6 +172,7 @@ impl error::Error for LoadingError {
LoadingError::XmlParseError(_) => "XML parse error",
LoadingError::BadUrl => "invalid URL",
LoadingError::BadDataUrl => "invalid data: URL",
LoadingError::BadCss => "invalid CSS",
LoadingError::Cairo(_) => "cairo error",
LoadingError::EmptyData => "empty data",
LoadingError::SvgHasNoElements => "SVG has no elements",
......@@ -190,6 +192,7 @@ impl fmt::Display for LoadingError {
| LoadingError::CouldNotCreateXmlParser
| LoadingError::BadUrl
| LoadingError::BadDataUrl
| LoadingError::BadCss
| LoadingError::EmptyData
| LoadingError::SvgHasNoElements
| LoadingError::RootElementIsNotSvg
......
......@@ -5,7 +5,6 @@ use cairo;
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::ParseError;
use property_bag::PropertyBag;
......@@ -45,13 +44,8 @@ impl Blend {
}
impl NodeTrait for Blend {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -6,7 +6,6 @@ use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{self, ListLength, NumberListError, ParseError};
use property_bag::PropertyBag;
......@@ -48,13 +47,8 @@ impl ColorMatrix {
}
impl NodeTrait for ColorMatrix {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
// First, determine the operation type.
let mut operation_type = OperationType::Matrix;
......
......@@ -6,7 +6,6 @@ use cairo::{self, ImageSurface};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers::{self, ListLength, NumberListError, ParseError};
use property_bag::PropertyBag;
......@@ -203,24 +202,14 @@ impl FuncX {
impl NodeTrait for ComponentTransfer {
#[inline]
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)
}
}
impl NodeTrait for FuncX {
#[inline]
fn set_atts(
&self,
_node: &RsvgNode,
_handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
fn set_atts(&self, _node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
Attribute::Type => self.function_type.set(FunctionType::parse(attr, value)?),
......
......@@ -6,7 +6,6 @@ use cssparser::{CowRcStr, Parser, Token};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::{NodeError, ValueErrorKind};
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{self, Parse, ParseValue};
use property_bag::PropertyBag;
......@@ -62,13 +61,8 @@ impl Composite {
}
impl NodeTrait for Composite {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -6,7 +6,6 @@ use nalgebra::{DMatrix, Dynamic, MatrixVec};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{self, ListLength, NumberListError, ParseError};
use property_bag::PropertyBag;
......@@ -57,13 +56,8 @@ impl ConvolveMatrix {
}
impl NodeTrait for ConvolveMatrix {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -5,7 +5,6 @@ use cairo::{self, ImageSurface, MatrixTrait};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{self, ParseError};
use property_bag::PropertyBag;
......@@ -47,13 +46,8 @@ impl DisplacementMap {
}
impl NodeTrait for DisplacementMap {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -2,7 +2,6 @@ use cairo::{self, ImageSurface};
use cssparser;
use drawing_ctx::DrawingCtx;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use property_bag::PropertyBag;
use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
......@@ -27,13 +26,8 @@ impl Flood {
impl NodeTrait for Flood {
#[inline]
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)
}
}
......
......@@ -8,7 +8,6 @@ use nalgebra::{DMatrix, Dynamic, MatrixVec};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers;
use property_bag::PropertyBag;
......@@ -44,13 +43,8 @@ impl GaussianBlur {
}
impl NodeTrait for GaussianBlur {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
use std::cell::{Cell, RefCell};
use std::ptr;
use cairo::{self, ImageSurface, MatrixTrait, PatternTrait};
......@@ -8,7 +7,7 @@ use attributes::Attribute;
use defs::{Fragment, Href};
use drawing_ctx::DrawingCtx;
use error::{NodeError, RenderingError};
use handle::{self, RsvgHandle};
use handle::{self, LoadOptions};
use node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
use parsers::{ParseError, ParseValue};
use property_bag::PropertyBag;
......@@ -24,10 +23,7 @@ pub struct Image {
base: Primitive,
aspect: Cell<AspectRatio>,
href: RefCell<Option<Href>>,
// Storing this here seems hack-ish... It's required by rsvg_cairo_surface_new_from_href(). The
// <image> element calls it in set_atts() but I don't think it belongs there.
handle: Cell<*const RsvgHandle>,
load_options: RefCell<Option<LoadOptions>>,
}
impl Image {
......@@ -38,8 +34,7 @@ impl Image {
base: Primitive::new::<Self>(),
aspect: Cell::new(AspectRatio::default()),
href: RefCell::new(None),
handle: Cell::new(ptr::null()),
load_options: RefCell::new(None),
}
}
......@@ -130,8 +125,10 @@ impl Image {
unreachable!();
};
let load_options_ref = self.load_options.borrow();
// FIXME: translate the error better here
let surface = handle::load_image_to_surface(self.handle.get() as *mut _, &url)
let surface = handle::load_image_to_surface(load_options_ref.as_ref().unwrap(), &url)
.map_err(|_| FilterError::InvalidInput)?;
let output_surface = ImageSurface::create(
......@@ -183,13 +180,8 @@ impl Image {
}
impl NodeTrait for Image {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......@@ -202,7 +194,11 @@ impl NodeTrait for Image {
}
}
self.handle.set(handle);
Ok(())
}
fn resolve_resources(&self, load_options: &LoadOptions) -> NodeResult {
*self.load_options.borrow_mut() = Some(load_options.clone());
Ok(())
}
......
......@@ -7,7 +7,6 @@ use nalgebra::Vector3;
use attributes::Attribute;
use error::NodeError;
use filters::context::FilterContext;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers;
use property_bag::PropertyBag;
......@@ -201,12 +200,7 @@ impl TransformedLightSource {
}
impl NodeTrait for LightSource {
fn set_atts(
&self,
_node: &RsvgNode,
_handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
fn set_atts(&self, _node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match self {
LightSource::Distant {
......
......@@ -29,7 +29,6 @@ use filters::{
FilterError,
PrimitiveWithInput,
};
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers;
use property_bag::PropertyBag;
......@@ -98,13 +97,8 @@ impl Lighting {
}
impl NodeTrait for Lighting {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -4,7 +4,6 @@ use cairo::{self, ImageSurface};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use property_bag::PropertyBag;
use rect::IRect;
......@@ -46,24 +45,14 @@ impl MergeNode {
impl NodeTrait for Merge {
#[inline]
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)
}
}
impl NodeTrait for MergeNode {
#[inline]
fn set_atts(
&self,
_node: &RsvgNode,
_handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
fn set_atts(&self, _node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
Attribute::In => {
......
......@@ -9,7 +9,6 @@ use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::{RenderingError, ValueErrorKind};
use handle::RsvgHandle;
use length::{Length, LengthDir, LengthUnit};
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers::{ParseError, ParseValue};
......@@ -111,12 +110,7 @@ impl Primitive {
}
impl NodeTrait for Primitive {
fn set_atts(
&self,
node: &RsvgNode,
_: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
// With ObjectBoundingBox, only fractions and percents are allowed.
let primitiveunits = node
.get_parent()
......@@ -198,13 +192,8 @@ impl PrimitiveWithInput {
}
impl NodeTrait for PrimitiveWithInput {
fn set_atts(
&self,
node: &RsvgNode,
handle: *const RsvgHandle,
pbag: &PropertyBag<'_>,
) -> NodeResult {
self.base.set_atts(node, handle, pbag)?;
fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
self.base.set_atts(node, pbag)?;
for (attr, value) in pbag.iter() {
match attr {
......
......@@ -6,7 +6,6 @@ use cairo::{self, ImageSurface, MatrixTrait};
use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{self, ParseError};
use property_bag::PropertyBag;
......@@ -49,13 +48,8 @@ impl Morphology {
}
impl NodeTrait for Morphology {
fn set_atts(
&self,
node: &RsvgNode,