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
29class 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
198class 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
340dng_rect operator& (const dng_rect &a,
341					const dng_rect &b);
342
343dng_rect operator| (const dng_rect &a,
344					const dng_rect &b);
345
346/*****************************************************************************/
347
348dng_rect_real64 operator& (const dng_rect_real64 &a,
349						   const dng_rect_real64 &b);
350
351dng_rect_real64 operator| (const dng_rect_real64 &a,
352						   const dng_rect_real64 &b);
353
354/*****************************************************************************/
355
356inline 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
369inline 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
382inline 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
395inline 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
408inline 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
417inline 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
426inline 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
436inline 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
446inline 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
459inline void OuterPadRect (dng_rect &rect,
460						  int32 pad)
461	{
462
463	InnerPadRect (rect, -pad);
464
465	}
466
467/*****************************************************************************/
468
469inline void InnerPadRectH (dng_rect &rect,
470						   int32 pad)
471	{
472
473	rect.l += pad;
474	rect.r -= pad;
475
476	}
477
478/*****************************************************************************/
479
480inline void InnerPadRectV (dng_rect &rect,
481						   int32 pad)
482	{
483
484	rect.t += pad;
485	rect.b -= pad;
486
487	}
488
489/*****************************************************************************/
490
491inline 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
504inline 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
517inline 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
531inline 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