Geometry.cpp revision 01eeed7dbec7b3cb4f6c9076de55bae95cb9de09
1// This may look like C code, but it is really -*- C++ -*-
2//
3// Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
4//
5// Geometry implementation
6//
7
8#define MAGICKCORE_IMPLEMENTATION  1
9#define MAGICK_PLUSPLUS_IMPLEMENTATION 1
10
11#include "Magick++/Include.h"
12#include <string>
13#include <ctype.h> // for isdigit
14#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
15#include <strings.h>
16#endif
17
18using namespace std;
19
20#include "Magick++/Geometry.h"
21#include "Magick++/Exception.h"
22
23MagickPPExport int Magick::operator == (const Magick::Geometry& left_,
24  const Magick::Geometry& right_)
25{
26  return((left_.aspect() == right_.aspect()) &&
27    (left_.fillArea() == right_.fillArea()) &&
28    (left_.greater() == right_.greater()) &&
29    (left_.height() == right_.height()) &&
30    (left_.isValid() == right_.isValid()) &&
31    (left_.less() == right_.less()) &&
32    (left_.limitPixels() == right_.limitPixels()) &&
33    (left_.percent() == right_.percent()) &&
34    (left_.width() == right_.width()) &&
35    (left_.xNegative() == right_.xNegative()) &&
36    (left_.xOff() == right_.xOff()) &&
37    (left_.yNegative() == right_.yNegative()) &&
38    (left_.yOff() == right_.yOff()));
39}
40
41MagickPPExport int Magick::operator != (const Magick::Geometry& left_,
42  const Magick::Geometry& right_)
43{
44  return(!(left_ == right_));
45}
46
47MagickPPExport int Magick::operator > (const Magick::Geometry& left_,
48  const Magick::Geometry& right_)
49{
50  return(!(left_ < right_) && (left_ != right_));
51}
52
53MagickPPExport int Magick::operator < (const Magick::Geometry& left_,
54  const Magick::Geometry& right_)
55{
56  return((left_.width()*left_.height()) < (right_.width()*right_.height()));
57}
58
59MagickPPExport int Magick::operator >= (const Magick::Geometry& left_,
60  const Magick::Geometry& right_)
61{
62  return((left_ > right_) || (left_ == right_));
63}
64
65MagickPPExport int Magick::operator <= (const Magick::Geometry& left_,
66  const Magick::Geometry& right_ )
67{
68  return((left_ < right_) || (left_ == right_));
69}
70
71Magick::Geometry::Geometry(void)
72  : _width(0),
73    _height(0),
74    _xOff(0),
75    _yOff(0),
76    _xNegative(false),
77    _yNegative(false),
78    _isValid(false),
79    _percent(false),
80    _aspect(false),
81    _greater(false),
82    _less(false),
83    _fillArea(false),
84    _limitPixels(false)
85{
86}
87
88Magick::Geometry::Geometry(const char *geometry_)
89  : _width(0),
90    _height(0),
91    _xOff(0),
92    _yOff(0),
93    _xNegative(false),
94    _yNegative(false),
95    _isValid(false),
96    _percent(false),
97    _aspect(false),
98    _greater(false),
99    _less(false),
100    _fillArea(false),
101    _limitPixels(false)
102{
103  *this=geometry_; // Use assignment operator
104}
105
106Magick::Geometry::Geometry(const Geometry &geometry_)
107  : _width(geometry_._width),
108    _height(geometry_._height),
109    _xOff(geometry_._xOff),
110    _yOff(geometry_._yOff),
111    _xNegative(geometry_._xNegative),
112    _yNegative(geometry_._yNegative),
113    _isValid(geometry_._isValid),
114    _percent(geometry_._percent),
115    _aspect(geometry_._aspect),
116    _greater(geometry_._greater),
117    _less(geometry_._less),
118    _fillArea(geometry_._fillArea),
119    _limitPixels(geometry_._limitPixels)
120{
121}
122
123Magick::Geometry::Geometry(const std::string &geometry_)
124  : _width(0),
125    _height(0),
126    _xOff(0),
127    _yOff(0),
128    _xNegative(false),
129    _yNegative(false),
130    _isValid(false),
131    _percent(false),
132    _aspect(false),
133    _greater(false),
134    _less(false),
135    _fillArea(false),
136    _limitPixels(false)
137{
138  *this=geometry_; // Use assignment operator
139}
140
141Magick::Geometry::Geometry(size_t width_,size_t height_,ssize_t xOff_,
142  ssize_t yOff_,bool xNegative_,bool yNegative_)
143  : _width(width_),
144    _height(height_),
145    _xOff(xOff_),
146    _yOff(yOff_),
147    _xNegative(xNegative_),
148    _yNegative(yNegative_),
149    _isValid(true),
150    _percent(false),
151    _aspect(false),
152    _greater(false),
153    _less(false),
154    _fillArea(false),
155    _limitPixels(false)
156{
157}
158
159Magick::Geometry::~Geometry(void)
160{
161}
162
163const Magick::Geometry& Magick::Geometry::operator=(const char * geometry_)
164{
165  *this=std::string(geometry_);
166  return(*this);
167}
168
169Magick::Geometry& Magick::Geometry::operator=(const Geometry& geometry_)
170{
171  // If not being set to ourself
172  if (this != &geometry_)
173    {
174      _width=geometry_._width;
175      _height=geometry_._height;
176      _xOff=geometry_._xOff;
177      _yOff=geometry_._yOff;
178      _xNegative=geometry_._xNegative;
179      _yNegative=geometry_._yNegative;
180      _isValid=geometry_._isValid;
181      _percent=geometry_._percent;
182      _aspect=geometry_._aspect;
183      _greater=geometry_._greater;
184      _less=geometry_._less;
185      _fillArea=geometry_._fillArea;
186      _limitPixels=geometry_._limitPixels;
187    }
188  return(*this);
189}
190
191const Magick::Geometry& Magick::Geometry::operator=(
192  const std::string &geometry_)
193{
194  char
195    geom[MaxTextExtent];
196
197  char
198    *pageptr;
199
200  ssize_t
201    flags,
202    x = 0,
203    y = 0;
204
205  size_t
206    height=0,
207    width=0;
208
209  // If argument does not start with digit, presume that it is a
210  // page-size specification that needs to be converted to an
211  // equivalent geometry specification using PostscriptGeometry()
212  (void) CopyMagickString(geom,geometry_.c_str(),MaxTextExtent);
213  if (geom[0] != '-' && geom[0] != '+' && geom[0] != 'x' &&
214      !isdigit(static_cast<int>(geom[0])))
215    {
216      pageptr=GetPageGeometry(geom);
217      if (pageptr != 0)
218        {
219          (void) CopyMagickString(geom,pageptr,MaxTextExtent);
220          pageptr=(char *) RelinquishMagickMemory(pageptr);
221        }
222    }
223
224  flags=GetGeometry(geom,&x,&y,&width,&height);
225
226  if (flags == NoValue)
227    {
228      // Total failure!
229      *this=Geometry();
230      isValid(false);
231      return(*this);
232    }
233
234  if ((flags & WidthValue) != 0)
235    {
236      _width=width;
237      isValid(true);
238    }
239
240  if ((flags & HeightValue) != 0)
241    {
242      _height=height;
243      isValid(true);
244    }
245
246  if ((flags & XValue) != 0)
247    {
248      _xOff=static_cast<ssize_t>(x);
249      isValid(true);
250    }
251
252  if ((flags & YValue) != 0)
253    {
254      _yOff=static_cast<ssize_t>(y);
255      isValid(true);
256    }
257
258  if ((flags & XNegative) != 0)
259    _xNegative=true;
260
261  if ((flags & YNegative) != 0)
262    _yNegative=true;
263
264  if ((flags & PercentValue) != 0)
265    _percent=true;
266
267  if ((flags & AspectValue) != 0)
268    _aspect=true;
269
270  if ((flags & LessValue) != 0)
271    _less=true;
272
273  if ((flags & GreaterValue) != 0)
274    _greater=true;
275
276  if ((flags & MinimumValue) != 0)
277    _fillArea=true;
278
279  if ((flags & AreaValue) != 0)
280    _limitPixels=true;
281
282  return(*this);
283}
284
285Magick::Geometry::operator std::string() const
286{
287  char
288    buffer[MaxTextExtent];
289
290  string
291    geometry;
292
293  if (!isValid())
294    throwExceptionExplicit(OptionError,"Invalid geometry argument");
295
296  if (_width)
297    {
298      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _width);
299      geometry+=buffer;
300    }
301
302  if (_height)
303    {
304      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _height);
305      geometry+='x';
306      geometry+=buffer;
307    }
308
309  if (_xOff || _yOff)
310    {
311      if (_xNegative)
312        geometry+='-';
313      else
314        geometry+='+';
315
316      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _xOff);
317      geometry+=buffer;
318
319      if (_yNegative)
320        geometry+='-';
321      else
322        geometry+='+';
323
324      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _yOff);
325      geometry+=buffer;
326    }
327
328  if (_percent)
329    geometry+='%';
330
331  if (_aspect)
332    geometry+='!';
333
334  if (_greater)
335    geometry+='>';
336
337  if (_less)
338    geometry+='<';
339
340  if (_fillArea)
341    geometry+='^';
342
343  if (_limitPixels)
344    geometry+='@';
345
346  return(geometry);
347}
348
349Magick::Geometry::Geometry(const MagickCore::RectangleInfo &rectangle_)
350  : _width(static_cast<size_t>(rectangle_.width)),
351    _height(static_cast<size_t>(rectangle_.height)),
352    _xOff(static_cast<ssize_t>(rectangle_.x)),
353    _yOff(static_cast<ssize_t>(rectangle_.y)),
354    _xNegative(rectangle_.x < 0 ? true : false),
355    _yNegative(rectangle_.y < 0 ? true : false),
356    _isValid(true),
357    _percent(false),
358    _aspect(false),
359    _greater(false),
360    _less(false),
361    _fillArea(false),
362    _limitPixels(false)
363{
364}
365
366Magick::Geometry::operator MagickCore::RectangleInfo() const
367{
368  RectangleInfo rectangle;
369  rectangle.width=_width;
370  rectangle.height=_height;
371  _xNegative ? rectangle.x=static_cast<ssize_t>(0-_xOff) :
372    rectangle.x=static_cast<ssize_t>(_xOff);
373  _yNegative ? rectangle.y=static_cast<ssize_t>(0-_yOff) :
374    rectangle.y=static_cast<ssize_t>(_yOff);
375  return(rectangle);
376}
377