summaryrefslogtreecommitdiff
path: root/dmagick/Geometry.d
blob: e25a6859a6617638d27e2a36d21913816fd9ed22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
 * Copyright: Mike Wey 2011
 * License:   To be determined
 * Authors:   Mike Wey
 */

module dmagick.Geometry;

import std.conv;
import std.ctype;
import std.string;
import core.sys.posix.sys.types;

import dmagick.c.geometry;
import dmagick.c.magickString;
import dmagick.c.magickType;

/**
 * Geometry provides a convenient means to specify a geometry argument.
 */
struct Geometry
{
	size_t width;    ///
	size_t height;   ///
	ssize_t xOffset; ///
	ssize_t yOffset; ///
	bool percent;    /// The width and/or height are percentages of the original.
	bool minimum;    /// The specified width and/or height is the minimum value.
	bool keepAspect = true;  ///Retain the aspect ratio.
	bool greater;    /// Resize only if the image is greater than the width and/or height.
	bool less;       /// Resize only if the image is smaller than the width and/or height.

	/**
	 * Create a Geometry form a Imagemagick / X11 geometry string.
	 */
	//TODO: expand the documentation for this constructor.
	this(string geometry)
	{
		MagickStatusType flags;

		//If the string starts with a letter assume it's a Page Geometry.
		if ( isalpha(geometry[0]) )
		{
			char* geo = GetPageGeometry(toStringz(geometry));

			if( geo !is null )
			{
				geometry = to!(string)(geo);
				DestroyString(geo);
			}
		}

		flags = GetGeometry(toStringz(geometry), &xOffset, &yOffset, &width, &height);

		percent    = ( flags & GeometryFlags.PercentValue ) != 0;
		minimum    = ( flags & GeometryFlags.MinimumValue ) != 0;
		keepAspect = ( flags & GeometryFlags.AspectValue  ) == 0;
		greater    = ( flags & GeometryFlags.GreaterValue ) != 0;
		less       = ( flags & GeometryFlags.LessValue    ) != 0;
	}

	unittest
	{
		Geometry geo = Geometry("200x150-50+25!");
		assert( geo.width == 200 && geo.xOffset == -50 );
		assert( geo.keepAspect == false );

		geo = Geometry("A4");
		assert( geo.width == 595 && geo.height == 842);
	}

	this(RectangleInfo rectangle)
	{
		this.width = rectangle.width;
		this.height = rectangle.height;
		this.xOffset = rectangle.x;
		this.yOffset = rectangle.y;
	}

	/**
	 * Initialize with width heigt and offsets.
	 */
	this(size_t width, size_t height, ssize_t xOffset = 0, ssize_t yOffset = 0)
	{
		this.width   = width;
		this.height  = height;
		this.xOffset = xOffset;
		this.yOffset = yOffset;
	}

	/**
	 * Convert Geometry into a Imagemagick geometry string.
	 */
	string toString()
	{
		string geometry;

		if ( width > 0 )
			geometry ~= to!(string)(width);

		if ( height > 0 )
			geometry ~= "x" ~ to!(string)(height);

		geometry ~= format("%s%s%s%s%s",
			percent ? "%" : "",
			minimum ? "^" : "",
			keepAspect ? "" : "!",
			less ? "<" : "",
			greater ? ">" : "");

		if ( xOffset != 0 && yOffset != 0 )
			geometry ~= format("%+s%+s", xOffset, yOffset);

		return geometry;
	}

	unittest
	{
		Geometry geo = Geometry("200x150!-50+25");
		assert( geo.toString == "200x150!-50+25");
	}

	int opCmp(ref const Geometry geometry)
	{
		return width*height - geometry.width*geometry.height;
	}
}