From 6c7637ee2b4b443797c36d7f40aa4cc2ffcdf0d0 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 11 Oct 2017 18:51:13 +0200 Subject: [PATCH] svg: add a new function to specify the SVG document unit X-Face: z*RaLf`X<@C75u6Ig9}{oW$H;1_\2t5)({*|jhM/Vb;]yA5\I~93>J<_`<4)A{':UrE 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 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. https://bugs.freedesktop.org/show_bug.cgi?id=90166 --- src/cairo-svg-surface.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-- src/cairo-svg.h | 47 +++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 29bdd8c04..0853360a7 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) "\n" "\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 592c645f6..95434dcf6 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 */ -- 2.15.0