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, ®ion );
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