Clone in a terminal:
ViewBox.vala
/*
	Copyright (C) 2016 Johan Mattsson

	This library is free software; you can redistribute it and/or modify 
	it under the terms of the GNU Lesser General Public License as 
	published by the Free Software Foundation; either version 3 of the 
	License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful, but 
	WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
	Lesser General Public License for more details.
*/


using B;
using Cairo;
using Math;

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 uint alignment;
	public bool slice;

	public bool preserve_aspect_ratio;

	public ViewBox.empty () {
	}

	public ViewBox (double minx, double miny, double width, double height,
		uint alignment, bool slice, bool preserve_aspect_ratio) {
			
		this.minx = minx;
		this.miny = miny;
		this.width = width;
		this.height = height;
		
		this.alignment = alignment;
		this.slice = slice;
		this.preserve_aspect_ratio = preserve_aspect_ratio;
	}

	public ViewBox copy () {
		ViewBox box = new ViewBox.empty (); 
		
		box.minx = minx;
		box.miny = miny;
		box.width = width;
		box.height = height;
		
		box.alignment = alignment;
		box.slice = slice;
		box.preserve_aspect_ratio = preserve_aspect_ratio;
		
		return box;
	}

	public Matrix get_matrix (double original_width, double original_height) {
		double scale_x = 1;
		double scale_y = 1;
		double scale = 1;

		Matrix matrix = Matrix.identity ();

		if (original_width == 0  || original_height == 0 || width == 0 || height == 0) {
			return matrix;
		}
		
		matrix.translate (minx, miny);
		scale_x = original_width / width;
		scale_y = original_height / height;
		
		bool scale_width = scale_x * original_height > scale_y * original_width;
		
		if (scale_width) {
			scale = scale_y;
		} else {
			scale = scale_x;
		}
		
		if (preserve_aspect_ratio) {
			if ((alignment & ViewBox.XMID) > 0) {
				matrix.translate ((original_width - width * scale) / 2, 0);
			} else if ((alignment & ViewBox.XMAX) > 0) {
				matrix.translate ((original_width - width * scale), 0);
			}

			if ((alignment & ViewBox.YMID) > 0) {
				matrix.translate ((original_height - height * scale) / 2, 0);
			} else if ((alignment & ViewBox.YMAX) > 0) {
				matrix.translate ((original_height - height * scale), 0);
			}
		}

		if (!preserve_aspect_ratio) {
			matrix.scale (scale_x, scale_y);
		} else if (scale_width) {
			scale = scale_y;
			matrix.scale (scale, scale);
		} else {
			scale = scale_x;
			matrix.scale (scale, scale);
		}
		
		return matrix;
	}	
}

}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112