wip: xinclude fallback

parent 925e75d7
......@@ -162,74 +162,6 @@ rsvg_load_steal_tree (RsvgLoad *load)
return rsvg_xml_state_steal_tree (load->xml.rust_state);
}
/* start xinclude */
typedef struct _RsvgSaxHandlerXinclude {
RsvgSaxHandler super;
RsvgSaxHandler *prev_handler;
RsvgLoad *load;
gboolean success;
gboolean in_fallback;
} RsvgSaxHandlerXinclude;
static void start_xinclude (RsvgLoad *load, RsvgPropertyBag *atts);
static void
xinclude_handler_free (RsvgSaxHandler * self)
{
g_free (self);
}
static void
xinclude_handler_characters (RsvgSaxHandler * self, const char *ch, gsize len)
{
RsvgSaxHandlerXinclude *z = (RsvgSaxHandlerXinclude *) self;
if (z->in_fallback) {
rsvg_xml_state_characters (z->load->xml.rust_state, ch, len);
}
}
static void
xinclude_handler_start (RsvgSaxHandler * self, const char *name, RsvgPropertyBag atts)
{
RsvgSaxHandlerXinclude *z = (RsvgSaxHandlerXinclude *) self;
if (!z->success) {
if (z->in_fallback) {
if (!strcmp (name, "xi:include"))
start_xinclude (z->load, atts);
else {
rsvg_xml_state_start_element (z->load->xml.rust_state,
z->load->handle,
(const char *) name,
atts);
}
} else if (!strcmp (name, "xi:fallback")) {
z->in_fallback = TRUE;
}
}
}
static void
xinclude_handler_end (RsvgSaxHandler * self, const char *name)
{
RsvgSaxHandlerXinclude *z = (RsvgSaxHandlerXinclude *) self;
RsvgSaxHandler *previous = z->prev_handler;
RsvgLoad *load = z->load;
if (!strcmp (name, "include") || !strcmp (name, "xi:include")) {
if (load->xml.handler != NULL) {
load->xml.handler->free (load->xml.handler);
load->xml.handler = previous;
}
} else if (z->in_fallback) {
if (!strcmp (name, "xi:fallback"))
z->in_fallback = FALSE;
}
}
static void
set_xml_parse_options(xmlParserCtxtPtr xml_parser,
gboolean unlimited_size)
......@@ -346,6 +278,7 @@ create_xml_stream_parser (RsvgLoad *load,
return parser;
}
#if 0
/* http://www.w3.org/TR/xinclude/ */
static void
start_xinclude (RsvgLoad *load, RsvgPropertyBag * atts)
......@@ -440,8 +373,8 @@ start_xinclude (RsvgLoad *load, RsvgPropertyBag * atts)
/* needed to handle xi:fallback */
handler = g_new0 (RsvgSaxHandlerXinclude, 1);
handler->super.free = xinclude_handler_free;
handler->super.characters = xinclude_handler_characters;
handler->super.free = NULL;
handler->super.characters = NULL;
handler->super.start_element = xinclude_handler_start;
handler->super.end_element = xinclude_handler_end;
handler->prev_handler = load->xml.handler;
......@@ -450,6 +383,7 @@ start_xinclude (RsvgLoad *load, RsvgPropertyBag * atts)
load->xml.handler = &handler->super;
}
#endif
/* end xinclude */
......
......@@ -18,107 +18,7 @@ use structure::NodeSvg;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;
// struct XIncludeContext {
// needs_fallback: bool,
// }
//
// impl XmlHandler for XIncludeContext {
// fn start_element(
// &self,
// _previous_handler: Option<&XmlHandler>,
// _parent: Option<&Rc<Node>>,
// handle: *mut RsvgHandle,
// _name: &str,
// pbag: &PropertyBag,
// ) -> Box<XmlHandler> {
// let mut href = None;
// let mut parse = None;
// let mut encoding = None;
//
// for (_key, attr, value) in pbag.iter() {
// match attr {
// Attribute::Href => href = Some(value),
// Attribute::Parse => parse = Some(value),
// Attribute::Encoding => encoding = Some(value),
// _ => (),
// }
// }
//
// self.acquire(handle, href, parse, encoding);
//
// unimplemented!("finish start_xinclude() here");
//
// Box::new(XIncludeContext::empty())
// }
//
// fn end_element(&self, handle: *mut RsvgHandle, _name: &str) -> Option<Rc<Node>> {
// unimplemented!();
// }
//
// fn characters(&self, text: &str) {
// unimplemented!();
// }
// }
//
// impl XIncludeContext {
// fn empty() -> XIncludeContext {
// XIncludeContext {
// needs_fallback: true,
// }
// }
//
// fn acquire(
// &self,
// handle: *mut RsvgHandle,
// href: Option<&str>,
// parse: Option<&str>,
// encoding: Option<&str>,
// ) {
// if let Some(href) = href {
// if parse == Some("text") {
// self.acquire_text(handle, href, encoding);
// } else {
// unimplemented!("finish the xml case here");
// }
// }
// }
//
// fn acquire_text(&self, handle: *mut RsvgHandle, href: &str, encoding: Option<&str>) {
// let binary = match handle::acquire_data(handle, href) {
// Ok(b) => b,
// Err(e) => {
// rsvg_log!("could not acquire \"{}\": {}", href, e);
// return;
// }
// };
//
// let encoding = encoding.unwrap_or("utf-8");
//
// let encoder = match encoding_from_whatwg_label(encoding) {
// Some(enc) => enc,
// None => {
// rsvg_log!("unknown encoding \"{}\" for \"{}\"", encoding, href);
// return;
// }
// };
//
// let utf8_data = match encoder.decode(&binary.data, DecoderTrap::Strict) {
// Ok(data) => data,
//
// Err(e) => {
// rsvg_log!(
// "could not convert contents of \"{}\" from character encoding \"{}\": {}",
// href,
// encoding,
// e
// );
// return;
// }
// };
//
// unimplemented!("rsvg_xml_state_characters(utf8_data)");
// }
// }
enum ContextKind {
// Starting state
Start,
......@@ -133,7 +33,13 @@ enum ContextKind {
UnsupportedStyleChild,
// Inside <xi:include>
XInclude,
XInclude(XIncludeContext),
// An unsupported element inside a <xi:include> context, to be ignored
UnsupportedXIncludeChild,
// Insie <xi::fallback>
XIncludeFallback,
}
/// Handles the `<style>` element by parsing its character contents as CSS
......@@ -142,6 +48,10 @@ struct StyleContext {
text: String,
}
struct XIncludeContext {
needs_fallback: bool,
}
/// A concrete parsing context for a surrounding `element_name` and its XML event handlers
struct Context {
element_name: String,
......@@ -217,7 +127,11 @@ impl XmlState {
}
ContextKind::Style(_) => self.inside_style_start_element(name),
ContextKind::UnsupportedStyleChild => self.inside_style_start_element(name),
ContextKind::XInclude => self.xinclude_start_element(handle, name, pbag),
ContextKind::XInclude(ref ctx) => {
self.inside_xinclude_start_element(ctx, handle, name, pbag)
}
ContextKind::UnsupportedXIncludeChild => self.unsupported_xinclude_start_element(name),
ContextKind::XIncludeFallback => self.xinclude_fallback_start_element(ctx, handle, name, pbag),
};
self.push_context(new_ctx);
......@@ -244,7 +158,8 @@ impl XmlState {
}
ContextKind::Style(style_ctx) => self.style_end_element(style_ctx, handle),
ContextKind::UnsupportedStyleChild => (),
ContextKind::XInclude => self.xinclude_end_element(handle, name),
ContextKind::XInclude(_) => self.xinclude_end_element(handle, name),
ContextKind::UnsupportedXIncludeChild => (),
}
}
......@@ -256,7 +171,9 @@ impl XmlState {
}
ContextKind::Style(ref mut style_ctx) => style_characters(style_ctx, text),
ContextKind::UnsupportedStyleChild => (),
ContextKind::XInclude => self.xinclude_characters(text),
ContextKind::XInclude(ref ctx) => (),
ContextKind::UnsupportedXIncludeChild => (),
ContextKind::XIncludeFallback => self.xinclude_fallback_characters(ctx, text),
}
}
......@@ -268,7 +185,7 @@ impl XmlState {
pbag: &PropertyBag,
) -> Context {
match name {
"include" => unimplemented!(),
"include" => self.xinclude_start_element(handle, name, pbag),
"style" => self.style_start_element(name, pbag),
_ => {
let node = self.create_node(parent, handle, name, pbag);
......@@ -399,19 +316,129 @@ impl XmlState {
fn xinclude_start_element(
&mut self,
ctx: &XIncludeContext,
handle: *mut RsvgHandle,
name: &str,
pbag: &PropertyBag,
) -> Context {
unimplemented!();
let mut href = None;
let mut parse = None;
let mut encoding = None;
for (_key, attr, value) in pbag.iter() {
match attr {
Attribute::Href => href = Some(value),
Attribute::Parse => parse = Some(value),
Attribute::Encoding => encoding = Some(value),
_ => (),
}
}
let needs_fallback = self.acquire(handle, href, parse, encoding).is_ok();
Context {
element_name: name.to_string(),
kind: ContextKind::XInclude(XIncludeContext { needs_fallback }),
}
}
fn xinclude_end_element(&mut self, handle: *mut RsvgHandle, name: &str) {
unimplemented!();
}
fn xinclude_characters(&mut self, text: &str) {
unimplemented!();
fn inside_xinclude_start_element(
&self,
ctx: &XIncludeContext,
handle: *mut RsvgHandle,
name: &str,
pbag: &PropertyBag,
) -> Context {
if name == "xi:fallback" {
Context {
element_name: name.to_string(),
kind: ContextKind::XIncludeFallback,
}
}
}
fn xinclude_fallback_characters(&mut self, ctx: &XIncludeContext, text: &str) {
self.characters(text);
}
fn xinclude_fallback_start_element(
&self,
ctx: &XIncludeContext,
handle: *mut RsvgHandle,
name: &str,
pbag: &PropertyBag,
) -> Context {
if name == "xi:include" {
self.xinclude_start_element(handle, name, pbag)
} else {
let parent = parent.clone();
self.element_creation_start_element(Some(&parent), handle, name, pbag)
}
}
fn acquire(
&self,
handle: *mut RsvgHandle,
href: Option<&str>,
parse: Option<&str>,
encoding: Option<&str>,
) -> Result<(), ()> {
if let Some(href) = href {
if parse == Some("text") {
self.acquire_text(handle, href, encoding)
} else {
self.acquire_xml(handle, href)
}
}
}
fn acquire_text(
&mut self,
handle: *mut RsvgHandle,
href: &str,
encoding: Option<&str>,
) -> Result<(), ()> {
let binary = handle::acquire_data(handle, href).map_err(|e| {
rsvg_log!("could not acquire \"{}\": {}", href, e);
()
})?;
let encoding = encoding.unwrap_or("utf-8");
let encoder = encoding_from_whatwg_label(encoding)
.ok_or_else(|| {
rsvg_log!("unknown encoding \"{}\" for \"{}\"", encoding, href);
()
})?;
let utf8_data = encoder
.decode(&binary.data, DecoderTrap::Strict)
.map_err(|e| {
rsvg_log!(
"could not convert contents of \"{}\" from character encoding \"{}\": {}",
href,
encoding,
e
);
()
})?;
self.characters(utf8_data);
Ok(())
}
fn acquire_xml(&self, handle: *mut RsvgHandle, href: &str) -> Result<(), ()> {
unimplemented!()
}
fn unsupported_xinclude_start_element(&self, name: &str) -> Context {
Context {
element_name: name.to_string(),
kind: ContextKind::UnsupportedXIncludeChild,
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment