/*****************************************************************************/
// Copyright 2006-2007 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_rect.h#2 $ */
/* $DateTime: 2012/06/01 07:28:57 $ */
/* $Change: 832715 $ */
/* $Author: tknoll $ */
/*****************************************************************************/
#ifndef __dng_rect__
#define __dng_rect__
/*****************************************************************************/
#include "dng_exceptions.h"
#include "dng_point.h"
#include "dng_safe_arithmetic.h"
#include "dng_types.h"
#include "dng_utils.h"
/*****************************************************************************/
class dng_rect
{
public:
int32 t;
int32 l;
int32 b;
int32 r;
public:
dng_rect ()
: t (0)
, l (0)
, b (0)
, r (0)
{
}
// Constructs a dng_rect from the top-left and bottom-right corner.
// Throws an exception if the resulting height or width are too large to
// be represented as an int32. The intent of this is to protect code
// that may be computing the height or width directly from the member
// variables (instead of going through H() or W()).
dng_rect (int32 tt, int32 ll, int32 bb, int32 rr)
: t (tt)
, l (ll)
, b (bb)
, r (rr)
{
int32 dummy;
if (!SafeInt32Sub(r, l, &dummy) ||
!SafeInt32Sub(b, t, &dummy))
{
ThrowProgramError ("Overflow in dng_rect constructor");
}
}
dng_rect (uint32 h, uint32 w)
: t (0)
, l (0)
{
if (!ConvertUint32ToInt32(h, &b) ||
!ConvertUint32ToInt32(w, &r))
{
ThrowProgramError ("Overflow in dng_rect constructor");
}
}
dng_rect (const dng_point &size)
: t (0)
, l (0)
, b (size.v)
, r (size.h)
{
}
void Clear ()
{
*this = dng_rect ();
}
bool operator== (const dng_rect &rect) const;
bool operator!= (const dng_rect &rect) const
{
return !(*this == rect);
}
bool IsZero () const;
bool NotZero () const
{
return !IsZero ();
}
bool IsEmpty () const
{
return (t >= b) || (l >= r);
}
bool NotEmpty () const
{
return !IsEmpty ();
}
// Returns the width of the rectangle, or 0 if r is smaller than l.
// Throws an exception if the width is too large to be represented as
// a _signed_ int32 (even if it would fit in a uint32). This is
// consciously conservative -- there are existing uses of W() where
// the result is converted to an int32 without an overflow check, and
// we want to make sure no overflow can occur in such cases. We provide
// this check in addition to the check performed in the "two-corners"
// constructor to protect client code that produes a dng_rect with
// excessive size by initializing or modifying the member variables
// directly.
uint32 W () const
{
if (r >= l)
{
int32 width;
if (!SafeInt32Sub(r, l, &width))
{
ThrowProgramError ("Overflow computing rectangle width");
}
return static_cast<uint32>(width);
}
else
{
return 0;
}
}
// Returns the height of the rectangle, or 0 if b is smaller than t.
// Throws an exception if the height is too large to be represented as
// a _signed_ int32 (see W() for rationale).
uint32 H () const
{
if (b >= t)
{
int32 height;
if (!SafeInt32Sub(b, t, &height))
{
ThrowProgramError ("Overflow computing rectangle height");
}
return static_cast<uint32>(height);
}
else
{
return 0;
}
}
dng_point TL () const
{
return dng_point (t, l);
}
dng_point TR () const
{
return dng_point (t, r);
}
dng_point BL () const
{
return dng_point (b, l);
}
dng_point BR () const
{
return dng_point (b, r);
}
dng_point Size () const
{
return dng_point ((int32) H (), (int32) W ());
}
real64 Diagonal () const
{
return hypot ((real64) W (),
(real64) H ());
}
};
/*****************************************************************************/
class dng_rect_real64
{
public:
real64 t;
real64 l;
real64 b;
real64 r;
public:
dng_rect_real64 ()
: t (0.0)
, l (0.0)
, b (0.0)
, r (0.0)
{
}
dng_rect_real64 (real64 tt, real64 ll, real64 bb, real64 rr)
: t (tt)
, l (ll)
, b (bb)
, r (rr)
{
}
dng_rect_real64 (real64 h, real64 w)
: t (0)
, l (0)
, b (h)
, r (w)
{
}
dng_rect_real64 (const dng_point_real64 &size)
: t (0)
, l (0)
, b (size.v)
, r (size.h)
{
}
dng_rect_real64 (const dng_point_real64 &pt1,
const dng_point_real64 &pt2)
: t (Min_real64 (pt1.v, pt2.v))
, l (Min_real64 (pt1.h, pt2.h))
, b (Max_real64 (pt1.v, pt2.v))
, r (Max_real64 (pt1.h, pt2.h))
{
}
dng_rect_real64 (const dng_rect &rect)
: t ((real64) rect.t)
, l ((real64) rect.l)
, b ((real64) rect.b)
, r ((real64) rect.r)
{
}
void Clear ()
{
*this = dng_point_real64 ();
}
bool operator== (const dng_rect_real64 &rect) const;
bool operator!= (const dng_rect_real64 &rect) const
{
return !(*this == rect);
}
bool IsZero () const;
bool NotZero () const
{
return !IsZero ();
}
bool IsEmpty () const
{
return (t >= b) || (l >= r);
}
bool NotEmpty () const
{
return !IsEmpty ();
}
real64 W () const
{
return Max_real64 (r - l, 0.0);
}
real64 H () const
{
return Max_real64 (b - t, 0.0);
}
dng_point_real64 TL () const
{
return dng_point_real64 (t, l);
}
dng_point_real64 TR () const
{
return dng_point_real64 (t, r);
}
dng_point_real64 BL () const
{
return dng_point_real64 (b, l);
}
dng_point_real64 BR () const
{
return dng_point_real64 (b, r);
}
dng_point_real64 Size () const
{
return dng_point_real64 (H (), W ());
}
dng_rect Round () const
{
return dng_rect (Round_int32 (t),
Round_int32 (l),
Round_int32 (b),
Round_int32 (r));
}
real64 Diagonal () const
{
return hypot (W (), H ());
}
};
/*****************************************************************************/
dng_rect operator& (const dng_rect &a,
const dng_rect &b);
dng_rect operator| (const dng_rect &a,
const dng_rect &b);
/*****************************************************************************/
dng_rect_real64 operator& (const dng_rect_real64 &a,
const dng_rect_real64 &b);
dng_rect_real64 operator| (const dng_rect_real64 &a,
const dng_rect_real64 &b);
/*****************************************************************************/
inline dng_rect operator+ (const dng_rect &a,
const dng_point &b)
{
return dng_rect (a.t + b.v,
a.l + b.h,
a.b + b.v,
a.r + b.h);
}
/*****************************************************************************/
inline dng_rect_real64 operator+ (const dng_rect_real64 &a,
const dng_point_real64 &b)
{
return dng_rect_real64 (a.t + b.v,
a.l + b.h,
a.b + b.v,
a.r + b.h);
}
/*****************************************************************************/
inline dng_rect operator- (const dng_rect &a,
const dng_point &b)
{
return dng_rect (a.t - b.v,
a.l - b.h,
a.b - b.v,
a.r - b.h);
}
/*****************************************************************************/
inline dng_rect_real64 operator- (const dng_rect_real64 &a,
const dng_point_real64 &b)
{
return dng_rect_real64 (a.t - b.v,
a.l - b.h,
a.b - b.v,
a.r - b.h);
}
/*****************************************************************************/
inline dng_rect Transpose (const dng_rect &a)
{
return dng_rect (a.l, a.t, a.r, a.b);
}
/*****************************************************************************/
inline dng_rect_real64 Transpose (const dng_rect_real64 &a)
{
return dng_rect_real64 (a.l, a.t, a.r, a.b);
}
/*****************************************************************************/
inline void HalfRect (dng_rect &rect)
{
rect.r = rect.l + (int32) (rect.W () >> 1);
rect.b = rect.t + (int32) (rect.H () >> 1);
}
/*****************************************************************************/
inline void DoubleRect (dng_rect &rect)
{
rect.r = rect.l + (int32) (rect.W () << 1);
rect.b = rect.t + (int32) (rect.H () << 1);
}
/*****************************************************************************/
inline void InnerPadRect (dng_rect &rect,
int32 pad)
{
rect.l += pad;
rect.r -= pad;
rect.t += pad;
rect.b -= pad;
}
/*****************************************************************************/
inline void OuterPadRect (dng_rect &rect,
int32 pad)
{
InnerPadRect (rect, -pad);
}
/*****************************************************************************/
inline void InnerPadRectH (dng_rect &rect,
int32 pad)
{
rect.l += pad;
rect.r -= pad;
}
/*****************************************************************************/
inline void InnerPadRectV (dng_rect &rect,
int32 pad)
{
rect.t += pad;
rect.b -= pad;
}
/*****************************************************************************/
inline dng_rect MakeHalfRect (const dng_rect &rect)
{
dng_rect out = rect;
HalfRect (out);
return out;
}
/*****************************************************************************/
inline dng_rect MakeDoubleRect (const dng_rect &rect)
{
dng_rect out = rect;
DoubleRect (out);
return out;
}
/*****************************************************************************/
inline dng_rect MakeInnerPadRect (const dng_rect &rect,
int32 pad)
{
dng_rect out = rect;
InnerPadRect (out, pad);
return out;
}
/*****************************************************************************/
inline dng_rect MakeOuterPadRect (const dng_rect &rect,
int32 pad)
{
dng_rect out = rect;
OuterPadRect (out, pad);
return out;
}
/*****************************************************************************/
#endif
/*****************************************************************************/