[cairo] controlling the DPI in libsvg and friends

Jason Dorje Short jdorje at users.sf.net
Sat Aug 13 02:11:53 PDT 2005


This next patch adds user control of the DPI to libsvg, libsvg-cairo, 
and svg2png.  DPI must be the same in X and Y dimensions (this wouldn't 
be hard to separate but would complicate the interface more).

* libsvg gets a new function, svg_set_dpi.  This function probably needs 
to be called before parsing the SVG, but I don't see how to check this. 
  Changing the DPI later will probably give bizarre results.  I 
considered making it a part of svg_create but then we'd need to use -1 
for the "default"

   svg_create(&svg, -1);   // default resolution
   svg_create(&svg, 90);   // 90 DPI
   svg_create(&svg, 300);  // 300 DPI

and the API would become incompatible (all users would have to be 
fixed).  One alternative would be a new function svg_create_at_dpi (or 
svg_create_full).

* libsvg-cairo gets a wrapper, svg_cairo_set_dpi.  The same caveats apply.

* svg2png is given a new parameter --dpi.  Note that most SVG files 
(including all created with inkscape AFAICT) will not operate 
exclusively in distance measurements.  Even if you tell inkscape to use 
inches as its default unit everything is still saved in pixels. 
Attached is a simple SVG that is all in inches.  Using --dpi with this 
does work.  This would be useful for rendering into a resolution for 
printing (for instance). The -d option is also compatible with 
inkscape's command-line interface (rsvg does separate X and Y dpi setting).

* xsvg could probably use a similar option, but I haven't looked into that.

-jason

-------------- next part --------------
Index: libsvg/src/svg.c
===================================================================
RCS file: /cvs/cairo/libsvg/src/svg.c,v
retrieving revision 1.13
diff -p -u -r1.13 svg.c
--- libsvg/src/svg.c	13 Aug 2005 07:00:13 -0000	1.13
+++ libsvg/src/svg.c	13 Aug 2005 09:01:25 -0000
@@ -261,6 +261,18 @@ svg_get_dpi (svg_t *svg)
     return svg->dpi;
 }
 
+/* This function probably needs to be called before parsing is done. */
+svg_status_t
+svg_set_dpi (svg_t *svg, double dpi)
+{
+    if (dpi > 0.0) {
+	svg->dpi = dpi;
+	return SVG_STATUS_SUCCESS;
+    } else {
+	return SVG_STATUS_INVALID_VALUE;
+    }
+}
+
 void
 svg_get_size (svg_t *svg, svg_length_t *width, svg_length_t *height)
 {
Index: libsvg/src/svg.h
===================================================================
RCS file: /cvs/cairo/libsvg/src/svg.h,v
retrieving revision 1.24
diff -p -u -r1.24 svg.h
--- libsvg/src/svg.h	13 Aug 2005 07:00:13 -0000	1.24
+++ libsvg/src/svg.h	13 Aug 2005 09:01:25 -0000
@@ -350,6 +350,8 @@ svg_render (svg_t		*svg,
 
 double
 svg_get_dpi (svg_t *svg);
+svg_status_t
+svg_set_dpi (svg_t *svg, double dpi);
 
 void
 svg_get_size (svg_t *svg,
Index: libsvg-cairo/src/svg-cairo.h
===================================================================
RCS file: /cvs/cairo/libsvg-cairo/src/svg-cairo.h,v
retrieving revision 1.14
diff -p -u -r1.14 svg-cairo.h
--- libsvg-cairo/src/svg-cairo.h	12 Jul 2005 18:46:22 -0000	1.14
+++ libsvg-cairo/src/svg-cairo.h	13 Aug 2005 09:01:25 -0000
@@ -46,6 +46,9 @@ svg_cairo_status_t
 svg_cairo_create (svg_cairo_t **svg_cairo);
 
 svg_cairo_status_t
+svg_cairo_set_dpi (svg_cairo_t *svg_cairo, double dpi);
+
+svg_cairo_status_t
 svg_cairo_destroy (svg_cairo_t *svg_cairo);
 
 svg_cairo_status_t
Index: libsvg-cairo/src/svg_cairo.c
===================================================================
RCS file: /cvs/cairo/libsvg-cairo/src/svg_cairo.c,v
retrieving revision 1.43
diff -p -u -r1.43 svg_cairo.c
--- libsvg-cairo/src/svg_cairo.c	13 Aug 2005 07:06:02 -0000	1.43
+++ libsvg-cairo/src/svg_cairo.c	13 Aug 2005 09:01:26 -0000
@@ -289,6 +289,16 @@ svg_cairo_create (svg_cairo_t **svg_cair
 }
 
 svg_cairo_status_t
+svg_cairo_set_dpi (svg_cairo_t *svg_cairo, double dpi)
+{
+    if (svg_set_dpi(svg_cairo->svg, dpi) == SVG_STATUS_SUCCESS) {
+	return SVG_CAIRO_STATUS_SUCCESS;
+    } else {
+	return SVG_CAIRO_STATUS_INVALID_VALUE;
+    }
+}
+
+svg_cairo_status_t
 svg_cairo_destroy (svg_cairo_t *svg_cairo)
 {
     svg_cairo_status_t status;
Index: svg2png/doc/svg2png.1
===================================================================
RCS file: /cvs/cairo/svg2png/doc/svg2png.1,v
retrieving revision 1.3
diff -p -u -r1.3 svg2png.1
--- svg2png/doc/svg2png.1	13 Aug 2005 07:41:22 -0000	1.3
+++ svg2png/doc/svg2png.1	13 Aug 2005 09:01:26 -0000
@@ -36,6 +36,9 @@ Scale image by \fIFACTOR\fR in the X dir
 .B \-y, \-\-yscale=\fIFACTOR\fR
 Scale image by \fIFACTOR\fR in the Y direction. This option is ignored if either of the \-\-width or \-\-height options are provided.  This option will override the \-\-scale option.
 .TP
+.B \-d, \-\-dpi=\fIDPI\fR
+Render the SVG at the given resolution (dots per inch).  This is most useful when the SVG is defined in terms of distances (inches, millimeters) and this size needs to be preserved when rendering to a fixed-DPI device (printer, monitor).  This option does not work well with \-\-width, \-\-height, \-\-scale, \-\-xscale, or \-\-yscale.  SVG files that use pixel measurements or mixed units may be rendered incorrectly with this option.
+.TP
 .B \-X, \-\-flipx
 Flip the output X coordinates.
 .TP
Index: svg2png/src/args.c
===================================================================
RCS file: /cvs/cairo/svg2png/src/args.c,v
retrieving revision 1.5
diff -p -u -r1.5 args.c
--- svg2png/src/args.c	13 Aug 2005 07:41:22 -0000	1.5
+++ svg2png/src/args.c	13 Aug 2005 09:01:26 -0000
@@ -49,6 +49,7 @@ enum args_val {
     ARGS_VAL_SCALE = 's',
     ARGS_VAL_XSCALE = 'x',
     ARGS_VAL_YSCALE = 'y',
+    ARGS_VAL_DPI = 'd',
     ARGS_VAL_FLIPX = 'X',
     ARGS_VAL_FLIPY = 'Y',
     ARGS_VAL_PAD = 'p',
@@ -57,7 +58,7 @@ enum args_val {
     ARGS_VAL_VERSION = 'V'
 };
 
-static const char args_optstring[] = "h:w:s:x:y:XYpt?V";
+static const char args_optstring[] = "h:w:s:x:y:d:XYpt?V";
 static struct option args_options[] = {
     /* name,		has_arg,	flag,	val */
     {"height",		1,		0,	ARGS_VAL_HEIGHT},
@@ -65,6 +66,7 @@ static struct option args_options[] = {
     {"scale",		1,		0,	ARGS_VAL_SCALE},
     {"xscale",          1,              0,      ARGS_VAL_XSCALE},
     {"yscale",          1,              0,      ARGS_VAL_YSCALE},
+    {"dpi",             1,              0,      ARGS_VAL_DPI},
 
     {"flipx",		0,		0,	ARGS_VAL_FLIPX},
     {"flipy",		0,		0,	ARGS_VAL_FLIPY},
@@ -98,6 +100,7 @@ args_help (const char *argv0)
     printf ("  -s, --scale=FACTOR\tScale image by FACTOR\n");
     printf ("  -x, --xscale=FACTOR\tScale image width by FACTOR\n");
     printf ("  -y, --yscale=FACTOR\tScale image height by FACTOR\n");
+    printf ("  -d, --dpi=DPI\t\tRender image at DPI resolution\n");
     puts ("");
 #if 0
     printf ("Options to flip the image:\n");
@@ -152,6 +155,7 @@ args_parse (args_t *args, int argc, char
     args->yscale = -1.0;
     args->width = -1;
     args->height = -1;
+    args->dpi = -1.0;
 
     args->flipx = 0;
     args->flipy = 0;
@@ -179,6 +183,9 @@ args_parse (args_t *args, int argc, char
 	case ARGS_VAL_YSCALE:
 	    args->yscale = atof(optarg);
 	    break;
+	case ARGS_VAL_DPI:
+	    args->dpi = atof(optarg);
+	    break;
 	case ARGS_VAL_FLIPX:
 	    args->flipx = 1;
 	    break;
Index: svg2png/src/svg2png.c
===================================================================
RCS file: /cvs/cairo/svg2png/src/svg2png.c,v
retrieving revision 1.10
diff -p -u -r1.10 svg2png.c
--- svg2png/src/svg2png.c	13 Aug 2005 07:41:22 -0000	1.10
+++ svg2png/src/svg2png.c	13 Aug 2005 09:01:26 -0000
@@ -132,6 +132,14 @@ render_to_png (FILE *svg_file, FILE *png
 	exit(1);
     }
 
+    if (args->dpi > 0.0) {
+	status = svg_cairo_set_dpi(svgc, args->dpi);
+	if (status) {
+	    fprintf (stderr, "Failed to set DPI of %f. Exiting.\n", args->dpi);
+	    exit(1);
+	}
+    }
+
     status = svg_cairo_parse_file (svgc, svg_file);
     if (status)
 	return status;
@@ -140,8 +148,8 @@ render_to_png (FILE *svg_file, FILE *png
 
     /* xscale, yscale, or scale <= 0 means no option */
     scale = args->scale > 0.0 ? args->scale : 1.0;
-    xscale = args->xscale > 0.0 ? args->xscale : args->scale;
-    yscale = args->yscale > 0.0 ? args->yscale : args->scale;
+    xscale = args->xscale > 0.0 ? args->xscale : scale;
+    yscale = args->yscale > 0.0 ? args->yscale : scale;
 
     if (args->width <= 0 && args->height <= 0) {
         /* Neither width or height are given.  This case is easy; we just
-------------- next part --------------
A non-text attachment was scrubbed...
Name: in.svg
Type: image/svg+xml
Size: 1368 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050813/c9039379/in.svg


More information about the cairo mailing list