File indexing completed on 2025-01-19 03:55:13
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 #ifndef __dng_rect__ 0010 #define __dng_rect__ 0011 0012 /*****************************************************************************/ 0013 0014 #include "dng_exceptions.h" 0015 #include "dng_point.h" 0016 #include "dng_safe_arithmetic.h" 0017 #include "dng_types.h" 0018 #include "dng_utils.h" 0019 0020 /*****************************************************************************/ 0021 0022 class dng_rect 0023 { 0024 0025 public: 0026 0027 int32 t; 0028 int32 l; 0029 int32 b; 0030 int32 r; 0031 0032 public: 0033 0034 dng_rect () 0035 : t (0) 0036 , l (0) 0037 , b (0) 0038 , r (0) 0039 { 0040 } 0041 0042 // Constructs a dng_rect from the top-left and bottom-right corner. 0043 // Throws an exception if the resulting height or width are too large 0044 // to be represented as an int32. The intent of this is to protect 0045 // code that may be computing the height or width directly from the 0046 // member variables (instead of going through H() or W()). 0047 0048 dng_rect (int32 tt, int32 ll, int32 bb, int32 rr) 0049 : t (tt) 0050 , l (ll) 0051 , b (bb) 0052 , r (rr) 0053 { 0054 0055 int32 dummy; 0056 0057 if (!SafeInt32Sub (r, l, &dummy) || 0058 !SafeInt32Sub (b, t, &dummy)) 0059 { 0060 ThrowProgramError ("Overflow in dng_rect constructor"); 0061 } 0062 0063 } 0064 0065 dng_rect (uint32 h, uint32 w) 0066 : t (0) 0067 , l (0) 0068 { 0069 0070 if (!ConvertUint32ToInt32 (h, &b) || 0071 !ConvertUint32ToInt32 (w, &r)) 0072 { 0073 ThrowProgramError ("Overflow in dng_rect constructor"); 0074 } 0075 0076 } 0077 0078 dng_rect (const dng_point &size) 0079 : t (0) 0080 , l (0) 0081 , b (size.v) 0082 , r (size.h) 0083 { 0084 } 0085 0086 void Clear () 0087 { 0088 *this = dng_rect (); 0089 } 0090 0091 bool operator== (const dng_rect &rect) const; 0092 0093 bool operator!= (const dng_rect &rect) const 0094 { 0095 return !(*this == rect); 0096 } 0097 0098 bool IsZero () const; 0099 0100 bool NotZero () const 0101 { 0102 return !IsZero (); 0103 } 0104 0105 bool IsEmpty () const 0106 { 0107 return (t >= b) || (l >= r); 0108 } 0109 0110 bool NotEmpty () const 0111 { 0112 return !IsEmpty (); 0113 } 0114 0115 // Returns the width of the rectangle, or 0 if r is smaller than l. 0116 // Throws an exception if the width is too large to be represented as 0117 // a _signed_ int32 (even if it would fit in a uint32). This is 0118 // consciously conservative -- there are existing uses of W() where 0119 // the result is converted to an int32 without an overflow check, and 0120 // we want to make sure no overflow can occur in such cases. We 0121 // provide this check in addition to the check performed in the 0122 // "two-corners" constructor to protect client code that produes a 0123 // dng_rect with excessive size by initializing or modifying the 0124 // member variables directly. 0125 0126 uint32 W () const 0127 { 0128 0129 if (r >= l) 0130 { 0131 0132 int32 width; 0133 0134 if (!SafeInt32Sub (r, l, &width)) 0135 { 0136 ThrowProgramError ("Overflow computing rectangle width"); 0137 } 0138 0139 return static_cast<uint32> (width); 0140 0141 } 0142 0143 else 0144 { 0145 return 0; 0146 } 0147 0148 } 0149 0150 // Returns the height of the rectangle, or 0 if b is smaller than t. 0151 // Throws an exception if the height is too large to be represented as 0152 // a _signed_ int32 (see W() for rationale). 0153 0154 uint32 H () const 0155 { 0156 0157 if (b >= t) 0158 { 0159 0160 int32 height; 0161 0162 if (!SafeInt32Sub (b, t, &height)) 0163 { 0164 ThrowProgramError ("Overflow computing rectangle height"); 0165 } 0166 0167 return static_cast<uint32> (height); 0168 0169 } 0170 0171 else 0172 { 0173 return 0; 0174 } 0175 0176 } 0177 0178 dng_point TL () const 0179 { 0180 return dng_point (t, l); 0181 } 0182 0183 dng_point TR () const 0184 { 0185 return dng_point (t, r); 0186 } 0187 0188 dng_point BL () const 0189 { 0190 return dng_point (b, l); 0191 } 0192 0193 dng_point BR () const 0194 { 0195 return dng_point (b, r); 0196 } 0197 0198 dng_point Size () const 0199 { 0200 return dng_point ((int32) H (), (int32) W ()); 0201 } 0202 0203 uint32 LongSide () const 0204 { 0205 return Max_uint32 (W (), H ()); 0206 } 0207 0208 uint32 ShortSide () const 0209 { 0210 return Min_uint32 (W (), H ()); 0211 } 0212 0213 real64 Diagonal () const 0214 { 0215 return hypot ((real64) W (), 0216 (real64) H ()); 0217 } 0218 0219 }; 0220 0221 /*****************************************************************************/ 0222 0223 class dng_rect_real64 0224 { 0225 0226 public: 0227 0228 real64 t; 0229 real64 l; 0230 real64 b; 0231 real64 r; 0232 0233 public: 0234 0235 dng_rect_real64 () 0236 : t (0.0) 0237 , l (0.0) 0238 , b (0.0) 0239 , r (0.0) 0240 { 0241 } 0242 0243 dng_rect_real64 (real64 tt, real64 ll, real64 bb, real64 rr) 0244 : t (tt) 0245 , l (ll) 0246 , b (bb) 0247 , r (rr) 0248 { 0249 } 0250 0251 dng_rect_real64 (real64 h, real64 w) 0252 : t (0) 0253 , l (0) 0254 , b (h) 0255 , r (w) 0256 { 0257 } 0258 0259 dng_rect_real64 (const dng_point_real64 &size) 0260 : t (0) 0261 , l (0) 0262 , b (size.v) 0263 , r (size.h) 0264 { 0265 } 0266 0267 dng_rect_real64 (const dng_point_real64 &pt1, 0268 const dng_point_real64 &pt2) 0269 : t (Min_real64 (pt1.v, pt2.v)) 0270 , l (Min_real64 (pt1.h, pt2.h)) 0271 , b (Max_real64 (pt1.v, pt2.v)) 0272 , r (Max_real64 (pt1.h, pt2.h)) 0273 { 0274 } 0275 0276 dng_rect_real64 (const dng_rect &rect) 0277 : t ((real64) rect.t) 0278 , l ((real64) rect.l) 0279 , b ((real64) rect.b) 0280 , r ((real64) rect.r) 0281 { 0282 } 0283 0284 void Clear () 0285 { 0286 *this = dng_point_real64 (); 0287 } 0288 0289 bool operator== (const dng_rect_real64 &rect) const; 0290 0291 bool operator!= (const dng_rect_real64 &rect) const 0292 { 0293 return !(*this == rect); 0294 } 0295 0296 bool IsZero () const; 0297 0298 bool NotZero () const 0299 { 0300 return !IsZero (); 0301 } 0302 0303 bool IsEmpty () const 0304 { 0305 return (t >= b) || (l >= r); 0306 } 0307 0308 bool NotEmpty () const 0309 { 0310 return !IsEmpty (); 0311 } 0312 0313 real64 W () const 0314 { 0315 return Max_real64 (r - l, 0.0); 0316 } 0317 0318 real64 H () const 0319 { 0320 return Max_real64 (b - t, 0.0); 0321 } 0322 0323 dng_point_real64 TL () const 0324 { 0325 return dng_point_real64 (t, l); 0326 } 0327 0328 dng_point_real64 TR () const 0329 { 0330 return dng_point_real64 (t, r); 0331 } 0332 0333 dng_point_real64 BL () const 0334 { 0335 return dng_point_real64 (b, l); 0336 } 0337 0338 dng_point_real64 BR () const 0339 { 0340 return dng_point_real64 (b, r); 0341 } 0342 0343 dng_point_real64 Size () const 0344 { 0345 return dng_point_real64 (H (), W ()); 0346 } 0347 0348 dng_rect Round () const 0349 { 0350 return dng_rect (Round_int32 (t), 0351 Round_int32 (l), 0352 Round_int32 (b), 0353 Round_int32 (r)); 0354 } 0355 0356 real64 LongSide () const 0357 { 0358 return Max_real64 (W (), H ()); 0359 } 0360 0361 real64 ShortSide () const 0362 { 0363 return Min_real64 (W (), H ()); 0364 } 0365 0366 real64 Diagonal () const 0367 { 0368 return hypot (W (), H ()); 0369 } 0370 0371 dng_point_real64 Center () const 0372 { 0373 return dng_point_real64 ((t + b) * 0.5, 0374 (l + r) * 0.5); 0375 } 0376 0377 }; 0378 0379 /*****************************************************************************/ 0380 0381 dng_rect operator& (const dng_rect &a, 0382 const dng_rect &b); 0383 0384 dng_rect operator| (const dng_rect &a, 0385 const dng_rect &b); 0386 0387 /*****************************************************************************/ 0388 0389 dng_rect_real64 operator& (const dng_rect_real64 &a, 0390 const dng_rect_real64 &b); 0391 0392 dng_rect_real64 operator| (const dng_rect_real64 &a, 0393 const dng_rect_real64 &b); 0394 0395 /*****************************************************************************/ 0396 0397 inline dng_rect operator+ (const dng_rect &a, 0398 const dng_point &b) 0399 { 0400 0401 return dng_rect (a.t + b.v, 0402 a.l + b.h, 0403 a.b + b.v, 0404 a.r + b.h); 0405 0406 } 0407 0408 /*****************************************************************************/ 0409 0410 inline dng_rect_real64 operator+ (const dng_rect_real64 &a, 0411 const dng_point_real64 &b) 0412 { 0413 0414 return dng_rect_real64 (a.t + b.v, 0415 a.l + b.h, 0416 a.b + b.v, 0417 a.r + b.h); 0418 0419 } 0420 0421 /*****************************************************************************/ 0422 0423 inline dng_rect operator- (const dng_rect &a, 0424 const dng_point &b) 0425 { 0426 0427 return dng_rect (a.t - b.v, 0428 a.l - b.h, 0429 a.b - b.v, 0430 a.r - b.h); 0431 0432 } 0433 0434 /*****************************************************************************/ 0435 0436 inline dng_rect_real64 operator- (const dng_rect_real64 &a, 0437 const dng_point_real64 &b) 0438 { 0439 0440 return dng_rect_real64 (a.t - b.v, 0441 a.l - b.h, 0442 a.b - b.v, 0443 a.r - b.h); 0444 0445 } 0446 0447 /*****************************************************************************/ 0448 0449 inline dng_rect Transpose (const dng_rect &a) 0450 { 0451 0452 return dng_rect (a.l, a.t, a.r, a.b); 0453 0454 } 0455 0456 /*****************************************************************************/ 0457 0458 inline dng_rect_real64 Transpose (const dng_rect_real64 &a) 0459 { 0460 0461 return dng_rect_real64 (a.l, a.t, a.r, a.b); 0462 0463 } 0464 0465 /*****************************************************************************/ 0466 0467 inline void HalfRect (dng_rect &rect) 0468 { 0469 0470 rect.r = rect.l + (int32) (rect.W () >> 1); 0471 rect.b = rect.t + (int32) (rect.H () >> 1); 0472 0473 } 0474 0475 /*****************************************************************************/ 0476 0477 inline void DoubleRect (dng_rect &rect) 0478 { 0479 0480 rect.r = rect.l + (int32) (rect.W () << 1); 0481 rect.b = rect.t + (int32) (rect.H () << 1); 0482 0483 } 0484 0485 /*****************************************************************************/ 0486 0487 inline void InnerPadRect (dng_rect &rect, 0488 int32 pad) 0489 { 0490 0491 rect.l += pad; 0492 rect.r -= pad; 0493 rect.t += pad; 0494 rect.b -= pad; 0495 0496 } 0497 0498 /*****************************************************************************/ 0499 0500 inline void OuterPadRect (dng_rect &rect, 0501 int32 pad) 0502 { 0503 0504 InnerPadRect (rect, -pad); 0505 0506 } 0507 0508 /*****************************************************************************/ 0509 0510 inline void InnerPadRectH (dng_rect &rect, 0511 int32 pad) 0512 { 0513 0514 rect.l += pad; 0515 rect.r -= pad; 0516 0517 } 0518 0519 /*****************************************************************************/ 0520 0521 inline void InnerPadRectV (dng_rect &rect, 0522 int32 pad) 0523 { 0524 0525 rect.t += pad; 0526 rect.b -= pad; 0527 0528 } 0529 0530 /*****************************************************************************/ 0531 0532 inline dng_rect MakeHalfRect (const dng_rect &rect) 0533 { 0534 0535 dng_rect out = rect; 0536 0537 HalfRect (out); 0538 0539 return out; 0540 0541 } 0542 0543 /*****************************************************************************/ 0544 0545 inline dng_rect MakeDoubleRect (const dng_rect &rect) 0546 { 0547 0548 dng_rect out = rect; 0549 0550 DoubleRect (out); 0551 0552 return out; 0553 0554 } 0555 0556 /*****************************************************************************/ 0557 0558 inline dng_rect MakeInnerPadRect (const dng_rect &rect, 0559 int32 pad) 0560 { 0561 0562 dng_rect out = rect; 0563 0564 InnerPadRect (out, pad); 0565 0566 return out; 0567 0568 } 0569 0570 /*****************************************************************************/ 0571 0572 inline dng_rect MakeOuterPadRect (const dng_rect &rect, 0573 int32 pad) 0574 { 0575 0576 dng_rect out = rect; 0577 0578 OuterPadRect (out, pad); 0579 0580 return out; 0581 0582 } 0583 0584 /*****************************************************************************/ 0585 0586 inline dng_rect_real64 MakeOuterPadRect (const dng_rect_real64 &rect, 0587 const real64 pad) 0588 { 0589 0590 dng_rect_real64 result = rect; 0591 0592 result.t -= pad; 0593 result.l -= pad; 0594 result.b += pad; 0595 result.r += pad; 0596 0597 return result; 0598 0599 } 0600 0601 /*****************************************************************************/ 0602 0603 inline dng_rect_real64 Lerp (const dng_rect_real64 &a, 0604 const dng_rect_real64 &b, 0605 const real64 t) 0606 { 0607 0608 return dng_rect_real64 (Lerp_real64 (a.t, b.t, t), 0609 Lerp_real64 (a.l, b.l, t), 0610 Lerp_real64 (a.b, b.b, t), 0611 Lerp_real64 (a.r, b.r, t)); 0612 0613 } 0614 0615 /*****************************************************************************/ 0616 0617 dng_rect_real64 Bounds (const dng_point_real64 &a, 0618 const dng_point_real64 &b, 0619 const dng_point_real64 &c, 0620 const dng_point_real64 &d); 0621 0622 /*****************************************************************************/ 0623 0624 #endif 0625 0626 /*****************************************************************************/