1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
4 // Copyright Dirk Lemstra 2014-2015
5 //
6 // Geometry implementation
7 //
8 
9 #define MAGICKCORE_IMPLEMENTATION  1
10 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
11 
12 #include "Magick++/Include.h"
13 #include <string>
14 #include <ctype.h> // for isdigit
15 #if !defined(MAGICKCORE_WINDOWS_SUPPORT)
16 #include <strings.h>
17 #endif
18 
19 #include "Magick++/Geometry.h"
20 #include "Magick++/Exception.h"
21 
22 using namespace std;
23 
operator ==(const Magick::Geometry & left_,const Magick::Geometry & right_)24 MagickPPExport int Magick::operator == (const Magick::Geometry& left_,
25   const Magick::Geometry& right_)
26 {
27   return((left_.aspect() == right_.aspect()) &&
28     (left_.fillArea() == right_.fillArea()) &&
29     (left_.greater() == right_.greater()) &&
30     (left_.height() == right_.height()) &&
31     (left_.isValid() == right_.isValid()) &&
32     (left_.less() == right_.less()) &&
33     (left_.limitPixels() == right_.limitPixels()) &&
34     (left_.percent() == right_.percent()) &&
35     (left_.width() == right_.width()) &&
36     (left_.xOff() == right_.xOff()) &&
37     (left_.yOff() == right_.yOff()));
38 }
39 
operator !=(const Magick::Geometry & left_,const Magick::Geometry & right_)40 MagickPPExport int Magick::operator != (const Magick::Geometry& left_,
41   const Magick::Geometry& right_)
42 {
43   return(!(left_ == right_));
44 }
45 
operator >(const Magick::Geometry & left_,const Magick::Geometry & right_)46 MagickPPExport int Magick::operator > (const Magick::Geometry& left_,
47   const Magick::Geometry& right_)
48 {
49   return(!(left_ < right_) && (left_ != right_));
50 }
51 
operator <(const Magick::Geometry & left_,const Magick::Geometry & right_)52 MagickPPExport int Magick::operator < (const Magick::Geometry& left_,
53   const Magick::Geometry& right_)
54 {
55   return((left_.width()*left_.height()) < (right_.width()*right_.height()));
56 }
57 
operator >=(const Magick::Geometry & left_,const Magick::Geometry & right_)58 MagickPPExport int Magick::operator >= (const Magick::Geometry& left_,
59   const Magick::Geometry& right_)
60 {
61   return((left_ > right_) || (left_ == right_));
62 }
63 
operator <=(const Magick::Geometry & left_,const Magick::Geometry & right_)64 MagickPPExport int Magick::operator <= (const Magick::Geometry& left_,
65   const Magick::Geometry& right_ )
66 {
67   return((left_ < right_) || (left_ == right_));
68 }
69 
Geometry(void)70 Magick::Geometry::Geometry(void)
71   : _width(0),
72     _height(0),
73     _xOff(0),
74     _yOff(0),
75     _isValid(false),
76     _percent(false),
77     _aspect(false),
78     _greater(false),
79     _less(false),
80     _fillArea(false),
81     _limitPixels(false)
82 {
83 }
84 
Geometry(const char * geometry_)85 Magick::Geometry::Geometry(const char *geometry_)
86   : _width(0),
87     _height(0),
88     _xOff(0),
89     _yOff(0),
90     _isValid(false),
91     _percent(false),
92     _aspect(false),
93     _greater(false),
94     _less(false),
95     _fillArea(false),
96     _limitPixels(false)
97 {
98   *this=geometry_; // Use assignment operator
99 }
100 
Geometry(const Geometry & geometry_)101 Magick::Geometry::Geometry(const Geometry &geometry_)
102   : _width(geometry_._width),
103     _height(geometry_._height),
104     _xOff(geometry_._xOff),
105     _yOff(geometry_._yOff),
106     _isValid(geometry_._isValid),
107     _percent(geometry_._percent),
108     _aspect(geometry_._aspect),
109     _greater(geometry_._greater),
110     _less(geometry_._less),
111     _fillArea(geometry_._fillArea),
112     _limitPixels(geometry_._limitPixels)
113 {
114 }
115 
Geometry(const std::string & geometry_)116 Magick::Geometry::Geometry(const std::string &geometry_)
117   : _width(0),
118     _height(0),
119     _xOff(0),
120     _yOff(0),
121     _isValid(false),
122     _percent(false),
123     _aspect(false),
124     _greater(false),
125     _less(false),
126     _fillArea(false),
127     _limitPixels(false)
128 {
129   *this=geometry_; // Use assignment operator
130 }
131 
Geometry(size_t width_,size_t height_,ssize_t xOff_,ssize_t yOff_)132 Magick::Geometry::Geometry(size_t width_,size_t height_,ssize_t xOff_,
133   ssize_t yOff_)
134   : _width(width_),
135     _height(height_),
136     _xOff(xOff_),
137     _yOff(yOff_),
138     _isValid(true),
139     _percent(false),
140     _aspect(false),
141     _greater(false),
142     _less(false),
143     _fillArea(false),
144     _limitPixels(false)
145 {
146 }
147 
~Geometry(void)148 Magick::Geometry::~Geometry(void)
149 {
150 }
151 
operator =(const char * geometry_)152 const Magick::Geometry& Magick::Geometry::operator=(const char *geometry_)
153 {
154   *this=std::string(geometry_);
155   return(*this);
156 }
157 
operator =(const Geometry & geometry_)158 Magick::Geometry& Magick::Geometry::operator=(const Geometry &geometry_)
159 {
160   // If not being set to ourself
161   if (this != &geometry_)
162     {
163       _width=geometry_._width;
164       _height=geometry_._height;
165       _xOff=geometry_._xOff;
166       _yOff=geometry_._yOff;
167       _isValid=geometry_._isValid;
168       _percent=geometry_._percent;
169       _aspect=geometry_._aspect;
170       _greater=geometry_._greater;
171       _less=geometry_._less;
172       _fillArea=geometry_._fillArea;
173       _limitPixels=geometry_._limitPixels;
174     }
175   return(*this);
176 }
177 
operator =(const std::string & geometry_)178 const Magick::Geometry& Magick::Geometry::operator=(
179   const std::string &geometry_)
180 {
181   char
182     geom[MagickPathExtent];
183 
184   char
185     *pageptr;
186 
187   ssize_t
188     flags,
189     x = 0,
190     y = 0;
191 
192   size_t
193     height_val=0,
194     width_val=0;
195 
196   // If argument does not start with digit, presume that it is a
197   // page-size specification that needs to be converted to an
198   // equivalent geometry specification using PostscriptGeometry()
199   (void) CopyMagickString(geom,geometry_.c_str(),MagickPathExtent);
200   if (geom[0] != '-' && geom[0] != '+' && geom[0] != 'x' &&
201       !isdigit(static_cast<int>(geom[0])))
202     {
203       pageptr=GetPageGeometry(geom);
204       if (pageptr != 0)
205         {
206           (void) CopyMagickString(geom,pageptr,MagickPathExtent);
207           pageptr=(char *) RelinquishMagickMemory(pageptr);
208         }
209     }
210 
211   flags=GetGeometry(geom,&x,&y,&width_val,&height_val);
212 
213   if (flags == NoValue)
214     {
215       // Total failure!
216       *this=Geometry();
217       isValid(false);
218       return(*this);
219     }
220 
221   if ((flags & WidthValue) != 0)
222     {
223       _width=width_val;
224       isValid(true);
225     }
226 
227   if ((flags & HeightValue) != 0)
228     {
229       _height=height_val;
230       isValid(true);
231     }
232 
233   if ((flags & XValue) != 0)
234     {
235       _xOff=static_cast<ssize_t>(x);
236       isValid(true);
237     }
238 
239   if ((flags & YValue) != 0)
240     {
241       _yOff=static_cast<ssize_t>(y);
242       isValid(true);
243     }
244 
245   if ((flags & PercentValue) != 0)
246     _percent=true;
247 
248   if ((flags & AspectValue) != 0)
249     _aspect=true;
250 
251   if ((flags & LessValue) != 0)
252     _less=true;
253 
254   if ((flags & GreaterValue) != 0)
255     _greater=true;
256 
257   if ((flags & MinimumValue) != 0)
258     _fillArea=true;
259 
260   if ((flags & AreaValue) != 0)
261     _limitPixels=true;
262 
263   return(*this);
264 }
265 
operator std::string() const266 Magick::Geometry::operator std::string() const
267 {
268   char
269     buffer[MagickPathExtent];
270 
271   std::string
272     geometry;
273 
274   if (!isValid())
275     throwExceptionExplicit(MagickCore::OptionError,
276       "Invalid geometry argument");
277 
278   if (_width)
279     {
280       FormatLocaleString(buffer,MagickPathExtent,"%.20g",(double) _width);
281       geometry+=buffer;
282     }
283 
284   if (_height)
285     {
286       FormatLocaleString(buffer,MagickPathExtent,"%.20g",(double) _height);
287       geometry+='x';
288       geometry+=buffer;
289     }
290 
291   if (_xOff || _yOff)
292     {
293       if (_xOff >= 0)
294         geometry+='+';
295 
296       FormatLocaleString(buffer,MagickPathExtent,"%.20g",(double) _xOff);
297       geometry+=buffer;
298 
299       if (_yOff >= 0)
300         geometry+='+';
301 
302       FormatLocaleString(buffer,MagickPathExtent,"%.20g",(double) _yOff);
303       geometry+=buffer;
304     }
305 
306   if (_percent)
307     geometry+='%';
308 
309   if (_aspect)
310     geometry+='!';
311 
312   if (_greater)
313     geometry+='>';
314 
315   if (_less)
316     geometry+='<';
317 
318   if (_fillArea)
319     geometry+='^';
320 
321   if (_limitPixels)
322     geometry+='@';
323 
324   return(geometry);
325 }
326 
aspect(bool aspect_)327 void Magick::Geometry::aspect(bool aspect_)
328 {
329   _aspect=aspect_;
330 }
331 
aspect(void) const332 bool Magick::Geometry::aspect(void) const
333 {
334   return(_aspect);
335 }
336 
fillArea(bool fillArea_)337 void Magick::Geometry::fillArea(bool fillArea_)
338 {
339   _fillArea=fillArea_;
340 }
341 
fillArea(void) const342 bool Magick::Geometry::fillArea(void) const
343 {
344   return(_fillArea);
345 }
346 
greater(bool greater_)347 void Magick::Geometry::greater(bool greater_)
348 {
349   _greater=greater_;
350 }
351 
greater(void) const352 bool Magick::Geometry::greater(void) const
353 {
354   return(_greater);
355 }
356 
height(size_t height_)357 void Magick::Geometry::height(size_t height_)
358 {
359   _height=height_;
360 }
361 
height(void) const362 size_t Magick::Geometry::height(void) const
363 {
364   return(_height);
365 }
366 
isValid(bool isValid_)367 void Magick::Geometry::isValid(bool isValid_)
368 {
369   _isValid=isValid_;
370 }
371 
isValid(void) const372 bool Magick::Geometry::isValid(void) const
373 {
374   return(_isValid);
375 }
376 
less(bool less_)377 void Magick::Geometry::less(bool less_)
378 {
379   _less=less_;
380 }
381 
less(void) const382 bool Magick::Geometry::less(void) const
383 {
384   return(_less);
385 }
386 
limitPixels(bool limitPixels_)387 void Magick::Geometry::limitPixels(bool limitPixels_)
388 {
389   _limitPixels=limitPixels_;
390 }
391 
limitPixels(void) const392 bool Magick::Geometry::limitPixels(void) const
393 {
394   return(_limitPixels);
395 }
396 
width(size_t width_)397 void Magick::Geometry::width(size_t width_)
398 {
399   _width=width_;
400   isValid(true);
401 }
402 
percent(bool percent_)403 void Magick::Geometry::percent(bool percent_)
404 {
405   _percent = percent_;
406 }
407 
percent(void) const408 bool Magick::Geometry::percent(void) const
409 {
410   return(_percent);
411 }
412 
width(void) const413 size_t Magick::Geometry::width(void) const
414 {
415   return(_width);
416 }
417 
xOff(::ssize_t xOff_)418 void Magick::Geometry::xOff(::ssize_t xOff_)
419 {
420   _xOff=xOff_;
421 }
422 
xOff(void) const423 ::ssize_t Magick::Geometry::xOff(void) const
424 {
425   return(_xOff);
426 }
427 
yOff(::ssize_t yOff_)428 void Magick::Geometry::yOff(::ssize_t yOff_)
429 {
430   _yOff=yOff_;
431 }
432 
yOff(void) const433 ::ssize_t Magick::Geometry::yOff(void) const
434 {
435   return(_yOff);
436 }
437 
Geometry(const MagickCore::RectangleInfo & rectangle_)438 Magick::Geometry::Geometry(const MagickCore::RectangleInfo &rectangle_)
439   : _width(static_cast<size_t>(rectangle_.width)),
440     _height(static_cast<size_t>(rectangle_.height)),
441     _xOff(static_cast<ssize_t>(rectangle_.x)),
442     _yOff(static_cast<ssize_t>(rectangle_.y)),
443     _isValid(true),
444     _percent(false),
445     _aspect(false),
446     _greater(false),
447     _less(false),
448     _fillArea(false),
449     _limitPixels(false)
450 {
451 }
452 
operator =(const MagickCore::RectangleInfo & rectangle_)453 const Magick::Geometry& Magick::Geometry::operator=(
454   const MagickCore::RectangleInfo &rectangle_)
455 {
456   _width=static_cast<size_t>(rectangle_.width),
457   _height=static_cast<size_t>(rectangle_.height),
458   _xOff=static_cast<ssize_t>(rectangle_.x),
459   _yOff=static_cast<ssize_t>(rectangle_.y),
460   _isValid=true;
461   return(*this);
462 }
463 
operator MagickCore::RectangleInfo() const464 Magick::Geometry::operator MagickCore::RectangleInfo() const
465 {
466   RectangleInfo rectangle;
467   rectangle.width=_width;
468   rectangle.height=_height;
469   rectangle.x=_xOff;
470   rectangle.y=_yOff;
471   return(rectangle);
472 }
473 
operator ==(const Magick::Offset & left_,const Magick::Offset & right_)474 MagickPPExport int Magick::operator == (const Magick::Offset& left_,
475   const Magick::Offset& right_)
476 {
477   return((left_.x() == right_.x()) &&
478     (left_.y() == right_.y()));
479 }
480 
operator !=(const Magick::Offset & left_,const Magick::Offset & right_)481 MagickPPExport int Magick::operator != (const Magick::Offset& left_,
482   const Magick::Offset& right_)
483 {
484   return(!(left_ == right_));
485 }
486 
Offset(void)487 Magick::Offset::Offset(void)
488   : _x(0),
489     _y(0)
490 {
491 }
492 
Offset(const char * offset_)493 Magick::Offset::Offset(const char *offset_)
494   : _x(0),
495     _y(0)
496 {
497   *this=offset_; // Use assignment operator
498 }
499 
Offset(const Offset & offset_)500 Magick::Offset::Offset(const Offset &offset_)
501   : _x(offset_._x),
502     _y(offset_._y)
503 {
504 }
505 
Offset(const std::string & offset_)506 Magick::Offset::Offset(const std::string &offset_)
507   : _x(0),
508     _y(0)
509 {
510   *this=offset_; // Use assignment operator
511 }
512 
Offset(ssize_t x_,ssize_t y_)513 Magick::Offset::Offset(ssize_t x_,ssize_t y_)
514   : _x(x_),
515     _y(y_)
516 {
517 }
518 
~Offset(void)519 Magick::Offset::~Offset(void)
520 {
521 }
522 
operator =(const char * offset_)523 const Magick::Offset& Magick::Offset::operator=(const char *offset_)
524 {
525   MagickCore::GeometryInfo
526     geometry_info;
527 
528   MagickCore::MagickStatusType
529     flags;
530 
531   flags=ParseGeometry(offset_,&geometry_info);
532   _x=geometry_info.rho;
533   _y=geometry_info.sigma;
534   if ((flags & MagickCore::SigmaValue) == 0)
535     _y=_x;
536   return(*this);
537 }
538 
operator =(const Offset & offset_)539 Magick::Offset& Magick::Offset::operator=(const Offset &offset_)
540 {
541   // If not being set to ourself
542   if (this != &offset_)
543     {
544       _x=offset_._x;
545       _y=offset_._y;
546     }
547   return(*this);
548 }
549 
operator =(const std::string & offset_)550 const Magick::Offset& Magick::Offset::operator=(const std::string &offset_)
551 {
552   *this=offset_.c_str();
553   return(*this);
554 }
555 
x(void) const556 ssize_t Magick::Offset::x(void) const
557 {
558   return(_x);
559 }
560 
y(void) const561 ssize_t Magick::Offset::y(void) const
562 {
563   return(_y);
564 }
565 
operator MagickCore::OffsetInfo() const566 Magick::Offset::operator MagickCore::OffsetInfo() const
567 {
568   OffsetInfo offset;
569   offset.x=_x;
570   offset.y=_y;
571   return(offset);
572 }
573 
operator ==(const Magick::Point & left_,const Magick::Point & right_)574 MagickPPExport int Magick::operator == (const Magick::Point& left_,
575   const Magick::Point& right_)
576 {
577   return((left_.x() == right_.x()) &&
578     (left_.y() == right_.y()));
579 }
580 
operator !=(const Magick::Point & left_,const Magick::Point & right_)581 MagickPPExport int Magick::operator != (const Magick::Point& left_,
582   const Magick::Point& right_)
583 {
584   return(!(left_ == right_));
585 }
586 
Point(void)587 Magick::Point::Point(void)
588   : _x(0.0),
589     _y(0.0)
590 {
591 }
592 
Point(const char * point_)593 Magick::Point::Point(const char *point_)
594   : _x(0.0),
595     _y(0.0)
596 {
597   *this=point_; // Use assignment operator
598 }
599 
Point(const Point & point_)600 Magick::Point::Point(const Point &point_)
601   : _x(point_._x),
602     _y(point_._y)
603 {
604 }
605 
Point(const std::string & point_)606 Magick::Point::Point(const std::string &point_)
607   : _x(0.0),
608     _y(0.0)
609 {
610   *this=point_; // Use assignment operator
611 }
612 
Point(double x_,double y_)613 Magick::Point::Point(double x_,double y_)
614   : _x(x_),
615     _y(y_)
616 {
617 }
618 
Point(double xy_)619 Magick::Point::Point(double xy_)
620   : _x(xy_),
621     _y(xy_)
622 {
623 }
624 
~Point(void)625 Magick::Point::~Point(void)
626 {
627 }
628 
operator =(const char * point_)629 const Magick::Point& Magick::Point::operator=(const char *point_)
630 {
631   MagickCore::GeometryInfo
632     geometry_info;
633 
634   MagickCore::MagickStatusType
635     flags;
636 
637   flags=ParseGeometry(point_,&geometry_info);
638   _x=geometry_info.rho;
639   _y=geometry_info.sigma;
640   if ((flags & MagickCore::SigmaValue) == 0)
641     _y=_x;
642   return(*this);
643 }
644 
operator =(const double xy_)645 const Magick::Point& Magick::Point::operator=(const double xy_)
646 {
647   _x=xy_;
648   _y=xy_;
649   return(*this);
650 }
651 
operator =(const Point & point_)652 Magick::Point& Magick::Point::operator=(const Point &point_)
653 {
654   // If not being set to ourself
655   if (this != &point_)
656     {
657       _x=point_._x;
658       _y=point_._y;
659     }
660   return(*this);
661 }
662 
operator =(const std::string & point_)663 const Magick::Point& Magick::Point::operator=(const std::string &point_)
664 {
665   *this=point_.c_str();
666   return(*this);
667 }
668 
operator std::string() const669 Magick::Point::operator std::string() const
670 {
671   char
672     buffer[MagickPathExtent];
673 
674   string
675     point;
676 
677   if (_x < 0.0)
678     point+="-";
679   else
680     point+="+";
681 
682   FormatLocaleString(buffer,MagickPathExtent,"%.20g",_x);
683   point+=buffer;
684 
685   if (_y < 0.0)
686     point+="x-";
687   else
688     point+="x+";
689 
690   FormatLocaleString(buffer,MagickPathExtent,"%.20g",(double) _y);
691   point+=buffer;
692 
693   return(point);
694 }
695 
isValid(void) const696 bool Magick::Point::isValid(void) const
697 {
698   return(_x > 0.0);
699 }
700 
x(void) const701 double Magick::Point::x(void) const
702 {
703   return(_x);
704 }
705 
y(void) const706 double Magick::Point::y(void) const
707 {
708   return(_y);
709 }