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 
dng_rect()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()).
dng_rect(int32 tt,int32 ll,int32 bb,int32 rr)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 
dng_rect(uint32 h,uint32 w)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 
dng_rect(const dng_point & size)79 		dng_rect (const dng_point &size)
80 			:	t (0)
81 			,	l (0)
82 			,	b (size.v)
83 			,	r (size.h)
84 			{
85 			}
86 
Clear()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 
NotZero()101 		bool NotZero () const
102 			{
103 			return !IsZero ();
104 			}
105 
IsEmpty()106 		bool IsEmpty () const
107 			{
108 			return (t >= b) || (l >= r);
109 			}
110 
NotEmpty()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.
W()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).
H()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 
TL()163 		dng_point TL () const
164 			{
165 			return dng_point (t, l);
166 			}
167 
TR()168 		dng_point TR () const
169 			{
170 			return dng_point (t, r);
171 			}
172 
BL()173 		dng_point BL () const
174 			{
175 			return dng_point (b, l);
176 			}
177 
BR()178 		dng_point BR () const
179 			{
180 			return dng_point (b, r);
181 			}
182 
Size()183 		dng_point Size () const
184 			{
185 			return dng_point ((int32) H (), (int32) W ());
186 			}
187 
Diagonal()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 
dng_rect_real64()210 		dng_rect_real64 ()
211 			:	t (0.0)
212 			,	l (0.0)
213 			,	b (0.0)
214 			,	r (0.0)
215 			{
216 			}
217 
dng_rect_real64(real64 tt,real64 ll,real64 bb,real64 rr)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 
dng_rect_real64(real64 h,real64 w)226 		dng_rect_real64 (real64 h, real64 w)
227 			:	t (0)
228 			,	l (0)
229 			,	b (h)
230 			,	r (w)
231 			{
232 			}
233 
dng_rect_real64(const dng_point_real64 & size)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 
dng_rect_real64(const dng_point_real64 & pt1,const dng_point_real64 & pt2)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 
dng_rect_real64(const dng_rect & rect)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 
Clear()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 
NotZero()273 		bool NotZero () const
274 			{
275 			return !IsZero ();
276 			}
277 
IsEmpty()278 		bool IsEmpty () const
279 			{
280 			return (t >= b) || (l >= r);
281 			}
282 
NotEmpty()283 		bool NotEmpty () const
284 			{
285 			return !IsEmpty ();
286 			}
287 
W()288 		real64 W () const
289 			{
290 			return Max_real64 (r - l, 0.0);
291 			}
292 
H()293 		real64 H () const
294 			{
295 			return Max_real64 (b - t, 0.0);
296 			}
297 
TL()298 		dng_point_real64 TL () const
299 			{
300 			return dng_point_real64 (t, l);
301 			}
302 
TR()303 		dng_point_real64 TR () const
304 			{
305 			return dng_point_real64 (t, r);
306 			}
307 
BL()308 		dng_point_real64 BL () const
309 			{
310 			return dng_point_real64 (b, l);
311 			}
312 
BR()313 		dng_point_real64 BR () const
314 			{
315 			return dng_point_real64 (b, r);
316 			}
317 
Size()318 		dng_point_real64 Size () const
319 			{
320 			return dng_point_real64 (H (), W ());
321 			}
322 
Round()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 
Diagonal()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 
Transpose(const dng_rect & a)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 
Transpose(const dng_rect_real64 & a)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 
HalfRect(dng_rect & rect)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 
DoubleRect(dng_rect & rect)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 
InnerPadRect(dng_rect & rect,int32 pad)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 
OuterPadRect(dng_rect & rect,int32 pad)459 inline void OuterPadRect (dng_rect &rect,
460 						  int32 pad)
461 	{
462 
463 	InnerPadRect (rect, -pad);
464 
465 	}
466 
467 /*****************************************************************************/
468 
InnerPadRectH(dng_rect & rect,int32 pad)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 
InnerPadRectV(dng_rect & rect,int32 pad)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 
MakeHalfRect(const dng_rect & rect)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 
MakeDoubleRect(const dng_rect & rect)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 
MakeInnerPadRect(const dng_rect & rect,int32 pad)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 
MakeOuterPadRect(const dng_rect & rect,int32 pad)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