[cairo-commit] src/cairo-svg.h src/cairo-svg-surface.c

Bryce Harrington bryce at kemper.freedesktop.org
Mon Dec 4 22:01:33 UTC 2017


 src/cairo-svg-surface.c |   84 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/cairo-svg.h         |   47 ++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 2 deletions(-)

New commits:
commit 15559b54af473d720da9e03b0e769c54a53505a9
Author: Antonio Ospite <ao2 at ao2.it>
Date:   Wed Oct 11 18:51:13 2017 +0200

    svg: add a new function to specify the SVG document unit
    
    Add a cairo_svg_surface_set_document_unit() function to allow users to
    set a unit for the width and height values of the root <svg> element.
    
    In particular this allows to draw in pixels and still have the expected
    result when generating SVG output.
    
    Add also the correspondent getter function.
    
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=90166
    Reviewed-by: Bryce Harrington <bryce at osg.samsung.com>

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 29bdd8c0..0853360a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -122,6 +122,20 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
     "1.2"
 };
 
+static const char * _cairo_svg_unit_strings[] =
+{
+    [CAIRO_SVG_UNIT_USER] = "",
+    [CAIRO_SVG_UNIT_EM] = "em",
+    [CAIRO_SVG_UNIT_EX] = "ex",
+    [CAIRO_SVG_UNIT_PX] = "px",
+    [CAIRO_SVG_UNIT_IN] = "in",
+    [CAIRO_SVG_UNIT_CM] = "cm",
+    [CAIRO_SVG_UNIT_MM] = "mm",
+    [CAIRO_SVG_UNIT_PT] = "pt",
+    [CAIRO_SVG_UNIT_PC] = "pc",
+    [CAIRO_SVG_UNIT_PERCENT] = "%"
+};
+
 struct cairo_svg_page {
     unsigned int surface_id;
     unsigned int clip_level;
@@ -136,6 +150,7 @@ struct cairo_svg_document {
 
     double width;
     double height;
+    cairo_svg_unit_t unit;
 
     cairo_output_stream_t *xml_node_defs;
     cairo_output_stream_t *xml_node_glyphs;
@@ -405,6 +420,69 @@ cairo_svg_version_to_string (cairo_svg_version_t version)
     return _cairo_svg_version_strings[version];
 }
 
+/**
+ * cairo_svg_surface_set_document_unit:
+ * @surface: a SVG #cairo_surface_t
+ * @unit: SVG unit
+ *
+ * Use the specified unit for the width and height of the generated SVG file.
+ * See #cairo_svg_unit_t for a list of available unit values that can be used
+ * here.
+ *
+ * This function can be called at any time before generating the SVG file.
+ *
+ * However to minimize the risk of ambiguities it's recommended to call it
+ * before any drawing operations have been performed on the given surface, to
+ * make it clearer what the unit used in the drawing operations is.
+ *
+ * The simplest way to do this is to call this function immediately after
+ * creating the SVG surface.
+ *
+ * NOTE: if this function is never called, the default unit for SVG documents
+ * generated by cairo will be "pt". This is for historical reasons.
+ *
+ * Since: 1.16
+ **/
+void
+cairo_svg_surface_set_document_unit (cairo_surface_t	*abstract_surface,
+				     cairo_svg_unit_t	 unit)
+{
+    cairo_svg_surface_t *surface = NULL; /* hide compiler warning */
+
+    if (! _extract_svg_surface (abstract_surface, &surface))
+	return;
+
+    if (unit <= CAIRO_SVG_UNIT_PERCENT)
+	surface->document->unit = unit;
+}
+
+/**
+ * cairo_svg_surface_get_document_unit:
+ * @surface: a SVG #cairo_surface_t
+ *
+ * Get the unit of the SVG surface.
+ *
+ * If the surface passed as an argument is not a SVG surface, the function
+ * sets the error status to CAIRO_STATUS_SURFACE_TYPE_MISMATCH and returns
+ * CAIRO_SVG_UNIT_USER.
+ *
+ * Return value: the SVG unit of the SVG surface.
+ *
+ * Since: 1.16
+ **/
+cairo_svg_unit_t
+cairo_svg_surface_get_document_unit (cairo_surface_t	*abstract_surface)
+{
+    cairo_svg_surface_t *surface = NULL; /* hide compiler warning */
+
+    if (! _extract_svg_surface (abstract_surface, &surface)) {
+	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
+	return CAIRO_SVG_UNIT_USER;
+    }
+
+    return surface->document->unit;
+}
+
 static void
 _cairo_svg_source_surface_init_key (cairo_svg_source_surface_t *key)
 {
@@ -2801,6 +2879,7 @@ _cairo_svg_document_create (cairo_output_stream_t	 *output_stream,
     document->finished = FALSE;
     document->width = width;
     document->height = height;
+    document->unit = CAIRO_SVG_UNIT_PT;
 
     document->linear_pattern_id = 0;
     document->radial_pattern_id = 0;
@@ -2903,9 +2982,10 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
 				 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 				 "<svg xmlns=\"http://www.w3.org/2000/svg\" "
 				 "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
-				 "width=\"%fpt\" height=\"%fpt\" "
+				 "width=\"%f%s\" height=\"%f%s\" "
 				 "viewBox=\"0 0 %f %f\" version=\"%s\">\n",
-				 document->width, document->height,
+				 document->width, _cairo_svg_unit_strings [document->unit],
+				 document->height, _cairo_svg_unit_strings [document->unit],
 				 document->width, document->height,
 				 _cairo_svg_internal_version_strings [document->svg_version]);
 
diff --git a/src/cairo-svg.h b/src/cairo-svg.h
index 592c645f..95434dcf 100644
--- a/src/cairo-svg.h
+++ b/src/cairo-svg.h
@@ -53,6 +53,46 @@ typedef enum _cairo_svg_version {
     CAIRO_SVG_VERSION_1_2
 } cairo_svg_version_t;
 
+/**
+ * cairo_svg_version_t:
+ *
+ * @CAIRO_SVG_UNIT_USER: User unit, a value in the current coordinate system.
+ *   If used in the root element for the initial coordinate systems it
+ *   corresponds to pixels. (Since 1.16)
+ * @CAIRO_SVG_UNIT_EM: The size of the element's font. (Since 1.16)
+ * @CAIRO_SVG_UNIT_EX: The x-height of the element’s font. (Since 1.16)
+ * @CAIRO_SVG_UNIT_PX: Pixels (1px = 1/96th of 1in). (Since 1.16)
+ * @CAIRO_SVG_UNIT_IN: Inches (1in = 2.54cm = 96px). (Since 1.16)
+ * @CAIRO_SVG_UNIT_CM: Centimeters (1cm = 96px/2.54). (Since 1.16)
+ * @CAIRO_SVG_UNIT_MM: Millimeters (1mm = 1/10th of 1cm). (Since 1.16)
+ * @CAIRO_SVG_UNIT_PT: Points (1pt = 1/72th of 1in). (Since 1.16)
+ * @CAIRO_SVG_UNIT_PC: Picas (1pc = 1/6th of 1in). (Since 1.16)
+ * @CAIRO_SVG_UNIT_PERCENT: Percent, a value that is some fraction of another
+ *   reference value. (Since 1.16)
+ *
+ * #cairo_svg_unit_t is used to describe the units valid for coordinates and
+ * lengths in the SVG specification.
+ *
+ * See also:
+ * https://www.w3.org/TR/SVG/coords.html#Units
+ * https://www.w3.org/TR/SVG/types.html#DataTypeLength
+ * https://www.w3.org/TR/css-values-3/#lengths
+ *
+ * Since: 1.16
+ **/
+typedef enum _cairo_svg_unit {
+    CAIRO_SVG_UNIT_USER = 0,
+    CAIRO_SVG_UNIT_EM,
+    CAIRO_SVG_UNIT_EX,
+    CAIRO_SVG_UNIT_PX,
+    CAIRO_SVG_UNIT_IN,
+    CAIRO_SVG_UNIT_CM,
+    CAIRO_SVG_UNIT_MM,
+    CAIRO_SVG_UNIT_PT,
+    CAIRO_SVG_UNIT_PC,
+    CAIRO_SVG_UNIT_PERCENT
+} cairo_svg_unit_t;
+
 cairo_public cairo_surface_t *
 cairo_svg_surface_create (const char   *filename,
 			  double	width_in_points,
@@ -75,6 +115,13 @@ cairo_svg_get_versions (cairo_svg_version_t const	**versions,
 cairo_public const char *
 cairo_svg_version_to_string (cairo_svg_version_t version);
 
+cairo_public void
+cairo_svg_surface_set_document_unit (cairo_surface_t	*surface,
+				     cairo_svg_unit_t	 unit);
+
+cairo_public cairo_svg_unit_t
+cairo_svg_surface_get_document_unit (cairo_surface_t	*surface);
+
 CAIRO_END_DECLS
 
 #else  /* CAIRO_HAS_SVG_SURFACE */


More information about the cairo-commit mailing list