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 /*****************************************************************************/