The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Preserve aspect ratio in view box

These changes was commited to the Birdfont repository Sat, 02 Jul 2016 09:47:53 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Sat, 02 Jul 2016 09:47:53 +0000 (11:47 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Sat, 02 Jul 2016 09:47:53 +0000 (11:47 +0200)
commit 616fbabd957e312219d92ec61a8fad9b08a9cbc1
tree 1a79091171e00db1a9f9b243b9fc67842df487ae
parent 3336516c6e2e065929a97b767ed70e45e6977dcd
Preserve aspect ratio in view box

libsvgbird/SvgDrawing.vala
libsvgbird/SvgFile.vala
libsvgbird/ViewBox.vala
--- a/libsvgbird/SvgDrawing.vala +++ b/libsvgbird/SvgDrawing.vala @@ -66,8 +66,47 @@ 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 override void draw_outline (Context cr) { - cr.save (); - apply_transform (cr); root_layer.draw_outline (cr); - cr.restore (); } public override Object copy () {
--- a/libsvgbird/SvgFile.vala +++ b/libsvgbird/SvgFile.vala @@ -46,7 +46,7 @@ } 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 @@ 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 @@ 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) {
--- a/libsvgbird/ViewBox.vala +++ b/libsvgbird/ViewBox.vala @@ -20,20 +20,46 @@ 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; } } }