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