1 /*
2    (c) Copyright 2001-2009  The world wide DirectFB Open Source Community (directfb.org)
3    (c) Copyright 2000-2004  Convergence (integrated media) GmbH
4 
5    All rights reserved.
6 
7    Written by Denis Oliver Kropp <dok@directfb.org>,
8               Andreas Hundt <andi@fischlustig.de>,
9               Sven Neumann <neo@directfb.org>,
10               Ville Syrjälä <syrjala@sci.fi> and
11               Claudio Ciccani <klan@users.sf.net>.
12 
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17 
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22 
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the
25    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26    Boston, MA 02111-1307, USA.
27 */
28 
29 #ifndef __DIRECTFB_UTIL_H__
30 #define __DIRECTFB_UTIL_H__
31 
32 #include <stdlib.h>
33 #include <errno.h>
34 
35 #include <directfb.h>
36 
37 #ifdef __cplusplus
38 extern "C"
39 {
40 #endif
41 
42 #include <directfb_strings.h>
43 
44 #include <direct/types.h>
45 #include <direct/debug.h>
46 
47 bool dfb_region_intersect( DFBRegion *region,
48                            int x1, int y1, int x2, int y2 );
49 
50 bool dfb_region_region_intersect( DFBRegion       *region,
51                                   const DFBRegion *clip );
52 
53 bool dfb_region_rectangle_intersect( DFBRegion          *region,
54                                      const DFBRectangle *rect );
55 
56 bool dfb_unsafe_region_intersect( DFBRegion *region,
57                                   int x1, int y1, int x2, int y2 );
58 
59 bool dfb_unsafe_region_rectangle_intersect( DFBRegion          *region,
60                                             const DFBRectangle *rect );
61 
62 bool dfb_rectangle_intersect_by_unsafe_region( DFBRectangle *rectangle,
63                                                DFBRegion    *region );
64 
65 bool dfb_rectangle_intersect_by_region( DFBRectangle    *rectangle,
66                                         const DFBRegion *region );
67 
68 bool dfb_rectangle_intersect( DFBRectangle       *rectangle,
69                               const DFBRectangle *clip );
70 
71 /* returns the result in the first rectangle */
72 void dfb_rectangle_union ( DFBRectangle       *rect1,
73                            const DFBRectangle *rect2 );
74 
75 
76 #define DFB_RECTANGLE_ASSERT(r)              \
77      do {                                    \
78           D_ASSERT( (r) != NULL );           \
79           D_ASSERT( (r)->w >= 0 );           \
80           D_ASSERT( (r)->h >= 0 );           \
81      } while (0)
82 
83 #define DFB_RECTANGLE_ASSERT_IF(r)           \
84      do {                                    \
85           if ((r) != NULL) {                 \
86                D_ASSERT( (r)->w >= 0 );      \
87                D_ASSERT( (r)->h >= 0 );      \
88           }                                  \
89      } while (0)
90 
91 #define DFB_RECTANGLE_VALS(r)                (r)->x, (r)->y, (r)->w, (r)->h
92 #define DFB_RECTANGLE_VALS_FROM_REGION(r)    (r)->x1, (r)->y1, (r)->x2-(r)->x1+1, (r)->y2-(r)->y1+1
93 #define DFB_RECTANGLE_INIT_FROM_REGION(r)    (DFBRectangle){ DFB_RECTANGLE_VALS_FROM_REGION(r) }
94 #define DFB_RECTANGLE_CONTAINS_POINT(r,X,Y)  (((X) >= (r)->x) && ((X) < (r)->x + (r)->w) && \
95                                               ((Y) >= (r)->y) && ((Y) < (r)->y + (r)->h))
96 
97 #define DFB_RECTANGLES_DEBUG_AT( Domain, rects, num )                                                         \
98      do {                                                                                                     \
99           unsigned int i;                                                                                     \
100                                                                                                               \
101           for (i=0; i<(num); i++)                                                                             \
102                D_DEBUG_AT( Domain, "  -> [%2d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS(&(rects)[i]) );      \
103      } while (0)
104 
105 
106 #define DFB_TRIANGLE_VALS(t)                 (t)->x1, (t)->y1, (t)->x2, (t)->y2, (t)->x3, (t)->y3
107 
108 #define DFB_COLORKEY_VALS(c)                 (c)->r, (c)->g, (c)->b, (c)->index
109 
110 #define DFB_REGION_CHECK(r)     \
111       ((r) != NULL &&           \
112        (r)->x1 <= (r)->x2 &&    \
113        (r)->y1 <= (r)->y2)
114 
115 #define DFB_REGION_CHECK_IF(r)  \
116       ((r) == NULL ||           \
117        ((r)->x1 <= (r)->x2 &&   \
118         (r)->y1 <= (r)->y2))
119 
120 #define DFB_REGION_ASSERT(r)                 \
121      do {                                    \
122           D_ASSERT( (r) != NULL );           \
123           D_ASSERT( (r)->x1 <= (r)->x2 );    \
124           D_ASSERT( (r)->y1 <= (r)->y2 );    \
125      } while (0)
126 
127 #define DFB_REGION_ASSERT_IF(r)                   \
128      do {                                         \
129           if ((r) != NULL) {                      \
130                D_ASSERT( (r)->x1 <= (r)->x2 );    \
131                D_ASSERT( (r)->y1 <= (r)->y2 );    \
132           }                                       \
133      } while (0)
134 
135 
136 #define DFB_REGION_VALS(r)                   (r)->x1, (r)->y1, (r)->x2, (r)->y2
137 
138 #define DFB_REGION_VALS_FROM_DIMENSION(d)    0, 0, (d)->w-1, (d)->h-1
139 #define DFB_REGION_INIT_FROM_DIMENSION(d)    (DFBRegion){ DFB_REGION_VALS_FROM_DIMENSION(d) }
140 
141 #define DFB_REGION_VALS_FROM_RECTANGLE(r)    (r)->x, (r)->y, (r)->x+(r)->w-1, (r)->y+(r)->h-1
142 #define DFB_REGION_INIT_FROM_RECTANGLE(r)    (DFBRegion){ DFB_REGION_VALS_FROM_RECTANGLE(r) }
143 
144 #define DFB_REGION_VALS_FROM_RECTANGLE_VALS(x,y,w,h)   (x), (y), (x)+(w)-1, (y)+(h)-1
145 #define DFB_REGION_INIT_FROM_RECTANGLE_VALS(x,y,w,h)   (DFBRegion){ DFB_REGION_VALS_FROM_RECTANGLE_VALS(x,y,w,h) }
146 
147 #define DFB_REGION_VALS_TRANSLATED(r,x,y)    (r)->x1 + x, (r)->y1 + y, (r)->x2 + x, (r)->y2 + y
148 #define DFB_REGION_INIT_TRANSLATED(r,x,y)    (DFBRegion){ DFB_REGION_VALS_TRANSLATED(r,x,y) }
149 
150 #define DFB_REGION_VALS_INTERSECTED(r,X1,Y1,X2,Y2)   (r)->x1 > (X1) ? (r)->x1 : (X1),      \
151                                                      (r)->y1 > (Y1) ? (r)->y1 : (Y1),      \
152                                                      (r)->x2 < (X2) ? (r)->x2 : (X2),      \
153                                                      (r)->y2 < (Y2) ? (r)->y2 : (Y2)
154 #define DFB_REGION_INIT_INTERSECTED(r,X1,Y1,X2,Y2)   (DFBRegion){ DFB_REGION_VALS_INTERSECTED(r,X1,Y1,X2,Y2) }
155 
156 
157 #define DFB_REGION_CONTAINS_POINT(r,X,Y)     (((X) >= (r)->x1) && ((X) <= (r)->x2) && \
158                                               ((Y) >= (r)->y1) && ((Y) <= (r)->y2))
159 
160 
161 #define DFB_REGIONS_DEBUG_AT( Domain, regions, num )                                                          \
162      do {                                                                                                     \
163           unsigned int i;                                                                                     \
164                                                                                                               \
165           for (i=0; i<(num); i++)                                                                             \
166                D_DEBUG_AT( Domain, "  -> [%2d] %4d,%4d-%4d,%4d\n", i, DFB_REGION_VALS(&(regions)[i]) );       \
167      } while (0)
168 
169 
dfb_rectangle_from_region(DFBRectangle * rect,const DFBRegion * region)170 static inline void dfb_rectangle_from_region( DFBRectangle    *rect,
171                                               const DFBRegion *region )
172 {
173      D_ASSERT( rect != NULL );
174 
175      DFB_REGION_ASSERT( region );
176 
177      rect->x = region->x1;
178      rect->y = region->y1;
179      rect->w = region->x2 - region->x1 + 1;
180      rect->h = region->y2 - region->y1 + 1;
181 }
182 
dfb_rectangle_from_rectangle_plus_insets(DFBRectangle * rect,const DFBRectangle * inner,const DFBInsets * insets)183 static inline void dfb_rectangle_from_rectangle_plus_insets( DFBRectangle       *rect,
184                                                              const DFBRectangle *inner,
185                                                              const DFBInsets    *insets )
186 {
187      D_ASSERT( rect != NULL );
188      D_ASSERT( insets != NULL );
189 
190      DFB_RECTANGLE_ASSERT( inner );
191 
192      rect->x = inner->x - insets->l;
193      rect->y = inner->y - insets->t;
194      rect->w = inner->w + insets->l + insets->r;
195      rect->h = inner->h + insets->t + insets->b;
196 }
197 
dfb_region_from_rectangle(DFBRegion * region,const DFBRectangle * rect)198 static inline void dfb_region_from_rectangle( DFBRegion          *region,
199                                               const DFBRectangle *rect )
200 {
201      D_ASSERT( region != NULL );
202 
203      DFB_RECTANGLE_ASSERT( rect );
204 
205      D_ASSERT( rect->w > 0 );
206      D_ASSERT( rect->h > 0 );
207 
208      region->x1 = rect->x;
209      region->y1 = rect->y;
210      region->x2 = rect->x + rect->w - 1;
211      region->y2 = rect->y + rect->h - 1;
212 }
213 
214 void dfb_region_from_rotated( DFBRegion          *region,
215                               const DFBRegion    *from,
216                               const DFBDimension *size,
217                               int                 rotation );
218 
219 void dfb_rectangle_from_rotated( DFBRectangle       *rectangle,
220                                  const DFBRectangle *from,
221                                  const DFBDimension *size,
222                                  int                 rotation );
223 
224 void dfb_point_from_rotated_region( DFBPoint           *point,
225                                     const DFBRegion    *from,
226                                     const DFBDimension *size,
227                                     int                 rotation );
228 
dfb_rectangle_translate(DFBRectangle * rect,int dx,int dy)229 static inline void dfb_rectangle_translate( DFBRectangle *rect,
230                                             int           dx,
231                                             int           dy )
232 {
233      DFB_RECTANGLE_ASSERT( rect );
234 
235      rect->x += dx;
236      rect->y += dy;
237 }
238 
dfb_region_translate(DFBRegion * region,int dx,int dy)239 static inline void dfb_region_translate( DFBRegion *region,
240                                          int        dx,
241                                          int        dy )
242 {
243      DFB_REGION_ASSERT( region );
244 
245      region->x1 += dx;
246      region->y1 += dy;
247      region->x2 += dx;
248      region->y2 += dy;
249 }
250 
dfb_rectangle_resize(DFBRectangle * rect,int width,int height)251 static inline void dfb_rectangle_resize( DFBRectangle *rect,
252                                          int           width,
253                                          int           height )
254 {
255      DFB_RECTANGLE_ASSERT( rect );
256 
257      D_ASSERT( width >= 0 );
258      D_ASSERT( height >= 0 );
259 
260      rect->w = width;
261      rect->h = height;
262 }
263 
dfb_region_resize(DFBRegion * region,int width,int height)264 static inline void dfb_region_resize( DFBRegion *region,
265                                       int        width,
266                                       int        height )
267 {
268      DFB_REGION_ASSERT( region );
269 
270      D_ASSERT( width >= 0 );
271      D_ASSERT( height >= 0 );
272 
273      region->x2 = region->x1 + width - 1;
274      region->y2 = region->y1 + height - 1;
275 }
276 
dfb_region_intersects(const DFBRegion * region,int x1,int y1,int x2,int y2)277 static inline bool dfb_region_intersects( const DFBRegion *region,
278                                           int              x1,
279                                           int              y1,
280                                           int              x2,
281                                           int              y2 )
282 {
283      DFB_REGION_ASSERT( region );
284 
285      D_ASSERT( x1 <= x2 );
286      D_ASSERT( y1 <= y2 );
287 
288      return (region->x1 <= x2 &&
289              region->y1 <= y2 &&
290              region->x2 >= x1 &&
291              region->y2 >= y1);
292 }
293 
dfb_region_region_intersects(const DFBRegion * region,const DFBRegion * other)294 static inline bool dfb_region_region_intersects( const DFBRegion *region,
295                                                  const DFBRegion *other )
296 {
297      DFB_REGION_ASSERT( region );
298      DFB_REGION_ASSERT( other );
299 
300      return (region->x1 <= other->x2 &&
301              region->y1 <= other->y2 &&
302              region->x2 >= other->x1 &&
303              region->y2 >= other->y1);
304 }
305 
dfb_region_region_extends(const DFBRegion * a,const DFBRegion * b)306 static inline bool dfb_region_region_extends( const DFBRegion *a,
307                                               const DFBRegion *b )
308 {
309      if (a->x1 == b->x1 && a->x2 == b->x2)
310           return (a->y1 == b->y2 - 1) || (a->y2 == b->y1 - 1);
311 
312      if (a->y1 == b->y1 && a->y2 == b->y2)
313           return (a->x1 == b->x2 - 1) || (a->x2 == b->x1 - 1);
314 
315      return false;
316 }
317 
dfb_region_region_union(DFBRegion * region,const DFBRegion * other)318 static inline void dfb_region_region_union( DFBRegion       *region,
319                                             const DFBRegion *other )
320 {
321      DFB_REGION_ASSERT( region );
322      DFB_REGION_ASSERT( other );
323 
324      if (region->x1 > other->x1)
325           region->x1 = other->x1;
326 
327      if (region->y1 > other->y1)
328           region->y1 = other->y1;
329 
330      if (region->x2 < other->x2)
331           region->x2 = other->x2;
332 
333      if (region->y2 < other->y2)
334           region->y2 = other->y2;
335 }
336 
dfb_rectangle_region_intersects(const DFBRectangle * rect,const DFBRegion * region)337 static inline bool dfb_rectangle_region_intersects( const DFBRectangle *rect,
338                                                     const DFBRegion    *region )
339 {
340      DFB_RECTANGLE_ASSERT( rect );
341 
342      DFB_REGION_ASSERT( region );
343 
344      return (rect->x <= region->x2 &&
345              rect->y <= region->y2 &&
346              rect->x + rect->w > region->x1 &&
347              rect->y + rect->h > region->y1);
348 }
349 
dfb_region_clip(DFBRegion * region,int x1,int y1,int x2,int y2)350 static inline void dfb_region_clip( DFBRegion *region,
351                                     int        x1,
352                                     int        y1,
353                                     int        x2,
354                                     int        y2 )
355 {
356      DFB_REGION_ASSERT( region );
357 
358      D_ASSERT( dfb_region_intersects( region, x1, y1, x2, y2 ) );
359 
360      if (region->x1 < x1)
361           region->x1 = x1;
362 
363      if (region->y1 < y1)
364           region->y1 = y1;
365 
366      if (region->x2 > x2)
367           region->x2 = x2;
368 
369      if (region->y2 > y2)
370           region->y2 = y2;
371 }
372 
dfb_rectangle_subtract(DFBRectangle * rect,const DFBInsets * insets)373 static inline void dfb_rectangle_subtract( DFBRectangle    *rect,
374                                            const DFBInsets *insets )
375 {
376      D_ASSERT( rect != NULL );
377      D_ASSERT( insets != NULL );
378 
379      rect->x += insets->l;
380      rect->y += insets->t;
381      rect->w -= insets->l + insets->r;
382      rect->h -= insets->t + insets->b;
383 
384      if (rect->w <= 0 || rect->h <= 0)
385           rect->w = rect->h = 0;
386 }
387 
388 
389 /*
390  * Compute line segment intersection.
391  * Return true if intersection point exists within the given segment.
392  */
393 bool dfb_line_segment_intersect( const DFBRegion *line,
394                                  const DFBRegion *seg,
395                                  int             *x,
396                                  int             *y );
397 
398 
399 /*
400  * Copied declaration of DFBPixelFormatName from directfb_strings.h
401  */
402 extern const struct DFBPixelFormatName dfb_pixelformat_names[];
403 
404 
405 const char *dfb_input_event_type_name ( DFBInputEventType     type );
406 const char *dfb_pixelformat_name      ( DFBSurfacePixelFormat format );
407 const char *dfb_window_event_type_name( DFBWindowEventType    type );
408 
409 
410 
411 typedef struct {
412      int        magic;
413 
414      DFBRegion *regions;
415      int        max_regions;
416      int        num_regions;
417 
418      DFBRegion  bounding;
419 } DFBUpdates;
420 
421 #define DFB_UPDATES_ASSERT(updates)                                        \
422      do {                                                                  \
423           D_MAGIC_ASSERT( updates, DFBUpdates );                           \
424           D_ASSERT( (updates)->regions != NULL );                          \
425           D_ASSERT( (updates)->max_regions > 0 );                          \
426           D_ASSERT( (updates)->num_regions <= (updates)->max_regions );    \
427      } while (0)
428 
429 
430 void dfb_updates_init( DFBUpdates      *updates,
431                        DFBRegion       *regions,
432                        int              max_regions );
433 
434 void dfb_updates_add ( DFBUpdates      *updates,
435                        const DFBRegion *region );
436 
437 void dfb_updates_stat( DFBUpdates      *updates,
438                        int             *ret_total,
439                        int             *ret_bounding );
440 
441 void dfb_updates_get_rectangles( DFBUpdates   *updates,
442                                  DFBRectangle *ret_rects,
443                                  int          *ret_num );
444 
445 static inline void
dfb_updates_add_rect(DFBUpdates * updates,int x,int y,int w,int h)446 dfb_updates_add_rect( DFBUpdates      *updates,
447                       int              x,
448                       int              y,
449                       int              w,
450                       int              h )
451 {
452      DFBRegion region = DFB_REGION_INIT_FROM_RECTANGLE_VALS( x, y, w, h );
453 
454      dfb_updates_add( updates, &region );
455 }
456 
457 static inline void
dfb_updates_reset(DFBUpdates * updates)458 dfb_updates_reset( DFBUpdates *updates )
459 {
460      D_MAGIC_ASSERT( updates, DFBUpdates );
461 
462      updates->num_regions = 0;
463 }
464 
465 static inline void
dfb_updates_deinit(DFBUpdates * updates)466 dfb_updates_deinit( DFBUpdates *updates )
467 {
468      D_MAGIC_ASSERT( updates, DFBUpdates );
469 
470      D_MAGIC_CLEAR( updates );
471 }
472 
473 #ifdef __cplusplus
474 }
475 #endif
476 
477 #endif
478