Geometry.cpp revision e8f35322e8a3c6a53282eaf812d7a3bd69ba133f
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_.xOff() == right_.xOff()) &&
36    (left_.yOff() == right_.yOff()));
37}
38
39MagickPPExport int Magick::operator != (const Magick::Geometry& left_,
40  const Magick::Geometry& right_)
41{
42  return(!(left_ == right_));
43}
44
45MagickPPExport int Magick::operator > (const Magick::Geometry& left_,
46  const Magick::Geometry& right_)
47{
48  return(!(left_ < right_) && (left_ != right_));
49}
50
51MagickPPExport int Magick::operator < (const Magick::Geometry& left_,
52  const Magick::Geometry& right_)
53{
54  return((left_.width()*left_.height()) < (right_.width()*right_.height()));
55}
56
57MagickPPExport int Magick::operator >= (const Magick::Geometry& left_,
58  const Magick::Geometry& right_)
59{
60  return((left_ > right_) || (left_ == right_));
61}
62
63MagickPPExport int Magick::operator <= (const Magick::Geometry& left_,
64  const Magick::Geometry& right_ )
65{
66  return((left_ < right_) || (left_ == right_));
67}
68
69Magick::Geometry::Geometry(void)
70  : _width(0),
71    _height(0),
72    _xOff(0),
73    _yOff(0),
74    _isValid(false),
75    _percent(false),
76    _aspect(false),
77    _greater(false),
78    _less(false),
79    _fillArea(false),
80    _limitPixels(false)
81{
82}
83
84Magick::Geometry::Geometry(const char *geometry_)
85  : _width(0),
86    _height(0),
87    _xOff(0),
88    _yOff(0),
89    _isValid(false),
90    _percent(false),
91    _aspect(false),
92    _greater(false),
93    _less(false),
94    _fillArea(false),
95    _limitPixels(false)
96{
97  *this=geometry_; // Use assignment operator
98}
99
100Magick::Geometry::Geometry(const Geometry &geometry_)
101  : _width(geometry_._width),
102    _height(geometry_._height),
103    _xOff(geometry_._xOff),
104    _yOff(geometry_._yOff),
105    _isValid(geometry_._isValid),
106    _percent(geometry_._percent),
107    _aspect(geometry_._aspect),
108    _greater(geometry_._greater),
109    _less(geometry_._less),
110    _fillArea(geometry_._fillArea),
111    _limitPixels(geometry_._limitPixels)
112{
113}
114
115Magick::Geometry::Geometry(const std::string &geometry_)
116  : _width(0),
117    _height(0),
118    _xOff(0),
119    _yOff(0),
120    _isValid(false),
121    _percent(false),
122    _aspect(false),
123    _greater(false),
124    _less(false),
125    _fillArea(false),
126    _limitPixels(false)
127{
128  *this=geometry_; // Use assignment operator
129}
130
131Magick::Geometry::Geometry(size_t width_,size_t height_,ssize_t xOff_,
132  ssize_t yOff_)
133  : _width(width_),
134    _height(height_),
135    _xOff(xOff_),
136    _yOff(yOff_),
137    _isValid(true),
138    _percent(false),
139    _aspect(false),
140    _greater(false),
141    _less(false),
142    _fillArea(false),
143    _limitPixels(false)
144{
145}
146
147Magick::Geometry::~Geometry(void)
148{
149}
150
151const Magick::Geometry& Magick::Geometry::operator=(const char *geometry_)
152{
153  *this=std::string(geometry_);
154  return(*this);
155}
156
157Magick::Geometry& Magick::Geometry::operator=(const Geometry &geometry_)
158{
159  // If not being set to ourself
160  if (this != &geometry_)
161    {
162      _width=geometry_._width;
163      _height=geometry_._height;
164      _xOff=geometry_._xOff;
165      _yOff=geometry_._yOff;
166      _isValid=geometry_._isValid;
167      _percent=geometry_._percent;
168      _aspect=geometry_._aspect;
169      _greater=geometry_._greater;
170      _less=geometry_._less;
171      _fillArea=geometry_._fillArea;
172      _limitPixels=geometry_._limitPixels;
173    }
174  return(*this);
175}
176
177const Magick::Geometry& Magick::Geometry::operator=(
178  const std::string &geometry_)
179{
180  char
181    geom[MaxTextExtent];
182
183  char
184    *pageptr;
185
186  ssize_t
187    flags,
188    x = 0,
189    y = 0;
190
191  size_t
192    height_val=0,
193    width_val=0;
194
195  // If argument does not start with digit, presume that it is a
196  // page-size specification that needs to be converted to an
197  // equivalent geometry specification using PostscriptGeometry()
198  (void) CopyMagickString(geom,geometry_.c_str(),MaxTextExtent);
199  if (geom[0] != '-' && geom[0] != '+' && geom[0] != 'x' &&
200      !isdigit(static_cast<int>(geom[0])))
201    {
202      pageptr=GetPageGeometry(geom);
203      if (pageptr != 0)
204        {
205          (void) CopyMagickString(geom,pageptr,MaxTextExtent);
206          pageptr=(char *) RelinquishMagickMemory(pageptr);
207        }
208    }
209
210  flags=GetGeometry(geom,&x,&y,&width_val,&height_val);
211
212  if (flags == NoValue)
213    {
214      // Total failure!
215      *this=Geometry();
216      isValid(false);
217      return(*this);
218    }
219
220  if ((flags & WidthValue) != 0)
221    {
222      _width=width_val;
223      isValid(true);
224    }
225
226  if ((flags & HeightValue) != 0)
227    {
228      _height=height_val;
229      isValid(true);
230    }
231
232  if ((flags & XValue) != 0)
233    {
234      _xOff=static_cast<ssize_t>(x);
235      isValid(true);
236    }
237
238  if ((flags & YValue) != 0)
239    {
240      _yOff=static_cast<ssize_t>(y);
241      isValid(true);
242    }
243
244  if ((flags & XNegative) != 0)
245    _xOff=-_xOff;
246
247  if ((flags & YNegative) != 0)
248    _yOff=-_yOff;
249
250  if ((flags & PercentValue) != 0)
251    _percent=true;
252
253  if ((flags & AspectValue) != 0)
254    _aspect=true;
255
256  if ((flags & LessValue) != 0)
257    _less=true;
258
259  if ((flags & GreaterValue) != 0)
260    _greater=true;
261
262  if ((flags & MinimumValue) != 0)
263    _fillArea=true;
264
265  if ((flags & AreaValue) != 0)
266    _limitPixels=true;
267
268  return(*this);
269}
270
271Magick::Geometry::operator std::string() const
272{
273  char
274    buffer[MaxTextExtent];
275
276  string
277    geometry;
278
279  if (!isValid())
280    throwExceptionExplicit(OptionError,"Invalid geometry argument");
281
282  if (_width)
283    {
284      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _width);
285      geometry+=buffer;
286    }
287
288  if (_height)
289    {
290      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _height);
291      geometry+='x';
292      geometry+=buffer;
293    }
294
295  if (_xOff || _yOff)
296    {
297      if (_xOff < 0)
298        geometry+='-';
299      else
300        geometry+='+';
301
302      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _xOff);
303      geometry+=buffer;
304
305      if (_yOff < 0)
306        geometry+='-';
307      else
308        geometry+='+';
309
310      FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _yOff);
311      geometry+=buffer;
312    }
313
314  if (_percent)
315    geometry+='%';
316
317  if (_aspect)
318    geometry+='!';
319
320  if (_greater)
321    geometry+='>';
322
323  if (_less)
324    geometry+='<';
325
326  if (_fillArea)
327    geometry+='^';
328
329  if (_limitPixels)
330    geometry+='@';
331
332  return(geometry);
333}
334
335Magick::Geometry::Geometry(const MagickCore::RectangleInfo &rectangle_)
336  : _width(static_cast<size_t>(rectangle_.width)),
337    _height(static_cast<size_t>(rectangle_.height)),
338    _xOff(static_cast<ssize_t>(rectangle_.x)),
339    _yOff(static_cast<ssize_t>(rectangle_.y)),
340    _isValid(true),
341    _percent(false),
342    _aspect(false),
343    _greater(false),
344    _less(false),
345    _fillArea(false),
346    _limitPixels(false)
347{
348}
349
350const Magick::Geometry& Magick::Geometry::operator=(
351  const MagickCore::RectangleInfo &rectangle_)
352{
353  _width=static_cast<size_t>(rectangle_.width),
354  _height=static_cast<size_t>(rectangle_.height),
355  _xOff=static_cast<ssize_t>(rectangle_.x),
356  _yOff=static_cast<ssize_t>(rectangle_.y),
357  _isValid=true;
358  return(*this);
359}
360
361Magick::Geometry::operator MagickCore::RectangleInfo() const
362{
363  RectangleInfo rectangle;
364  rectangle.width=_width;
365  rectangle.height=_height;
366  rectangle.x=_xOff;
367  rectangle.y=_yOff;
368  return(rectangle);
369}
370
371void Magick::Geometry::aspect(bool aspect_)
372{
373  _aspect=aspect_;
374}
375
376bool Magick::Geometry::aspect(void) const
377{
378  return(_aspect);
379}
380
381void Magick::Geometry::fillArea(bool fillArea_)
382{
383  _fillArea=fillArea_;
384}
385
386bool Magick::Geometry::fillArea(void) const
387{
388  return(_fillArea);
389}
390
391void Magick::Geometry::greater(bool greater_)
392{
393  _greater=greater_;
394}
395
396bool Magick::Geometry::greater(void) const
397{
398  return(_greater);
399}
400
401void Magick::Geometry::height(size_t height_)
402{
403  _height=height_;
404}
405
406size_t Magick::Geometry::height(void) const
407{
408  return(_height);
409}
410
411void Magick::Geometry::isValid(bool isValid_)
412{
413  _isValid=isValid_;
414}
415
416bool Magick::Geometry::isValid(void) const
417{
418  return(_isValid);
419}
420
421void Magick::Geometry::less(bool less_)
422{
423  _less=less_;
424}
425
426bool Magick::Geometry::less(void) const
427{
428  return(_less);
429}
430
431void Magick::Geometry::limitPixels(bool limitPixels_)
432{
433  _limitPixels=limitPixels_;
434}
435
436bool Magick::Geometry::limitPixels(void) const
437{
438  return(_limitPixels);
439}
440
441void Magick::Geometry::width(size_t width_)
442{
443  _width=width_;
444  isValid(true);
445}
446
447void Magick::Geometry::percent(bool percent_)
448{
449  _percent = percent_;
450}
451
452bool Magick::Geometry::percent(void) const
453{
454  return(_percent);
455}
456
457size_t Magick::Geometry::width(void) const
458{
459  return(_width);
460}
461
462void Magick::Geometry::xOff(::ssize_t xOff_)
463{
464  _xOff=xOff_;
465}
466
467::ssize_t Magick::Geometry::xOff(void) const
468{
469  return(_xOff);
470}
471
472inline void Magick::Geometry::yOff(::ssize_t yOff_)
473{
474  _yOff=yOff_;
475}
476
477::ssize_t Magick::Geometry::yOff(void) const
478{
479  return(_yOff);
480}
481
482MagickPPExport int Magick::operator == (const Magick::Point& left_,
483  const Magick::Point& right_)
484{
485  return((left_.x() == right_.x()) &&
486    (left_.y() == right_.y()));
487}
488
489MagickPPExport int Magick::operator != (const Magick::Point& left_,
490  const Magick::Point& right_)
491{
492  return(!(left_ == right_));
493}
494
495Magick::Point::Point(void)
496  : _x(0.0),
497    _y(0.0)
498{
499}
500
501Magick::Point::Point(const char *point_)
502  : _x(0.0),
503    _y(0.0)
504{
505  *this=point_; // Use assignment operator
506}
507
508Magick::Point::Point(const Point &point_)
509  : _x(point_._x),
510    _y(point_._y)
511{
512}
513
514Magick::Point::Point(const std::string &point_)
515  : _x(0.0),
516    _y(0.0)
517{
518  *this=point_; // Use assignment operator
519}
520
521Magick::Point::Point(double x_,double y_)
522  : _x(x_),
523    _y(y_)
524{
525}
526
527Magick::Point::Point(double xy_)
528  : _x(xy_),
529    _y(xy_)
530{
531}
532
533Magick::Point::~Point(void)
534{
535}
536
537const Magick::Point& Magick::Point::operator=(const char *point_)
538{
539  MagickCore::GeometryInfo
540    geometry_info;
541
542  MagickCore::MagickStatusType
543    flags;
544
545  flags=ParseGeometry(point_,&geometry_info);
546  _x=geometry_info.rho;
547  _y=geometry_info.sigma;
548  if ((flags & MagickCore::SigmaValue) == 0)
549    _y=_x;
550  return(*this);
551}
552
553const Magick::Point& Magick::Point::operator=(const double xy_)
554{
555  _x=xy_;
556  _y=xy_;
557  return(*this);
558}
559
560Magick::Point& Magick::Point::operator=(const Point &point_)
561{
562  // If not being set to ourself
563  if (this != &point_)
564    {
565      _x=point_._x;
566      _y=point_._y;
567    }
568  return(*this);
569}
570
571const Magick::Point& Magick::Point::operator=(const std::string &point_)
572{
573  *this=point_.c_str();
574  return(*this);
575}
576
577Magick::Point::operator std::string() const
578{
579  char
580    buffer[MaxTextExtent];
581
582  string
583    point;
584
585  if (_x < 0.0)
586    point+='-';
587  else
588    point+='+';
589
590  FormatLocaleString(buffer,MaxTextExtent,"%.20g",_x);
591  point+=buffer;
592
593  if (_y < 0.0)
594    point+='x-';
595  else
596    point+='x+';
597
598  FormatLocaleString(buffer,MaxTextExtent,"%.20g",(double) _y);
599  point+=buffer;
600
601  return(point);
602}
603
604bool Magick::Point::isValid(void) const
605{
606  return(_x > 0.0);
607}
608
609double Magick::Point::x(void) const
610{
611  return(_x);
612}
613
614double Magick::Point::y(void) const
615{
616  return(_y);
617}