Commit 7ae21249 authored by Paolo Borelli's avatar Paolo Borelli

defs: port RsvgDefs to rust

parent bfa87218
......@@ -29,8 +29,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg/rsvg-base.c \
librsvg/rsvg-cairo.h \
librsvg/rsvg-css.h \
librsvg/rsvg-defs.c \
librsvg/rsvg-defs.h \
librsvg/rsvg-file-util.c \
librsvg/rsvg-handle.c \
librsvg/rsvg-io.c \
......
......@@ -74,7 +74,6 @@ IGNORE_HFILES = \
rsvg-cairo-clip.h \
rsvg-compat.h \
rsvg-css.h \
rsvg-defs.h \
rsvg-filter.h \
rsvg-io.h \
rsvg-marker.h \
......
......@@ -29,7 +29,6 @@
#include "rsvg-private.h"
#include "rsvg-css.h"
#include "rsvg-defs.h"
#include "rsvg-styles.h"
#include "rsvg-io.h"
#include "rsvg-load.h"
......
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
/*
rsvg-defs.c: Manage SVG defs and references.
Copyright (C) 2000 Eazel, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Raph Levien <raph@artofcode.com>
*/
#include "config.h"
#include "rsvg-private.h"
#include "rsvg-defs.h"
#include "rsvg-styles.h"
#include "rsvg-io.h"
#include <glib.h>
struct _RsvgDefs {
GHashTable *hash;
GHashTable *externs;
RsvgHandle *handle;
};
RsvgDefs *
rsvg_defs_new (RsvgHandle *handle)
{
RsvgDefs *result = g_new0 (RsvgDefs, 1);
result->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) rsvg_node_unref);
result->externs =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
result->handle = handle; /* no need to take a ref here */
return result;
}
static RsvgNode *
rsvg_defs_extern_lookup (const RsvgDefs * defs, const char *possibly_relative_uri, const char *name)
{
RsvgHandle *handle;
char *uri;
uri = rsvg_handle_resolve_uri (defs->handle, possibly_relative_uri);
if (!uri)
return NULL;
handle = (RsvgHandle *) g_hash_table_lookup (defs->externs, uri);
if (handle == NULL) {
handle = rsvg_handle_load_extern (defs->handle, uri);
if (handle != NULL) {
g_hash_table_insert (defs->externs, g_strdup (uri), handle);
}
}
if (handle != NULL) {
RsvgDefs *ext_defs = rsvg_handle_get_defs (handle);
return g_hash_table_lookup (ext_defs->hash, name);
}
return NULL;
}
RsvgNode *
rsvg_defs_lookup (const RsvgDefs * defs, const char *name)
{
char *hashpos;
hashpos = g_strrstr (name, "#");
if (!hashpos) {
return NULL;
}
if (hashpos == name) {
return g_hash_table_lookup (defs->hash, name + 1);
} else {
gchar **splitbits;
RsvgNode *toreturn;
splitbits = g_strsplit (name, "#", 2);
toreturn = rsvg_defs_extern_lookup (defs, splitbits[0], splitbits[1]);
g_strfreev (splitbits);
return toreturn;
}
}
void
rsvg_defs_register_node_by_id (RsvgDefs *defs, const char *id, RsvgNode *node)
{
g_assert (defs != NULL);
g_assert (id != NULL);
g_assert (node != NULL);
if (g_hash_table_lookup (defs->hash, id))
return;
g_hash_table_insert (defs->hash, g_strdup (id), rsvg_node_ref (node));
}
void
rsvg_defs_free (RsvgDefs * defs)
{
g_hash_table_destroy (defs->hash);
defs->hash = NULL;
g_hash_table_destroy (defs->externs);
defs->externs = NULL;
g_free (defs);
}
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
/*
rsvg-defs.h : SVG defs utilities
Copyright (C) 2000 Eazel, Inc.
Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Author: Raph Levien <raph@artofcode.com>
*/
#ifndef RSVG_DEFS_H
#define RSVG_DEFS_H
/* A module for handling SVG defs */
#include <glib.h>
#include "rsvg.h"
#include "rsvg-private.h"
G_BEGIN_DECLS
G_GNUC_INTERNAL
RsvgDefs *rsvg_defs_new (RsvgHandle *handle);
/* for some reason this one's public... */
RsvgNode *rsvg_defs_lookup (const RsvgDefs * defs, const char *name);
G_GNUC_INTERNAL
void rsvg_defs_free (RsvgDefs * defs);
G_GNUC_INTERNAL
void rsvg_defs_register_node_by_id (RsvgDefs *defs, const char *id, RsvgNode *node);
G_END_DECLS
#endif
......@@ -121,7 +121,6 @@
#include <string.h>
#include "rsvg-private.h"
#include "rsvg-defs.h"
enum {
PROP_0,
......
......@@ -27,7 +27,6 @@
#include <string.h>
#include "rsvg-attributes.h"
#include "rsvg-defs.h"
#include "rsvg-load.h"
#include "rsvg-styles.h"
......
......@@ -394,6 +394,18 @@ void rsvg_return_if_fail_warning (const char *pretty_function,
G_GNUC_INTERNAL
RsvgNode *rsvg_load_destroy (RsvgLoad *load) G_GNUC_WARN_UNUSED_RESULT;
/* Defined in rsvg_internals/src/defs.rs */
G_GNUC_INTERNAL
RsvgDefs *rsvg_defs_new (RsvgHandle *handle);
/* Defined in rsvg_internals/src/defs.rs */
G_GNUC_INTERNAL
void rsvg_defs_free (RsvgDefs *defs);
/* Defined in rsvg_internals/src/defs.rs */
/* for some reason this one's public... */
RsvgNode *rsvg_defs_lookup (const RsvgDefs * defs, const char *name);
G_GNUC_INTERNAL
RsvgDefs *rsvg_handle_get_defs (RsvgHandle *handle);
......
use glib::translate::*;
use libc;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::ptr;
use std::rc::Rc;
use node::RsvgNode;
use handle::{self, RsvgHandle};
use node::{Node, RsvgNode};
use util::utf8_cstr;
pub enum RsvgDefs {}
#[allow(improper_ctypes)]
extern "C" {
fn rsvg_defs_register_node_by_id(
defs: *mut RsvgDefs,
id: *const libc::c_char,
node: *const RsvgNode,
);
fn rsvg_defs_lookup(defs: *const RsvgDefs, name: *const libc::c_char) -> *mut RsvgNode;
pub struct Defs {
handle: *const RsvgHandle,
nodes: HashMap<String, Rc<Node>>,
externs: HashMap<String, *const RsvgHandle>,
}
pub fn register_node_by_id(defs: *mut RsvgDefs, id: &str, node: &RsvgNode) {
unsafe {
rsvg_defs_register_node_by_id(defs, id.to_glib_none().0, node);
impl Defs {
fn new(handle: *const RsvgHandle) -> Defs {
Defs {
handle,
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(&mut self, name: &str) -> Option<&Rc<Node>> {
match name.rfind('#') {
None => None,
Some(p) if p == 0 => self.nodes.get(&name[1..]),
Some(p) => {
let handle = self.get_extern_handle(&name[..p]);
if handle.is_null() {
None
} else {
handle::get_defs(handle).nodes.get(&name[(p + 1)..])
}
}
}
}
fn get_extern_handle(&mut self, possibly_relative_uri: &str) -> *const RsvgHandle {
handle::resolve_uri(self.handle, possibly_relative_uri).map_or(
ptr::null(),
|uri| match self.externs.entry(uri) {
Entry::Occupied(e) => *(e.get()),
Entry::Vacant(e) => {
let handle = handle::load_extern(self.handle, e.key());
if !handle.is_null() {
e.insert(handle);
}
handle
}
},
)
}
}
pub fn lookup(defs: *const RsvgDefs, name: &str) -> Option<&mut RsvgNode> {
#[no_mangle]
pub extern "C" fn rsvg_defs_new(handle: *const RsvgHandle) -> *mut RsvgDefs {
Box::into_raw(Box::new(Defs::new(handle))) as *mut RsvgDefs
}
#[no_mangle]
pub extern "C" fn rsvg_defs_free(defs: *mut RsvgDefs) {
assert!(!defs.is_null());
unsafe {
let node = rsvg_defs_lookup(defs, name.to_glib_none().0);
if node.is_null() {
None
} else {
Some(&mut *node)
}
let defs = { &mut *(defs as *mut Defs) };
Box::from_raw(defs);
}
}
#[no_mangle]
pub extern "C" fn rsvg_defs_lookup(
defs: *mut RsvgDefs,
name: *const libc::c_char,
) -> *const RsvgNode {
assert!(!defs.is_null());
assert!(!name.is_null());
let defs = unsafe { &mut *(defs as *mut Defs) };
let name = unsafe { utf8_cstr(name) };
match defs.lookup(name) {
Some(n) => n as *const RsvgNode,
None => ptr::null(),
}
}
......@@ -14,7 +14,7 @@ use std::rc::Rc;
use bbox::BoundingBox;
use clip_path::{ClipPathUnits, NodeClipPath};
use coord_units::CoordUnits;
use defs::{self, RsvgDefs};
use defs::{Defs, RsvgDefs};
use filters;
use float_eq_cairo::ApproxEqCairo;
use length::Dasharray;
......@@ -195,7 +195,9 @@ impl<'a> 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, url: &str) -> Option<AcquiredNode> {
if let Some(node) = defs::lookup(self.defs, url) {
let defs = unsafe { &mut *(self.defs as *mut Defs) };
if let Some(node) = defs.lookup(url) {
if !self.acquired_nodes_contains(node) {
self.acquired_nodes.borrow_mut().push(node.clone());
return Some(AcquiredNode(&self.acquired_nodes as *const _, node.clone()));
......@@ -976,6 +978,8 @@ pub extern "C" fn rsvg_drawing_ctx_new(
defs: *const RsvgDefs,
is_testing: glib_sys::gboolean,
) -> *mut RsvgDrawingCtx {
assert!(!defs.is_null());
Box::into_raw(Box::new(DrawingCtx::new(
unsafe { from_glib_none(cr) },
f64::from(width),
......
use glib::translate::*;
use libc;
use defs::{Defs, RsvgDefs};
pub enum RsvgHandle {}
#[allow(improper_ctypes)]
extern "C" {
fn rsvg_handle_get_defs(handle: *const RsvgHandle) -> *const RsvgDefs;
fn rsvg_handle_resolve_uri(
handle: *const RsvgHandle,
uri: *const libc::c_char,
) -> *const libc::c_char;
fn rsvg_handle_load_extern(
handle: *const RsvgHandle,
uri: *const libc::c_char,
) -> *const RsvgHandle;
}
pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a Defs {
unsafe {
let d = rsvg_handle_get_defs(handle);
&*(d as *const Defs)
}
}
pub fn resolve_uri(handle: *const RsvgHandle, uri: &str) -> Option<String> {
unsafe {
let resolved = rsvg_handle_resolve_uri(handle, uri.to_glib_none().0);
if resolved.is_null() {
None
} else {
Some(from_glib_full(resolved))
}
}
}
pub fn load_extern(handle: *const RsvgHandle, uri: &str) -> *const RsvgHandle {
unsafe { rsvg_handle_load_extern(handle, uri.to_glib_none().0) }
}
......@@ -28,6 +28,8 @@ pub use attributes::rsvg_attribute_from_name;
pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
pub use defs::{rsvg_defs_free, rsvg_defs_lookup, rsvg_defs_new};
pub use drawing_ctx::{
rsvg_drawing_ctx_add_node_and_ancestors_to_stack,
rsvg_drawing_ctx_draw_node_from_stack,
......
......@@ -12,7 +12,7 @@ use std::str::FromStr;
use attributes::Attribute;
use cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
use defs::{self, RsvgDefs};
use defs::{Defs, RsvgDefs};
use drawing_ctx::DrawingCtx;
use error::*;
use handle::RsvgHandle;
......@@ -283,9 +283,9 @@ impl Node {
self.class.as_ref().map(String::as_str)
}
pub fn register(&self, node: &RsvgNode, defs: *mut RsvgDefs) {
pub fn register(&self, node: &RsvgNode, defs: &mut Defs) {
if let Some(ref id) = self.id {
defs::register_node_by_id(defs, id, node);
defs.insert(id, node);
}
}
......@@ -692,6 +692,7 @@ pub extern "C" fn rsvg_node_register_in_defs(raw_node: *const RsvgNode, defs: *m
assert!(!defs.is_null());
let node: &RsvgNode = unsafe { &*raw_node };
let defs = unsafe { &mut *(defs as *mut Defs) };
node.register(node, defs);
}
......
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