summaryrefslogtreecommitdiff
path: root/capi
diff options
context:
space:
mode:
authorReizner Evgeniy <razrfalcon@gmail.com>2018-04-23 15:49:21 +0300
committerReizner Evgeniy <razrfalcon@gmail.com>2018-04-23 15:49:21 +0300
commitf78f5601e69d298106b147ccf48d95c3dc24647f (patch)
tree3b8cf4aae02f4dda8a76bdd9a8ad8e6675ce5dc6 /capi
parent2a05593f7feb4a63993b49be1c5b9cbbcaa69afe (diff)
C-API updated.
Diffstat (limited to 'capi')
-rw-r--r--capi/.gitignore1
-rw-r--r--capi/include/Doxyfile5
-rw-r--r--capi/include/resvg.h282
-rw-r--r--capi/src/lib.rs100
4 files changed, 324 insertions, 64 deletions
diff --git a/capi/.gitignore b/capi/.gitignore
new file mode 100644
index 0000000..eacffab
--- /dev/null
+++ b/capi/.gitignore
@@ -0,0 +1 @@
+/include/html
diff --git a/capi/include/Doxyfile b/capi/include/Doxyfile
new file mode 100644
index 0000000..d143338
--- /dev/null
+++ b/capi/include/Doxyfile
@@ -0,0 +1,5 @@
+PROJECT_NAME = "resvg C-API"
+OPTIMIZE_OUTPUT_FOR_C = YES
+QUIET = YES
+GENERATE_LATEX = NO
+ENABLE_PREPROCESSING = NO
diff --git a/capi/include/resvg.h b/capi/include/resvg.h
index b301db9..55eb2f8 100644
--- a/capi/include/resvg.h
+++ b/capi/include/resvg.h
@@ -1,74 +1,155 @@
-/* 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/. */
+/*
+ * 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/.
+ */
+
+/**
+ * @file resvg.h
+ *
+ * resvg C-API
+ */
#ifndef RESVG_H
#define RESVG_H
#include <stdbool.h>
+#include <stdint.h>
#ifdef RESVG_CAIRO_BACKEND
#include <cairo.h>
#endif
+/**
+ * @brief An opaque pointer to the global library handle.
+ *
+ * Must be invoked before any other \b resvg code.
+ *
+ * Currently, handles \b QGuiApplication object which must be created
+ * in order to draw text. If you don't plan to draw text - it's better to skip
+ * the initialization.
+ *
+ * If you are using this library from an existing Qt application you can skip it.
+ *
+ * Does nothing when only \b cairo backend is enabled/used.
+ *
+ * \b Note: \b QGuiApplication initialization is pretty slow (up to 100ms).
+ */
typedef struct resvg_handle resvg_handle;
+
+/**
+ * @brief An opaque pointer to the rendering tree.
+ */
typedef struct resvg_render_tree resvg_render_tree;
+/**
+ * @brief An RGB color representation.
+ */
typedef struct resvg_color {
- unsigned char r;
- unsigned char g;
- unsigned char b;
+ uint8_t r; /**< Red component. */
+ uint8_t g; /**< Green component. */
+ uint8_t b; /**< Blue component. */
} resvg_color;
+/**
+ * @brief A "fit to" type.
+ *
+ * All types produce proportional scaling.
+ */
typedef enum resvg_fit_to_type {
- RESVG_FIT_TO_ORIGINAL,
- RESVG_FIT_TO_WIDTH,
- RESVG_FIT_TO_HEIGHT,
- RESVG_FIT_TO_ZOOM,
+ RESVG_FIT_TO_ORIGINAL, /**< Use an original image size. */
+ RESVG_FIT_TO_WIDTH, /**< Fit an image to a specified width. */
+ RESVG_FIT_TO_HEIGHT, /**< Fit an image to a specified height. */
+ RESVG_FIT_TO_ZOOM, /**< Zoom an image using scaling factor */
} resvg_fit_to_type;
+/**
+ * @brief A "fit to" property.
+ */
typedef struct resvg_fit_to {
- resvg_fit_to_type type;
- float value;
+ resvg_fit_to_type type; /**< Fit type. */
+ float value; /**< Fit to value. Must be > 0. */
} resvg_fit_to;
+/**
+ * @brief Rendering options.
+ */
typedef struct resvg_options {
+ /// SVG image path. Used to resolve relative image paths.
const char *path;
+ /// Output DPI. Default: 96.
double dpi;
+ /// Fits the image using specified options.
+ /// Default: \b RESVG_FIT_TO_ORIGINAL.
resvg_fit_to fit_to;
+ /// Draw background. Default: false.
bool draw_background;
+ /// Background color.
resvg_color background;
+ /// Keep named groups. If set to \b true, all non-empty
+ /// groups with \b id attribute will not be removed.
bool keep_named_groups;
} resvg_options;
+/**
+ * @brief A rectangle representation.
+ */
typedef struct resvg_rect {
- double x;
- double y;
- double width;
- double height;
+ double x; /**< X position. */
+ double y; /**< Y position. */
+ double width; /**< Width. */
+ double height; /**< Height. */
} resvg_rect;
+/**
+ * @brief A size representation.
+ */
typedef struct resvg_size {
- unsigned int width;
- unsigned int height;
+ uint32_t width; /**< Width. */
+ uint32_t height; /**< Height. */
} resvg_size;
+/**
+ * @brief A 2D transform representation.
+ */
typedef struct resvg_transform {
- double a;
- double b;
- double c;
- double d;
- double e;
- double f;
+ double a; /**< \b a value */
+ double b; /**< \b b value */
+ double c; /**< \b c value */
+ double d; /**< \b d value */
+ double e; /**< \b e value */
+ double f; /**< \b f value */
} resvg_transform;
-
+/**
+ * @brief Initializes the library.
+ *
+ * See #resvg_handle for details.
+ *
+ * @return Library handle.
+ */
resvg_handle* resvg_init();
+
+/**
+ * @brief Destroys the #resvg_handle.
+ *
+ * @param handle Library handle.
+ */
void resvg_destroy(resvg_handle *handle);
+/**
+ * @brief Initializes the library log.
+ *
+ * Use it if you want to see any warnings.
+ *
+ * All warnings will be printed to the \b stderr.
+ */
void resvg_init_log();
+/**
+ * @brief Initializes the #resvg_options structure.
+ */
void resvg_init_options(resvg_options *opt)
{
opt->path = NULL;
@@ -76,93 +157,212 @@ void resvg_init_options(resvg_options *opt)
opt->fit_to.type = RESVG_FIT_TO_ORIGINAL;
opt->fit_to.value = 0;
opt->draw_background = false;
+ opt->background.r = 0;
+ opt->background.g = 0;
+ opt->background.b = 0;
opt->keep_named_groups = false;
}
/**
- * @brief Creates <b>resvg_render_tree</b> from file.
+ * @brief Creates #resvg_render_tree from file.
*
* .svg and .svgz files are supported.
*
- * @param file_path UTF-8 file path. Will panic on NULL value.
- * @param dpi Target DPI. Impact units converting and text rendering.
- * @param error The error string if NULL is returned. Should be destroyed via resvg_error_msg_destroy.
- * @return Parsed render tree. NULL on error. Should be destroyed via resvg_rtree_destroy.
+ * @param file_path UTF-8 file path.
+ * @param opt Rendering options.
+ * @param error The error string if NULL was returned. Should be destroyed via #resvg_error_msg_destroy.
+ * @return Parsed render tree. NULL on error. Should be destroyed via #resvg_rtree_destroy.
*/
resvg_render_tree *resvg_parse_rtree_from_file(const char *file_path,
const resvg_options *opt,
char **error);
/**
- * @brief Creates <b>resvg_render_tree</b> from UTF-8 string.
+ * @brief Creates #resvg_render_tree from UTF-8 string.
*
- * @param text UTF-8 string. Will panic on NULL value.
- * @param dpi Target DPI. Impact units converting and text rendering.
- * @param error The error string if NULL is returned. Should be destroyed via resvg_error_msg_destroy.
- * @return Parsed render tree. NULL on error. Should be destroyed via resvg_rtree_destroy.
+ * @param text UTF-8 string.
+ * @param opt Rendering options.
+ * @param error The error string if NULL was returned. Should be destroyed via #resvg_error_msg_destroy.
+ * @return Parsed render tree. NULL on error. Should be destroyed via #resvg_rtree_destroy.
*/
resvg_render_tree *resvg_parse_rtree_from_data(const char *text,
const resvg_options *opt,
char **error);
-void resvg_get_image_size(const resvg_render_tree *rtree,
- double *width,
- double *height);
+/**
+ * @brief Returns an image size.
+ *
+ * @param rtree Render tree.
+ * @return Image size.
+ */
+resvg_size resvg_get_image_size(const resvg_render_tree *rtree);
+
+/**
+ * @brief Returns an image viewbox.
+ *
+ * @param rtree Render tree.
+ * @return Image viewbox.
+ */
+resvg_rect resvg_get_image_viewbox(const resvg_render_tree *rtree);
+/**
+ * @brief Returns \b true if a node with such an ID exists.
+ *
+ * @param rtree Render tree.
+ * @param id Node's ID. UTF-8 string.
+ * @return \b true if a node exists. \b false if a node doesn't exist or ID isn't a UTF-8 string.
+ */
bool resvg_node_exists(const resvg_render_tree *rtree,
const char *id);
+/**
+ * @brief Returns node's transform by ID.
+ *
+ * @param rtree Render tree.
+ * @param id Node's ID. UTF-8 string.
+ * @param ts Node's transform.
+ * @return \b false if a node with such an ID does not exist or ID isn't a UTF-8 string.
+ */
bool resvg_get_node_transform(const resvg_render_tree *rtree,
const char *id,
resvg_transform *ts);
+/**
+ * @brief Destroys the #resvg_render_tree.
+ *
+ * @param rtree Render tree.
+ */
void resvg_rtree_destroy(resvg_render_tree *rtree);
+/**
+ * @brief Destroys the error message.
+ *
+ * @param msg Error message.
+ */
void resvg_error_msg_destroy(char *msg);
#ifdef RESVG_CAIRO_BACKEND
+/**
+ * @brief Returns node's bounding box by ID.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param id Node's ID.
+ * @param bbox Node's bounding box.
+ * @return \b false if a node with such an ID does not exist
+ * @return \b false if ID isn't a UTF-8 string.
+ * @return \b false if ID is an empty string
+ */
bool resvg_cairo_get_node_bbox(const resvg_render_tree *rtree,
const resvg_options *opt,
const char *id,
resvg_rect *bbox);
+/**
+ * @brief Renders the #resvg_render_tree to file.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param file_path File path.
+ * @return \b false if \b file_path isn't an UTF-8 string.
+ * @return \b false on "Out of memory".
+ * @return \b false on file write error.
+ */
bool resvg_cairo_render_to_image(const resvg_render_tree *rtree,
const resvg_options *opt,
const char *file_path);
+/**
+ * @brief Renders the #resvg_render_tree to canvas.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param size Canvas size.
+ * @param cr Canvas.
+ */
void resvg_cairo_render_to_canvas(const resvg_render_tree *rtree,
const resvg_options *opt,
resvg_size size,
cairo_t *cr);
+/**
+ * @brief Renders a Node by ID to canvas.
+ *
+ * Does nothing on error.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param size Canvas size.
+ * @param id Node's ID.
+ * @param cr Canvas.
+ */
void resvg_cairo_render_to_canvas_by_id(const resvg_render_tree *rtree,
const resvg_options *opt,
resvg_size size,
const char *id,
- void *painter);
-#endif
+ cairo_t *cr);
+#endif // RESVG_CAIRO_BACKEND
#ifdef RESVG_QT_BACKEND
+/**
+ * @brief Returns node's bounding box by ID.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param id Node's ID.
+ * @param bbox Node's bounding box.
+ * @return \b false if a node with such an ID does not exist,
+ * ID is an empty string or ID isn't a UTF-8 string.
+ */
bool resvg_qt_get_node_bbox(const resvg_render_tree *rtree,
const resvg_options *opt,
const char *id,
resvg_rect *bbox);
+/**
+ * @brief Renders the #resvg_render_tree to file.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param file_path File path.
+ * @return \b false if \b file_path isn't an UTF-8 string.
+ * @return \b false on "Out of memory".
+ * @return \b false on file write error.
+ */
bool resvg_qt_render_to_image(const resvg_render_tree *rtree,
const resvg_options *opt,
const char *file_path);
+/**
+ * @brief Renders the #resvg_render_tree to canvas.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param size Canvas size.
+ * @param painter Canvas.
+ */
void resvg_qt_render_to_canvas(const resvg_render_tree *rtree,
const resvg_options *opt,
resvg_size size,
void *painter);
+/**
+ * @brief Renders a Node by ID to canvas.
+ *
+ * Does nothing on error.
+ *
+ * @param rtree Render tree.
+ * @param opt Rendering options.
+ * @param size Canvas size.
+ * @param id Node's ID.
+ * @param painter Canvas.
+ */
void resvg_qt_render_to_canvas_by_id(const resvg_render_tree *rtree,
const resvg_options *opt,
resvg_size size,
const char *id,
void *painter);
-#endif
+#endif // RESVG_QT_BACKEND
#endif // RESVG_H
diff --git a/capi/src/lib.rs b/capi/src/lib.rs
index 7c7fad9..3329d11 100644
--- a/capi/src/lib.rs
+++ b/capi/src/lib.rs
@@ -16,13 +16,8 @@ extern crate cairo_sys;
use std::fmt;
use std::path;
use std::ptr;
-use std::ffi::{
- CStr,
- CString,
-};
-use std::os::raw::{
- c_char,
-};
+use std::ffi::{ CStr, CString };
+use std::os::raw::c_char;
#[cfg(feature = "qt-backend")]
use resvg::qt;
@@ -156,7 +151,10 @@ pub extern fn resvg_parse_rtree_from_file(
None => on_err!(error, "Error: file path is not an UTF-8 string."),
};
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
let rtree = match resvg::parse_rtree_from_file(file_path, &opt) {
Ok(rtree) => rtree,
@@ -178,7 +176,10 @@ pub extern fn resvg_parse_rtree_from_data(
None => on_err!(error, "Error: SVG data is not an UTF-8 string."),
};
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
let rtree = resvg::parse_rtree_from_data(text, &opt);
@@ -240,7 +241,10 @@ fn render_to_image(
None => return false,
};
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
let img = backend.render_to_image(&rtree.0, &opt);
let img = match img {
@@ -269,7 +273,10 @@ pub extern fn resvg_qt_render_to_canvas(
let painter = unsafe { qt::Painter::from_raw(painter) };
let size = resvg::ScreenSize::new(size.width, size.height);
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
resvg::render_qt::render_to_canvas(&rtree.0, &opt, size, &painter);
}
@@ -292,7 +299,10 @@ pub extern fn resvg_cairo_render_to_canvas(
let cr = unsafe { cairo::Context::from_glib_none(cr) };
let size = resvg::ScreenSize::new(size.width, size.height);
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
resvg::render_cairo::render_to_canvas(&rtree.0, &opt, size, &cr);
}
@@ -313,22 +323,34 @@ pub extern fn resvg_qt_render_to_canvas_by_id(
let painter = unsafe { qt::Painter::from_raw(painter) };
let size = resvg::ScreenSize::new(size.width, size.height);
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
let id = match cstr_to_str(id) {
Some(v) => v,
None => return,
};
+ if id.is_empty() {
+ warn!("Node with an empty ID can not be painted.");
+ return;
+ }
+
if let Some(node) = rtree.0.node_by_svg_id(id) {
if let Some(bbox) = resvg::render_qt::calc_node_bbox(&node, &opt) {
let vbox = tree::ViewBox {
rect: bbox,
- .. tree::ViewBox::default()
+ aspect: tree::AspectRatio::default(),
};
resvg::render_qt::render_node_to_canvas(&node, &opt, vbox, size, &painter);
+ } else {
+ warn!("A node with '{}' ID doesn't have a valid bounding box.", id);
}
+ } else {
+ warn!("A node with '{}' ID wasn't found.", id);
}
}
@@ -351,31 +373,41 @@ pub extern fn resvg_cairo_render_to_canvas_by_id(
None => return,
};
+ if id.is_empty() {
+ warn!("Node with an empty ID can not be painted.");
+ return;
+ }
+
use glib::translate::FromGlibPtrNone;
let cr = unsafe { cairo::Context::from_glib_none(cr) };
let size = resvg::ScreenSize::new(size.width, size.height);
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
if let Some(node) = rtree.0.node_by_svg_id(id) {
if let Some(bbox) = resvg::render_cairo::calc_node_bbox(&node, &opt) {
let vbox = tree::ViewBox {
rect: bbox,
- .. tree::ViewBox::default()
+ aspect: tree::AspectRatio::default(),
};
resvg::render_cairo::render_node_to_canvas(&node, &opt, vbox, size, &cr);
+ } else {
+ warn!("A node with '{}' ID doesn't have a valid bounding box.", id);
}
+ } else {
+ warn!("A node with '{}' ID wasn't found.", id);
}
}
#[no_mangle]
pub extern fn resvg_get_image_size(
rtree: *const resvg_render_tree,
- width: *mut f64,
- height: *mut f64,
-) {
+) -> resvg_size {
let rtree = unsafe {
assert!(!rtree.is_null());
&*rtree
@@ -383,9 +415,28 @@ pub extern fn resvg_get_image_size(
let size = rtree.0.svg_node().size;
- unsafe {
- *width = size.width;
- *height = size.height;
+ resvg_size {
+ width: size.width as u32,
+ height: size.height as u32,
+ }
+}
+
+#[no_mangle]
+pub extern fn resvg_get_image_viewbox(
+ rtree: *const resvg_render_tree,
+) -> resvg_rect {
+ let rtree = unsafe {
+ assert!(!rtree.is_null());
+ &*rtree
+ };
+
+ let r = rtree.0.svg_node().view_box.rect;
+
+ resvg_rect {
+ x: r.x(),
+ y: r.y(),
+ width: r.width(),
+ height: r.height(),
}
}
@@ -439,7 +490,10 @@ fn get_node_bbox(
};
- let opt = to_native_opt(unsafe { &*opt });
+ let opt = to_native_opt(unsafe {
+ assert!(!opt.is_null());
+ &*opt
+ });
match rtree.0.node_by_svg_id(id) {
Some(node) => {