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