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