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