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