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