1 /*****************************************************************************/ 2 // Copyright 2006-2007 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_rect.h#2 $ */ 10 /* $DateTime: 2012/06/01 07:28:57 $ */ 11 /* $Change: 832715 $ */ 12 /* $Author: tknoll $ */ 13 14 /*****************************************************************************/ 15 16 #ifndef __dng_rect__ 17 #define __dng_rect__ 18 19 /*****************************************************************************/ 20 21 #include "dng_exceptions.h" 22 #include "dng_point.h" 23 #include "dng_safe_arithmetic.h" 24 #include "dng_types.h" 25 #include "dng_utils.h" 26 27 /*****************************************************************************/ 28 29 class dng_rect 30 { 31 32 public: 33 34 int32 t; 35 int32 l; 36 int32 b; 37 int32 r; 38 39 public: 40 41 dng_rect () 42 : t (0) 43 , l (0) 44 , b (0) 45 , r (0) 46 { 47 } 48 49 // Constructs a dng_rect from the top-left and bottom-right corner. 50 // Throws an exception if the resulting height or width are too large to 51 // be represented as an int32. The intent of this is to protect code 52 // that may be computing the height or width directly from the member 53 // variables (instead of going through H() or W()). 54 dng_rect (int32 tt, int32 ll, int32 bb, int32 rr) 55 : t (tt) 56 , l (ll) 57 , b (bb) 58 , r (rr) 59 { 60 int32 dummy; 61 if (!SafeInt32Sub(r, l, &dummy) || 62 !SafeInt32Sub(b, t, &dummy)) 63 { 64 ThrowProgramError ("Overflow in dng_rect constructor"); 65 } 66 } 67 68 dng_rect (uint32 h, uint32 w) 69 : t (0) 70 , l (0) 71 { 72 if (!ConvertUint32ToInt32(h, &b) || 73 !ConvertUint32ToInt32(w, &r)) 74 { 75 ThrowProgramError ("Overflow in dng_rect constructor"); 76 } 77 } 78 79 dng_rect (const dng_point &size) 80 : t (0) 81 , l (0) 82 , b (size.v) 83 , r (size.h) 84 { 85 } 86 87 void Clear () 88 { 89 *this = dng_rect (); 90 } 91 92 bool operator== (const dng_rect &rect) const; 93 94 bool operator!= (const dng_rect &rect) const 95 { 96 return !(*this == rect); 97 } 98 99 bool IsZero () const; 100 101 bool NotZero () const 102 { 103 return !IsZero (); 104 } 105 106 bool IsEmpty () const 107 { 108 return (t >= b) || (l >= r); 109 } 110 111 bool NotEmpty () const 112 { 113 return !IsEmpty (); 114 } 115 116 // Returns the width of the rectangle, or 0 if r is smaller than l. 117 // Throws an exception if the width is too large to be represented as 118 // a _signed_ int32 (even if it would fit in a uint32). This is 119 // consciously conservative -- there are existing uses of W() where 120 // the result is converted to an int32 without an overflow check, and 121 // we want to make sure no overflow can occur in such cases. We provide 122 // this check in addition to the check performed in the "two-corners" 123 // constructor to protect client code that produes a dng_rect with 124 // excessive size by initializing or modifying the member variables 125 // directly. 126 uint32 W () const 127 { 128 if (r >= l) 129 { 130 int32 width; 131 if (!SafeInt32Sub(r, l, &width)) 132 { 133 ThrowProgramError ("Overflow computing rectangle width"); 134 } 135 return static_cast<uint32>(width); 136 } 137 else 138 { 139 return 0; 140 } 141 } 142 143 // Returns the height of the rectangle, or 0 if b is smaller than t. 144 // Throws an exception if the height is too large to be represented as 145 // a _signed_ int32 (see W() for rationale). 146 uint32 H () const 147 { 148 if (b >= t) 149 { 150 int32 height; 151 if (!SafeInt32Sub(b, t, &height)) 152 { 153 ThrowProgramError ("Overflow computing rectangle height"); 154 } 155 return static_cast<uint32>(height); 156 } 157 else 158 { 159 return 0; 160 } 161 } 162 163 dng_point TL () const 164 { 165 return dng_point (t, l); 166 } 167 168 dng_point TR () const 169 { 170 return dng_point (t, r); 171 } 172 173 dng_point BL () const 174 { 175 return dng_point (b, l); 176 } 177 178 dng_point BR () const 179 { 180 return dng_point (b, r); 181 } 182 183 dng_point Size () const 184 { 185 return dng_point ((int32) H (), (int32) W ()); 186 } 187 188 real64 Diagonal () const 189 { 190 return hypot ((real64) W (), 191 (real64) H ()); 192 } 193 194 }; 195 196 /*****************************************************************************/ 197 198 class dng_rect_real64 199 { 200 201 public: 202 203 real64 t; 204 real64 l; 205 real64 b; 206 real64 r; 207 208 public: 209 210 dng_rect_real64 () 211 : t (0.0) 212 , l (0.0) 213 , b (0.0) 214 , r (0.0) 215 { 216 } 217 218 dng_rect_real64 (real64 tt, real64 ll, real64 bb, real64 rr) 219 : t (tt) 220 , l (ll) 221 , b (bb) 222 , r (rr) 223 { 224 } 225 226 dng_rect_real64 (real64 h, real64 w) 227 : t (0) 228 , l (0) 229 , b (h) 230 , r (w) 231 { 232 } 233 234 dng_rect_real64 (const dng_point_real64 &size) 235 : t (0) 236 , l (0) 237 , b (size.v) 238 , r (size.h) 239 { 240 } 241 242 dng_rect_real64 (const dng_point_real64 &pt1, 243 const dng_point_real64 &pt2) 244 : t (Min_real64 (pt1.v, pt2.v)) 245 , l (Min_real64 (pt1.h, pt2.h)) 246 , b (Max_real64 (pt1.v, pt2.v)) 247 , r (Max_real64 (pt1.h, pt2.h)) 248 { 249 } 250 251 dng_rect_real64 (const dng_rect &rect) 252 : t ((real64) rect.t) 253 , l ((real64) rect.l) 254 , b ((real64) rect.b) 255 , r ((real64) rect.r) 256 { 257 } 258 259 void Clear () 260 { 261 *this = dng_point_real64 (); 262 } 263 264 bool operator== (const dng_rect_real64 &rect) const; 265 266 bool operator!= (const dng_rect_real64 &rect) const 267 { 268 return !(*this == rect); 269 } 270 271 bool IsZero () const; 272 273 bool NotZero () const 274 { 275 return !IsZero (); 276 } 277 278 bool IsEmpty () const 279 { 280 return (t >= b) || (l >= r); 281 } 282 283 bool NotEmpty () const 284 { 285 return !IsEmpty (); 286 } 287 288 real64 W () const 289 { 290 return Max_real64 (r - l, 0.0); 291 } 292 293 real64 H () const 294 { 295 return Max_real64 (b - t, 0.0); 296 } 297 298 dng_point_real64 TL () const 299 { 300 return dng_point_real64 (t, l); 301 } 302 303 dng_point_real64 TR () const 304 { 305 return dng_point_real64 (t, r); 306 } 307 308 dng_point_real64 BL () const 309 { 310 return dng_point_real64 (b, l); 311 } 312 313 dng_point_real64 BR () const 314 { 315 return dng_point_real64 (b, r); 316 } 317 318 dng_point_real64 Size () const 319 { 320 return dng_point_real64 (H (), W ()); 321 } 322 323 dng_rect Round () const 324 { 325 return dng_rect (Round_int32 (t), 326 Round_int32 (l), 327 Round_int32 (b), 328 Round_int32 (r)); 329 } 330 331 real64 Diagonal () const 332 { 333 return hypot (W (), H ()); 334 } 335 336 }; 337 338 /*****************************************************************************/ 339 340 dng_rect operator& (const dng_rect &a, 341 const dng_rect &b); 342 343 dng_rect operator| (const dng_rect &a, 344 const dng_rect &b); 345 346 /*****************************************************************************/ 347 348 dng_rect_real64 operator& (const dng_rect_real64 &a, 349 const dng_rect_real64 &b); 350 351 dng_rect_real64 operator| (const dng_rect_real64 &a, 352 const dng_rect_real64 &b); 353 354 /*****************************************************************************/ 355 356 inline dng_rect operator+ (const dng_rect &a, 357 const dng_point &b) 358 { 359 360 return dng_rect (a.t + b.v, 361 a.l + b.h, 362 a.b + b.v, 363 a.r + b.h); 364 365 } 366 367 /*****************************************************************************/ 368 369 inline dng_rect_real64 operator+ (const dng_rect_real64 &a, 370 const dng_point_real64 &b) 371 { 372 373 return dng_rect_real64 (a.t + b.v, 374 a.l + b.h, 375 a.b + b.v, 376 a.r + b.h); 377 378 } 379 380 /*****************************************************************************/ 381 382 inline dng_rect operator- (const dng_rect &a, 383 const dng_point &b) 384 { 385 386 return dng_rect (a.t - b.v, 387 a.l - b.h, 388 a.b - b.v, 389 a.r - b.h); 390 391 } 392 393 /*****************************************************************************/ 394 395 inline dng_rect_real64 operator- (const dng_rect_real64 &a, 396 const dng_point_real64 &b) 397 { 398 399 return dng_rect_real64 (a.t - b.v, 400 a.l - b.h, 401 a.b - b.v, 402 a.r - b.h); 403 404 } 405 406 /*****************************************************************************/ 407 408 inline dng_rect Transpose (const dng_rect &a) 409 { 410 411 return dng_rect (a.l, a.t, a.r, a.b); 412 413 } 414 415 /*****************************************************************************/ 416 417 inline dng_rect_real64 Transpose (const dng_rect_real64 &a) 418 { 419 420 return dng_rect_real64 (a.l, a.t, a.r, a.b); 421 422 } 423 424 /*****************************************************************************/ 425 426 inline void HalfRect (dng_rect &rect) 427 { 428 429 rect.r = rect.l + (int32) (rect.W () >> 1); 430 rect.b = rect.t + (int32) (rect.H () >> 1); 431 432 } 433 434 /*****************************************************************************/ 435 436 inline void DoubleRect (dng_rect &rect) 437 { 438 439 rect.r = rect.l + (int32) (rect.W () << 1); 440 rect.b = rect.t + (int32) (rect.H () << 1); 441 442 } 443 444 /*****************************************************************************/ 445 446 inline void InnerPadRect (dng_rect &rect, 447 int32 pad) 448 { 449 450 rect.l += pad; 451 rect.r -= pad; 452 rect.t += pad; 453 rect.b -= pad; 454 455 } 456 457 /*****************************************************************************/ 458 459 inline void OuterPadRect (dng_rect &rect, 460 int32 pad) 461 { 462 463 InnerPadRect (rect, -pad); 464 465 } 466 467 /*****************************************************************************/ 468 469 inline void InnerPadRectH (dng_rect &rect, 470 int32 pad) 471 { 472 473 rect.l += pad; 474 rect.r -= pad; 475 476 } 477 478 /*****************************************************************************/ 479 480 inline void InnerPadRectV (dng_rect &rect, 481 int32 pad) 482 { 483 484 rect.t += pad; 485 rect.b -= pad; 486 487 } 488 489 /*****************************************************************************/ 490 491 inline dng_rect MakeHalfRect (const dng_rect &rect) 492 { 493 494 dng_rect out = rect; 495 496 HalfRect (out); 497 498 return out; 499 500 } 501 502 /*****************************************************************************/ 503 504 inline dng_rect MakeDoubleRect (const dng_rect &rect) 505 { 506 507 dng_rect out = rect; 508 509 DoubleRect (out); 510 511 return out; 512 513 } 514 515 /*****************************************************************************/ 516 517 inline dng_rect MakeInnerPadRect (const dng_rect &rect, 518 int32 pad) 519 { 520 521 dng_rect out = rect; 522 523 InnerPadRect (out, pad); 524 525 return out; 526 527 } 528 529 /*****************************************************************************/ 530 531 inline dng_rect MakeOuterPadRect (const dng_rect &rect, 532 int32 pad) 533 { 534 535 dng_rect out = rect; 536 537 OuterPadRect (out, pad); 538 539 return out; 540 541 } 542 543 /*****************************************************************************/ 544 545 #endif 546 547 /*****************************************************************************/ 548