]> granicus.if.org Git - imagemagick/blob - Magick++/lib/Geometry.cpp
(no commit message)
[imagemagick] / Magick++ / lib / Geometry.cpp
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
18 using namespace std;
19
20 #include "Magick++/Geometry.h"
21 #include "Magick++/Exception.h"
22
23 #define AbsoluteValue(x)  ((x) < 0 ? -(x) : (x))
24
25 int 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 }
42 int Magick::operator != ( const Magick::Geometry& left_,
43                           const Magick::Geometry& right_ )
44 {
45   return ( ! (left_ == right_) );
46 }
47 int Magick::operator >  ( const Magick::Geometry& left_,
48                           const Magick::Geometry& right_ )
49 {
50   return ( !( left_ < right_ ) && ( left_ != right_ ) );
51 }
52 int 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 }
61 int Magick::operator >= ( const Magick::Geometry& left_,
62                           const Magick::Geometry& right_ )
63 {
64   return ( ( left_ > right_ ) || ( left_ == right_ ) );
65 }
66 int 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
73 Magick::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
94 Magick::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
112 Magick::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
129 Magick::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
145 Magick::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
165 Magick::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&
187 Magick::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
277 Magick::Geometry::operator std::string() const
278 {
279   if (!isValid())
280     {
281       throwExceptionExplicit( OptionError, "Invalid geometry argument" );
282     }
283
284   string geometry;
285   char buffer[MaxTextExtent];
286
287   if ( _width )
288     {
289       FormatMagickString( buffer, MaxTextExtent, "%.20g", (double) _width );
290       geometry += buffer;
291     }
292
293   if ( _height )
294     {
295       FormatMagickString( buffer, MaxTextExtent, "%.20g",  (double) _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, "%.20g", (double) _xOff);
308       geometry += buffer;
309
310       if ( _yNegative )
311         geometry += '-';
312       else
313         geometry += '+';
314
315       FormatMagickString( buffer, MaxTextExtent, "%.20g", (double) _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
335 Magick::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
351 Magick::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 }