#include "rect.h"
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. |
Definition in file cliprect.h.
#define ClipRect_foreach | ( | instance, | |||
iterator | ) | pointer_foreach_const( Rect, (instance)->dirty, (instance)->cDirty, iterator ) |
Iterate cliprects.
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 )
instance | Instance of ClipRect we're initializing | |
iterator | Name of variable to iterate with |
Definition at line 57 of file cliprect.h.
Add a dirty rectangle to dirty list Overlapped and redundant rectangles are merged. If list is filled, merges all rectangles to make more room.
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 }
Copy all the clipped quantities from another ClipRect to this one.
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 }
Initialize a dirty clipping list.
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 }
Add all the clipped quantities from another ClipRect to this one.
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 }
Remove a rectangle from dirty list to reserve a window.
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 }
Get union of all rectangles.
self | Pointer to clip accumulator |
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 }