Geometry.cpp revision 641733d57df11b441146f89f9fb1929e999b5e1f
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 15using namespace std; 16 17#include "Magick++/Geometry.h" 18#include "Magick++/Exception.h" 19 20#define AbsoluteValue(x) ((x) < 0 ? -(x) : (x)) 21 22int 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 ); 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 _fillArea( false ) 89{ 90} 91 92// Assignment from C++ string 93Magick::Geometry::Geometry ( const std::string &geometry_ ) 94 : _width( 0 ), 95 _height( 0 ), 96 _xOff( 0 ), 97 _yOff( 0 ), 98 _xNegative( false ), 99 _yNegative( false ), 100 _isValid( false ), 101 _percent( false ), 102 _aspect( false ), 103 _greater( false ), 104 _less( false ), 105 _fillArea( 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 _fillArea( false ) 125{ 126 *this = geometry_; // Use assignment operator 127} 128 129// Copy constructor 130Magick::Geometry::Geometry ( const Geometry &geometry_ ) 131 : _width( geometry_._width ), 132 _height( geometry_._height ), 133 _xOff( geometry_._xOff ), 134 _yOff( geometry_._yOff ), 135 _xNegative( geometry_._xNegative ), 136 _yNegative( geometry_._yNegative ), 137 _isValid ( geometry_._isValid ), 138 _percent( geometry_._percent ), 139 _aspect( geometry_._aspect ), 140 _greater( geometry_._greater ), 141 _less( geometry_._less ), 142 _fillArea( geometry_._fillArea ) 143{ 144} 145 146// Default constructor 147Magick::Geometry::Geometry ( void ) 148 : _width( 0 ), 149 _height( 0 ), 150 _xOff( 0 ), 151 _yOff( 0 ), 152 _xNegative( false ), 153 _yNegative( false ), 154 _isValid ( false ), 155 _percent( false ), 156 _aspect( false ), 157 _greater( false ), 158 _less( false ), 159 _fillArea( false ) 160{ 161} 162 163/* virtual */ Magick::Geometry::~Geometry ( void ) 164{ 165 // Nothing to do 166} 167 168Magick::Geometry& Magick::Geometry::operator = ( const Geometry& geometry_ ) 169{ 170 // If not being set to ourself 171 if ( this != &geometry_ ) 172 { 173 _width = geometry_._width; 174 _height = geometry_._height; 175 _xOff = geometry_._xOff; 176 _yOff = geometry_._yOff; 177 _xNegative = geometry_._xNegative; 178 _yNegative = geometry_._yNegative; 179 _isValid = geometry_._isValid; 180 _percent = geometry_._percent; 181 _aspect = geometry_._aspect; 182 _greater = geometry_._greater; 183 _less = geometry_._less; 184 _fillArea = geometry_._fillArea; 185 } 186 return *this; 187} 188 189// Set value via geometry string 190/* virtual */ const Magick::Geometry& 191Magick::Geometry::operator = ( const std::string &geometry_ ) 192{ 193 char 194 geom[MaxTextExtent]; 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(),MaxTextExtent); 200 if ( geom[0] != '-' && 201 geom[0] != '+' && 202 geom[0] != 'x' && 203 !isdigit(static_cast<int>(geom[0]))) 204 { 205 char *pageptr = GetPageGeometry( geom ); 206 if ( pageptr != 0 ) 207 { 208 (void) CopyMagickString(geom,pageptr,MaxTextExtent); 209 pageptr=(char *) RelinquishMagickMemory( pageptr ); 210 } 211 } 212 213 ssize_t x = 0; 214 ssize_t y = 0; 215 size_t width_val = 0; 216 size_t height_val = 0; 217 ssize_t flags = GetGeometry (geom, &x, &y, &width_val, &height_val ); 218 219 if (flags == NoValue) 220 { 221 // Total failure! 222 *this=Geometry(); 223 isValid( false ); 224 return *this; 225 } 226 227 if ( ( flags & WidthValue ) != 0 ) 228 { 229 _width = width_val; 230 isValid( true ); 231 } 232 233 if ( ( flags & HeightValue ) != 0 ) 234 { 235 _height = height_val; 236 isValid( true ); 237 } 238 239 if ( ( flags & XValue ) != 0 ) 240 { 241 _xOff = static_cast<ssize_t>(x); 242 isValid( true ); 243 } 244 245 if ( ( flags & YValue ) != 0 ) 246 { 247 _yOff = static_cast<ssize_t>(y); 248 isValid( true ); 249 } 250 251 if ( ( flags & XNegative ) != 0 ) 252 _xNegative = true; 253 254 if ( ( flags & YNegative ) != 0 ) 255 _yNegative = true; 256 257 if ( ( flags & PercentValue ) != 0 ) 258 _percent = true; 259 260 if ( ( flags & AspectValue ) != 0 ) 261 _aspect = true; 262 263 if ( ( flags & LessValue ) != 0 ) 264 _less = true; 265 266 if ( ( flags & GreaterValue ) != 0 ) 267 _greater = true; 268 269 if ( ( flags & MinimumValue ) != 0 ) 270 _fillArea = true; 271 272 return *this; 273} 274 275 276// Set value via geometry C string 277/* virtual */ const Magick::Geometry& Magick::Geometry::operator = ( const char * geometry_ ) 278{ 279 *this = std::string(geometry_); 280 return *this; 281} 282 283// Return geometry string 284Magick::Geometry::operator std::string() const 285{ 286 if (!isValid()) 287 { 288 throwExceptionExplicit( OptionError, "Invalid geometry argument" ); 289 } 290 291 string geometry; 292 char buffer[MaxTextExtent]; 293 294 if ( _width ) 295 { 296 FormatLocaleString( buffer, MaxTextExtent, "%.20g", (double) _width ); 297 geometry += buffer; 298 } 299 300 if ( _height ) 301 { 302 FormatLocaleString( buffer, MaxTextExtent, "%.20g", (double) _height); 303 geometry += 'x'; 304 geometry += buffer; 305 } 306 307 if ( _xOff || _yOff ) 308 { 309 if ( _xNegative ) 310 geometry += '-'; 311 else 312 geometry += '+'; 313 314 FormatLocaleString( buffer, MaxTextExtent, "%.20g", (double) _xOff); 315 geometry += buffer; 316 317 if ( _yNegative ) 318 geometry += '-'; 319 else 320 geometry += '+'; 321 322 FormatLocaleString( buffer, MaxTextExtent, "%.20g", (double) _yOff); 323 geometry += buffer; 324 } 325 326 if ( _percent ) 327 geometry += '%'; 328 329 if ( _aspect ) 330 geometry += '!'; 331 332 if ( _greater ) 333 geometry += '>'; 334 335 if ( _less ) 336 geometry += '<'; 337 338 if ( _fillArea ) 339 geometry += '^'; 340 341 return geometry; 342} 343 344// Construct from RectangleInfo 345Magick::Geometry::Geometry ( const MagickCore::RectangleInfo &rectangle_ ) 346 : _width(static_cast<size_t>(rectangle_.width)), 347 _height(static_cast<size_t>(rectangle_.height)), 348 _xOff(static_cast<ssize_t>(rectangle_.x)), 349 _yOff(static_cast<ssize_t>(rectangle_.y)), 350 _xNegative(rectangle_.x < 0 ? true : false), 351 _yNegative(rectangle_.y < 0 ? true : false), 352 _isValid(true), 353 _percent(false), 354 _aspect(false), 355 _greater(false), 356 _less(false), 357 _fillArea(false) 358{ 359} 360 361// Return an ImageMagick RectangleInfo struct 362Magick::Geometry::operator MagickCore::RectangleInfo() const 363{ 364 RectangleInfo rectangle; 365 rectangle.width = _width; 366 rectangle.height = _height; 367 _xNegative ? rectangle.x = static_cast<ssize_t>(0-_xOff) : rectangle.x = static_cast<ssize_t>(_xOff); 368 _yNegative ? rectangle.y = static_cast<ssize_t>(0-_yOff) : rectangle.y = static_cast<ssize_t>(_yOff); 369 return rectangle; 370} 371