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 using namespace std;
20
21 #include "Magick++/Geometry.h"
22 #include "Magick++/Exception.h"
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 }