cliprect.h File Reference

Rectangle clipping/dirty list. More...

#include "rect.h"

Include dependency graph for cliprect.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ClipRect
 Accumulate dirty rectangles or do window clipping Provides an instruction set for rendering/blitting dirty rectangle regions and skipping over rectangular window contents. More...

Defines

#define ClipRect_foreach(instance, iterator)   pointer_foreach_const( Rect, (instance)->dirty, (instance)->cDirty, iterator )
 Iterate cliprects.
#define ClipRect_foreach_mutable(instance, iterator)
 Iterate cliprects; count can change while we do it.

Functions

void ClipRect_init (ClipRect *self, Rect *dirty, size_t cDirty, const Rect *bounds)
 Initialize a dirty clipping list.
void ClipRect_add (ClipRect *self, const Rect *r)
 Add a dirty rectangle to dirty list Overlapped and redundant rectangles are merged. If list is filled, merges all rectangles to make more room.
void ClipRect_remove (ClipRect *self, const Rect *r)
 Remove a rectangle from dirty list to reserve a window.
Rect ClipRect_union (const ClipRect *self)
 Get union of all rectangles.
void ClipRect_merge (ClipRect *self, const ClipRect *other)
 Add all the clipped quantities from another ClipRect to this one.
void ClipRect_copy (ClipRect *self, const ClipRect *other)
 Copy all the clipped quantities from another ClipRect to this one.


Detailed Description

Rectangle clipping/dirty list.

Author:
David Mace

Definition in file cliprect.h.


Define Documentation

#define ClipRect_foreach ( instance,
iterator   )     pointer_foreach_const( Rect, (instance)->dirty, (instance)->cDirty, iterator )

Iterate cliprects.

Parameters:
instance Instance of ClipRect we're initializing
iterator Name of variable to iterate with

Definition at line 49 of file cliprect.h.

#define ClipRect_foreach_mutable ( instance,
iterator   ) 

Value:

Rect* iterator = (instance)->dirty;\
    size_t iterator##_curr;\
    for( iterator##_curr = 0; iterator##_curr < (instance)->cDirty; ++iterator##_curr, ++iterator )
Iterate cliprects; count can change while we do it.

Parameters:
instance Instance of ClipRect we're initializing
iterator Name of variable to iterate with

Definition at line 57 of file cliprect.h.


Function Documentation

void ClipRect_add ( ClipRect self,
const Rect rect 
)

Add a dirty rectangle to dirty list Overlapped and redundant rectangles are merged. If list is filled, merges all rectangles to make more room.

Parameters:
self Pointer to clip accumulator
rect New rectangle to add

Definition at line 34 of file cliprect.c.

References ClipRect_add(), RectContainsRect, RectEmpty, RectInRect, RectIntRect, and RectUnionRect.

Referenced by _GUI_Dirty_Rect(), ClipRect_add(), and ClipRect_merge().

00035 {
00036     Rect newRect = *rect;
00037     RectIntRect( newRect, self->bounds );
00038     if( !RectEmpty(newRect) )
00039     {
00040         Rect* curr = self->dirty;
00041         Rect* end = self->dirty + self->cDirty;
00042         while( curr < end )
00043         {
00044             /* Look for rectangles already containing newRect */
00045             if( RectContainsRect( *curr, newRect ) )
00046                 return;
00047             /* Look for rectangles to combine with newRect */
00048             if( RectInRect(*curr, newRect) )
00049             {
00050                 if( self->cDirty > 1 )
00051                 {
00052                     RectUnionRect( newRect, *curr );
00053                     self->cDirty--;
00054                     if( --end > curr )
00055                         *curr = *end;
00056                     curr = self->dirty;
00057                 }
00058                 else
00059                 {
00060                     RectUnionRect( *self->dirty, newRect );
00061                     return;
00062                 }
00063                 continue;
00064             }
00065             curr++;
00066         }
00067         if( self->cDirty < self->maxDirty )
00068         {
00069             /* Add new rectangle */
00070             self->dirty[self->cDirty++] = newRect;
00071         }
00072         else
00073         {
00074             /* If we run out of clipping rectangles, eat the last and try again */
00075             --self->cDirty;
00076             RectUnionRect( newRect, self->dirty[self->cDirty] );
00077             ClipRect_add( self, &newRect );
00078         }
00079     }
00080 }

Here is the call graph for this function:

void ClipRect_copy ( ClipRect self,
const ClipRect other 
)

Copy all the clipped quantities from another ClipRect to this one.

Parameters:
self Pointer to clip accumulator
other ClipRect to collect rectangles from

Definition at line 267 of file cliprect.c.

References ClipRect::cDirty, ClipRect_merge(), and ClipRect::dirty.

00268 {
00269     if( other->cDirty <= self->maxDirty )
00270     {
00271         memcpy( self->dirty, other->dirty, sizeof(Rect)*other->cDirty );
00272         self->cDirty = other->cDirty;
00273     }
00274     else
00275     {
00276         self->cDirty = 0;
00277         ClipRect_merge( self, other );
00278     }
00279 }

Here is the call graph for this function:

void ClipRect_init ( ClipRect self,
Rect dirty,
size_t  cDirty,
const Rect bounds 
)

Initialize a dirty clipping list.

Parameters:
self Instance of list to initialize
dirty An array of Rects for it to manage
cDirty Count of Rects in dirty.
bounds Bounding box for accumulation

Definition at line 19 of file cliprect.c.

00020 {
00021     self->cDirty = 0;
00022     self->dirty = dirty;
00023     self->maxDirty = cDirty;
00024     self->bounds = *bounds;
00025 }

void ClipRect_merge ( ClipRect self,
const ClipRect other 
)

Add all the clipped quantities from another ClipRect to this one.

Parameters:
self Pointer to clip accumulator
other ClipRect to collect rectangles from

Definition at line 256 of file cliprect.c.

References ClipRect::cDirty, ClipRect_add(), ClipRect::dirty, and pointer_foreach_const.

Referenced by ClipRect_copy().

00257 {
00258     pointer_foreach_const( Rect, other->dirty, other->cDirty, curr )
00259         ClipRect_add( self, curr );
00260 }

Here is the call graph for this function:

void ClipRect_remove ( ClipRect self,
const Rect rect 
)

Remove a rectangle from dirty list to reserve a window.

Parameters:
self Pointer to clip accumulator
rect rectangle to remove (deliberately passed by value) Useful *after* ClipRect_add functions are finished at a given stage of rendering ClipRect_add_nomerge is safe to use with this. Generally, if you use this, use more rectangles than you otherwise would.

Definition at line 90 of file cliprect.c.

References Rect::bottom, Rect::left, RectContainsRect, RectOutside, RectPtInRect, Rect::right, and Rect::top.

00091 {
00092     /* Local function: Add a rectangle to 'self' */\
00093 #define ClipRect_remove_AddRect( l,t,r,b )\
00094     if( self->cDirty < self->maxDirty ) \
00095     {\
00096         Rect* nr = self->dirty + self->cDirty++;\
00097         nr->left = (l); \
00098         nr->top = (t); \
00099         nr->right = (r); \
00100         nr->bottom = (b); \
00101     }\
00102     else\
00103     {\
00104         /* Running out of our fixed pool of rectangles is definitely an error */\
00105         throwassert( "Ran out of dirty rectangles." );\
00106         break;\
00107     }
00108     Rect* curr = self->dirty;
00109     Rect* end = self->dirty + self->cDirty;
00110     while( curr < end )
00111     {
00112         /* If rects don't touch, don't touch them */
00113         if( RectOutside( *rect, *curr ) )
00114         {
00115             curr++;
00116             continue;
00117         }
00118         /* If rect contains curr, eat curr */
00119         else if( RectContainsRect( *rect, *curr ) )
00120         {
00121             *curr = *--end;
00122             continue;
00123         }
00124         /* If curr contains rect, pop a hole in the middle */
00125         else if( RectContainsRect( *curr, *rect ) )
00126         {
00127             ClipRect_remove_AddRect( curr->left,curr->top,curr->right,rect->top );  /* Top box */
00128             ClipRect_remove_AddRect( curr->left,rect->top,rect->left,rect->bottom );    /* Left box */
00129             ClipRect_remove_AddRect( rect->right,rect->top,curr->right,rect->bottom );  /* Right box */
00130             curr->top = rect->bottom; /* Bottom box */
00131         }
00132         /* Check for simple clip off the left or right */
00133         else if( (curr->top >= rect->top) && (curr->bottom <= rect->bottom) ) 
00134         {
00135             if( curr->left >= rect->left )
00136             {
00137                 curr->left = rect->right;
00138             }
00139             else 
00140             {
00141                 /* Check bisecting, make rects left & right, as applicable */
00142                 if( curr->right <= rect->right )
00143                 {
00144                     curr->right = rect->left;
00145                 }
00146                 else 
00147                 {
00148                     ClipRect_remove_AddRect( curr->left,curr->top,rect->left,curr->bottom );
00149                     curr->left = rect->right;
00150                 }
00151             }
00152         }
00153         /* Check for simple clip off the top or bottom */
00154         else if( (curr->left >= rect->left) && (curr->right <= rect->right) ) 
00155         {
00156             if(curr->top >= rect->top)
00157             {
00158                 curr->top = rect->bottom;
00159             }
00160             else 
00161             {
00162                 /* Check bisecting, make rects above & below, as applicable */
00163                 if(curr->bottom <= rect->bottom)
00164                 {
00165                     curr->bottom = rect->top;
00166                 }
00167                 else 
00168                 {
00169                     ClipRect_remove_AddRect( curr->left,curr->top,curr->right,rect->top);
00170                     curr->top = rect->bottom;
00171                 }
00172             }
00173         }
00174         /* See if we need to make an 'L', left and above */
00175         else if( RectPtInRect(*rect, curr->right-1, curr->bottom-1 ) )
00176         {
00177             ClipRect_remove_AddRect( curr->left, rect->top, rect->left, curr->bottom );
00178             curr->bottom = rect->top;
00179         }
00180         /* See if we need to make an 'L', right and above */
00181         else if( RectPtInRect(*rect, curr->left, curr->bottom-1 ) )
00182         {
00183             ClipRect_remove_AddRect( rect->right, rect->top, curr->right, curr->bottom );
00184             curr->bottom = rect->top;
00185         }
00186         /* See if we need to make an 'L', left and below */
00187         else if( RectPtInRect(*rect, curr->right-1, curr->top ) )
00188         {
00189             ClipRect_remove_AddRect( curr->left, curr->top, rect->left, rect->bottom );
00190             curr->top = rect->bottom;
00191         }
00192         /* See if we need to make an 'L', right and below */
00193         else if( RectPtInRect(*rect, curr->left, curr->top ) )
00194         {
00195             ClipRect_remove_AddRect( rect->right, curr->top, curr->right, rect->bottom );
00196             curr->top = rect->bottom;
00197         }
00198         /* 
00199          * We now know the clipping rectangle is making a 'U' shape
00200          * Just work out which edge to lop clipping box out of
00201          */
00202         /* Make a 'C' out of three rectangles */
00203         else if( curr->right >= rect->left && curr->right <= rect->right) 
00204         {
00205             ClipRect_remove_AddRect(curr->left, curr->top, curr->right, rect->top);     /* Top of C */
00206             ClipRect_remove_AddRect(curr->left, rect->top, rect->left, rect->bottom);       /* Left edge of C */
00207             curr->top = rect->bottom;                                   /* Bottom of C */
00208         }
00209         /* Make a 'U' out of three rectangles */
00210         else if( curr->top >= rect->top && curr->top <= rect->bottom) 
00211         {
00212             ClipRect_remove_AddRect(curr->left, curr->top, rect->left, rect->bottom);       /* Left edge of U */
00213             ClipRect_remove_AddRect(rect->right, curr->top, curr->right, rect->bottom); /* Right edge of U */
00214             curr->top = rect->bottom;                                   /* Bottom edge of U */
00215         }
00216         /* Make an upside-down 'U' out of three rectangles */
00217         else if( curr->bottom >= rect->top && curr->bottom <= rect->bottom )
00218         {
00219             ClipRect_remove_AddRect(curr->left, rect->top, rect->left, curr->bottom);       /* Left edge of U */
00220             ClipRect_remove_AddRect(rect->right, rect->top, curr->right, curr->bottom); /* Right edge of U */
00221             curr->bottom = rect->top;                                   /* Top edge of U */
00222         }
00223         /* Make a backwards 'C' out of three rectangles */
00224         else if( curr->left >= rect->left && curr->left <= rect->right ) 
00225         {
00226             ClipRect_remove_AddRect(curr->left, curr->top, curr->right, rect->top );        /* Top of C */
00227             ClipRect_remove_AddRect(rect->right, rect->top, curr->right, rect->bottom); /* Right edge of C */
00228             curr->top = rect->bottom;                                   /* Bottom edge of C */
00229         }
00230         curr++;
00231     }
00232 #undef ClipRect_remove_AddRect
00233 }

Rect ClipRect_union ( const ClipRect self  ) 

Get union of all rectangles.

Parameters:
self Pointer to clip accumulator
Returns:
Rectangle union of all rectangles

Definition at line 240 of file cliprect.c.

References pointer_foreach_const, RectClear, and RectUnionRect.

00241 {
00242     Rect ret;
00243     RectClear(ret);
00244     {
00245         pointer_foreach_const( Rect, self->dirty, self->cDirty, curr )
00246             RectUnionRect( ret, *curr );
00247     }
00248     return ret;
00249 }


Generated on Fri Jan 2 15:28:35 2009 for Squat by  doxygen 1.5.6