Commit 616fbab
Preserve aspect ratio in view box
Changed files (3)
modifiedlibsvgbird/SvgDrawing.valamodifiedlibsvgbird/SvgFile.valamodifiedlibsvgbird/ViewBox.vala
Diff
@@ -66,8 +66,47 @@ public class SvgDrawing : Object { void apply_view_box (Context cr) { if (view_box != null) { ViewBox box = (!) view_box;+ double scale_x = 1;+ double scale_y = 1;+ double scale = 1;+ cr.translate (box.minx, box.miny);- cr.scale (width / box.width, height / box.height);+ scale_x = width / box.width;+ scale_y = height / box.height;+ + bool scale_width = height * box.width > width * box.height;+ + if (box.alignment == ViewBox.NONE) { + cr.scale (scale_x, scale_y);+ } else if (scale_width && box.slice) {+ scale = scale_x;+ cr.scale (scale, scale);+ } else {+ scale = scale_y;+ cr.scale (scale, scale);+ }+ + if (!box.slice) {+ if ((box.alignment & ViewBox.XMID) > 0) {+ cr.translate ((box.width - width) / 2, 0);+ } else if ((box.alignment & ViewBox.XMAX) > 0) {+ cr.translate (box.width - width, 0);+ }++ if ((box.alignment & ViewBox.YMID) > 0) {+ cr.translate (0, (box.height - height) / 2);+ } else if ((box.alignment & ViewBox.YMAX) > 0) {+ cr.translate (0, box.height - height);+ }+ } else {+ Layer layer = new Layer ();+ Rectangle rectangle = new Rectangle ();+ rectangle.width = box.width;+ rectangle.height = box.height;+ layer.add_object (rectangle);+ ClipPath clip = new ClipPath (layer);+ clip_path = clip;+ } } } @@ -84,10 +123,7 @@ public class SvgDrawing : Object { } public override void draw_outline (Context cr) {- cr.save ();- apply_transform (cr); root_layer.draw_outline (cr);- cr.restore (); } public override Object copy () {@@ -46,7 +46,7 @@ public class SvgFile : GLib.Object { } if (attr.get_name () == "viewBox") {- drawing.view_box = parse_view_box (attr.get_content ());+ drawing.view_box = parse_view_box (attr.get_content (), svg_tag); } } @@ -78,8 +78,26 @@ public class SvgFile : GLib.Object { return drawing; } - ViewBox? parse_view_box (string parameters) {+ ViewBox? parse_view_box (string parameters, XmlElement tag) { string arguments = parameters.replace (",", " ");+ string aspect_ratio = "";+ bool slice = false;+ + foreach (Attribute attribute in tag.get_attributes ()) {+ if (attribute.get_name () == "preserveAspectRatio") {+ aspect_ratio = attribute.get_content ();+ + string[] preserveSettings = aspect_ratio.split (" ");+ + if (preserveSettings.length >= 1) {+ aspect_ratio = preserveSettings[0];+ }+ + if (preserveSettings.length >= 2) {+ slice = preserveSettings[1] == "slice";+ }+ }+ } while (arguments.index_of (" ") > -1) { arguments = arguments.replace (" ", " ");@@ -97,7 +115,32 @@ public class SvgFile : GLib.Object { double width = parse_number (view_box_parameters[2]); double height = parse_number (view_box_parameters[3]); - return new ViewBox (minx, miny, width, height);+ uint alignment = ViewBox.XMID_YMID;+ aspect_ratio = aspect_ratio.up ();+ + if (aspect_ratio == "NONE") {+ alignment = ViewBox.NONE;+ } else if (aspect_ratio == "XMIN_YMIN") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMID_YMIN") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMAX_YMIN") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMIN_YMID") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMID_YMID") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMAX_YMID") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMIN_YMAX") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMID_YMAX") {+ alignment = ViewBox.XMIN_YMIN;+ } else if (aspect_ratio == "XMAX_YMAX") {+ alignment = ViewBox.XMIN_YMIN;+ }+ + return new ViewBox (minx, miny, width, height, alignment, slice); } private void parse_layer (Layer layer, SvgStyle parent_style, XmlElement tag) { @@ -21,16 +21,42 @@ namespace SvgBird { public class ViewBox : GLib.Object { + public const uint NONE = 1;+ public const uint XMIN = 1 << 1;+ public const uint XMID = 1 << 2;+ public const uint XMAX = 1 << 3;+ public const uint YMIN = 1 << 4;+ public const uint YMID = 1 << 5;+ public const uint YMAX = 1 << 6;+ + public const uint XMIN_YMIN = XMIN | YMIN;+ public const uint XMID_YMIN = XMID | YMIN;+ public const uint XMAX_YMIN = XMAX | YMIN;+ public const uint XMIN_YMID = XMIN | YMID;+ public const uint XMID_YMID = XMID | YMID;+ public const uint XMAX_YMID = XMAX | YMID;+ public const uint XMIN_YMAX = XMIN | YMAX;+ public const uint XMID_YMAX = XMID | YMAX;+ public const uint XMAX_YMAX = XMAX | YMAX;+ public double minx = 0; public double miny = 0; public double width = 0; public double height = 0; - public ViewBox (double minx, double miny, double width, double height) {+ public uint alignment;+ public bool slice;++ public ViewBox (double minx, double miny, double width, double height,+ uint alignment, bool slice) {+ this.minx = minx; this.miny = miny; this.width = width; this.height = height;+ + this.alignment = alignment;+ this.slice = slice; } }