00001
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include "../ctl/ctldef.h"
00010 #include "cliprect.h"
00011
00019 void ClipRect_init( ClipRect* self, Rect* dirty, size_t cDirty, const Rect* bounds )
00020 {
00021 self->cDirty = 0;
00022 self->dirty = dirty;
00023 self->maxDirty = cDirty;
00024 self->bounds = *bounds;
00025 }
00026
00034 void ClipRect_add( ClipRect* self, const Rect* rect )
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
00045 if( RectContainsRect( *curr, newRect ) )
00046 return;
00047
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
00070 self->dirty[self->cDirty++] = newRect;
00071 }
00072 else
00073 {
00074
00075 --self->cDirty;
00076 RectUnionRect( newRect, self->dirty[self->cDirty] );
00077 ClipRect_add( self, &newRect );
00078 }
00079 }
00080 }
00081
00090 void ClipRect_remove( ClipRect* self, const Rect* rect )
00091 {
00092 \
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 \
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
00113 if( RectOutside( *rect, *curr ) )
00114 {
00115 curr++;
00116 continue;
00117 }
00118
00119 else if( RectContainsRect( *rect, *curr ) )
00120 {
00121 *curr = *--end;
00122 continue;
00123 }
00124
00125 else if( RectContainsRect( *curr, *rect ) )
00126 {
00127 ClipRect_remove_AddRect( curr->left,curr->top,curr->right,rect->top );
00128 ClipRect_remove_AddRect( curr->left,rect->top,rect->left,rect->bottom );
00129 ClipRect_remove_AddRect( rect->right,rect->top,curr->right,rect->bottom );
00130 curr->top = rect->bottom;
00131 }
00132
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
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
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
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
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
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
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
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
00200
00201
00202
00203 else if( curr->right >= rect->left && curr->right <= rect->right)
00204 {
00205 ClipRect_remove_AddRect(curr->left, curr->top, curr->right, rect->top);
00206 ClipRect_remove_AddRect(curr->left, rect->top, rect->left, rect->bottom);
00207 curr->top = rect->bottom;
00208 }
00209
00210 else if( curr->top >= rect->top && curr->top <= rect->bottom)
00211 {
00212 ClipRect_remove_AddRect(curr->left, curr->top, rect->left, rect->bottom);
00213 ClipRect_remove_AddRect(rect->right, curr->top, curr->right, rect->bottom);
00214 curr->top = rect->bottom;
00215 }
00216
00217 else if( curr->bottom >= rect->top && curr->bottom <= rect->bottom )
00218 {
00219 ClipRect_remove_AddRect(curr->left, rect->top, rect->left, curr->bottom);
00220 ClipRect_remove_AddRect(rect->right, rect->top, curr->right, curr->bottom);
00221 curr->bottom = rect->top;
00222 }
00223
00224 else if( curr->left >= rect->left && curr->left <= rect->right )
00225 {
00226 ClipRect_remove_AddRect(curr->left, curr->top, curr->right, rect->top );
00227 ClipRect_remove_AddRect(rect->right, rect->top, curr->right, rect->bottom);
00228 curr->top = rect->bottom;
00229 }
00230 curr++;
00231 }
00232 #undef ClipRect_remove_AddRect
00233 }
00234
00240 Rect ClipRect_union( const ClipRect* self )
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 }
00250
00256 void ClipRect_merge( ClipRect* self, const ClipRect* other )
00257 {
00258 pointer_foreach_const( Rect, other->dirty, other->cDirty, curr )
00259 ClipRect_add( self, curr );
00260 }
00261
00267 void ClipRect_copy( ClipRect* self, const ClipRect* other )
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 }