This patch introduces no functional change, but makes some ugly code a little prettier.
--- server/region.c | 1036 ++++++++++++++++------------------------------- 1 file changed, 339 insertions(+), 697 deletions(-)
diff --git a/server/region.c b/server/region.c index 9f377ee05d3..ca5aba8cd63 100644 --- a/server/region.c +++ b/server/region.c @@ -72,709 +72,351 @@ SOFTWARE.
************************************************************************/
-#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "winternl.h" -#include "request.h" -#include "user.h"
-struct region -{ - int size; - int num_rects; - rectangle_t *rects; - rectangle_t extents; -}; +#include <stdarg.h> + #include <stdlib.h> + #include <string.h> + #include "ntstatus.h" + #define WIN32_NO_STATUS + #include "winternl.h" + #include "request.h" + #include"user.h" + struct region + {int size;int + num_rects ; + rectangle_t + *rects; rectangle_t extents;}; + # define RGN_DEFAULT_RECTS 2 + # define EXTENTCHECK( \ + r1 ,r2)((r1 )->right >\ + (r2)->left &&(\ + r1) ->left<(\ + r2)->right\ + &&(r1 )->bottom > (r2)\ + ->top&&(r1 )->top<(r2) ->bottom) + typedef int(* overlap_func_t)( struct region + * reg, const rectangle_t*r1,const rectangle_t* + r1End, const rectangle_t*r2,const rectangle_t* + r2End ,int top ,int bottom ); typedef int(* + non_overlap_func_t )(struct region* reg ,const + rectangle_t* r,const rectangle_t* rEnd,int top + ,int bottom );static const rectangle_t + empty_rect; /*all-zero rectangle for empty + regions */ /*add a rectangle to a region + */ static inline rectangle_t *add_rect ( + struct region * reg ){ if (reg-> num_rects >= + reg ->size ){ rectangle_t*new_rect =realloc(reg + -> rects , 2* sizeof(rectangle_t )*reg->size); + if(!new_rect) { set_error ( STATUS_NO_MEMORY + );return NULL;}reg->rects=new_rect;reg->size *= 2; + }return reg->rects +reg->num_rects++;}/* + make sure all the rectangles + are valid and that + the region is + properly y-x- + banded */static + inline int validate_rectangles (const + rectangle_t *rects,unsigned int nb_rects){ + const rectangle_t*ptr,*end; for(ptr + =rects ,end=rects+nb_rects; ptr<end + ;ptr++ ){ if(is_rect_empty( ptr )) + return 0 ;/*empty rectangle*/ if(ptr== + end-1)break; if(ptr[0].top == ptr[1 ].top)/*same + band*/{if(ptr[0]. bottom!=ptr[1].bottom) return 0; /* not + same y extent*/if ( ptr[0].right >= ptr[1].left)return 0;/*not + properly x ordered*/}else/*new band*/{if(ptr[0].bottom> + ptr[1].top)return 0;/*not properly y ordered + */}}return 1;}/*attempt to merge + the rects in the current band with those in + the previous one. Used only by region_op. */ static int + coalesce_region(struct region*pReg,int prevStart,int curStart){ + int curNumRects; rectangle_t*pRegEnd= & pReg->rects[pReg + ->num_rects]; rectangle_t*pPrevRect= &pReg->rects + [prevStart ];rectangle_t*pCurRect =&pReg-> + rects[ curStart];int prevNumRects= curStart- +prevStart ;int bandtop=pCurRect-> top;for( +curNumRects =0;(pCurRect!=pRegEnd) &&(pCurRect + ->top==bandtop );curNumRects++){pCurRect ++;}if(pCurRect + !=pRegEnd){pRegEnd --;while(pRegEnd[-1].top == pRegEnd -> top) + pRegEnd--;curStart= pRegEnd-pReg->rects; pRegEnd=pReg->rects+ + pReg->num_rects;}if((curNumRects==prevNumRects)&&(curNumRects + !=0)){pCurRect-=curNumRects;if (pPrevRect->bottom == + pCurRect->top){ do{ if((pPrevRect->left != + pCurRect->left) ||(pPrevRect-> + right != pCurRect->right))return curStart; + pPrevRect++; pCurRect++; prevNumRects -= 1; } while( + prevNumRects != 0);pReg->num_rects -= curNumRects;pCurRect -= + curNumRects;pPrevRect -= curNumRects;do{ pPrevRect->bottom= + pCurRect->bottom; pPrevRect++;pCurRect ++; curNumRects-= + 1;} while ( curNumRects != 0);if ( pCurRect == + pRegEnd) curStart= prevStart; else do{* +pPrevRect ++ = *pCurRect++;} while ( +pCurRect !=pRegEnd);}} return curStart + ;}/*apply an operation to two regions */ + /*check the GDI version of the code for + explanations */ static int region_op (struct region* + newReg,const struct region*reg1,const struct region *reg2, + overlap_func_t overlap_func,non_overlap_func_t + non_overlap1_func,non_overlap_func_t + non_overlap2_func){int ybot,ytop,top,bot,prevBand + ,curBand; const rectangle_t * r1BandEnd, *r2BandEnd; const + rectangle_t*r1= reg1->rects; const rectangle_t*r2= + reg2->rects ;const rectangle_t *r1End =r1+ + reg1-> num_rects ;const rectangle_t + *r2End =r2+reg2->num_rects; rectangle_t* +new_rects ,*old_rects=newReg ->rects; + int new_size ,ret=0;new_size=max( reg1->num_rects + ,reg2->num_rects )*2;if(!(new_rects= mem_alloc(new_size + *sizeof(*newReg ->rects)))) return 0;newReg->size= + new_size; newReg ->rects=new_rects; newReg->num_rects + =0;if(reg1->extents.top< reg2->extents.top)ybot=reg1-> + extents.top;else ybot = reg2->extents.top; + prevBand=0;do{curBand=newReg->num_rects; r1BandEnd=r1; + while((r1BandEnd!=r1End) && (r1BandEnd->top==r1->top)) + r1BandEnd++;r2BandEnd=r2;while((r2BandEnd != r2End)&&( + r2BandEnd->top == r2->top))r2BandEnd++;if(r1->top<r2-> + top){top=max(r1->top,ybot);bot=min(r1->bottom,r2->top) + ;if(top!=bot&&non_overlap1_func){if(!non_overlap1_func + (newReg,r1,r1BandEnd,top,bot))goto done;}ytop=r2->top; + }else if(r2->top < r1->top){top=max(r2->top,ybot);bot= + min(r2->bottom,r1->top);if(top!=bot&&non_overlap2_func + ){if (!non_overlap2_func(newReg,r2,r2BandEnd,top,bot)) goto done;} + ytop=r1->top;}else{ytop=r1->top;}if (newReg->num_rects != curBand) + prevBand = coalesce_region(newReg,prevBand,curBand); ybot=min(r1-> + bottom,r2->bottom); curBand = newReg->num_rects;if(ybot>ytop){if(! + overlap_func(newReg,r1,r1BandEnd,r2,r2BandEnd,ytop,ybot))goto done + ;}if(newReg->num_rects!=curBand)prevBand = coalesce_region(newReg, + prevBand,curBand);if(r1->bottom==ybot)r1=r1BandEnd;if(r2->bottom== +ybot)r2=r2BandEnd;}while((r1!=r1End)&&(r2!=r2End));curBand=newReg->num_rects;if( +r1 != r1End){if (non_overlap1_func){do{r1BandEnd=r1;while((r1BandEnd < r1End)&&( +r1BandEnd->top==r1->top))r1BandEnd++;if (!non_overlap1_func(newReg,r1,r1BandEnd, +max(r1->top,ybot),r1->bottom))goto done;r1=r1BandEnd;}while(r1!=r1End);}}else if +((r2!=r2End) && non_overlap2_func){do{r2BandEnd=r2;while ((r2BandEnd < r2End)&&( +r2BandEnd->top==r2->top))r2BandEnd++;if (!non_overlap2_func(newReg,r2,r2BandEnd, +max(r2->top, ybot ),r2->bottom +))goto done; r2=r2BandEnd;} while (r2!=r2End); +}if(newReg-> num_rects!=curBand)coalesce_region ( newReg , +prevBand , curBand);if((newReg->num_rects<(newReg->size/ 2))&&(newReg +->size >2)){ new_size=max(newReg->num_rects,RGN_DEFAULT_RECTS); if(new_rects += realloc( newReg->rects, sizeof (* newReg ->rects)* new_size )){ +newReg->rects=new_rects;newReg ->size=new_size;}}ret=1; done: +free(old_rects);return ret; }/* recalculate the extents +of a region */static void set_region_extents(struct +region*region){rectangle_t *pRect,*pRectEnd;if(region +->num_rects==0){region-> extents.left= 0;region-> +extents.top = 0;region-> extents.right=0;region-> +extents.bottom=0;return; }pRect = region-> rects; +pRectEnd =&pRect[region-> num_rects - 1]; region-> +extents.left=pRect->left; region->extents.top=pRect +->top;region->extents.right =pRectEnd-> right; region-> +extents.bottom=pRectEnd->bottom ;while(pRect <= pRectEnd){if ( +pRect->left< region->extents.left) region->extents.left= pRect->left; +if (pRect-> right>region->extents.right)region->extents.right= pRect->right +;pRect++; }} /*handle an overlapping band for intersect _region */ +static int intersect_overlapping(struct region *pReg, const +rectangle_t* r1,const rectangle_t *r1End,const +rectangle_t *r2, const +rectangle_t*r2End,int top,int bottom){int left,right;while ((r1 != r1End)&&(r2!= +r2End)){left=max(r1->left,r2->left);right=min(r1->right,r2->right);if(left<right +){rectangle_t*rect = add_rect(pReg);if(!rect)return 0;rect->left=left;rect->top= +top;rect->right=right;rect->bottom=bottom;}if (r1->right<r2->right)r1++;else if( +r2->right<r1->right)r2++;else{r1++;r2++;}}return 1;} /* handle a non-overlapping +band for subtract_region*/static int subtract_non_overlapping(struct region*pReg +,const rectangle_t*r,const rectangle_t*rEnd, int top,int bottom){while(r!=rEnd){ + rectangle_t*rect =add_rect(pReg); + if(!rect) return 0;rect->left=r-> + left;rect->top = top;rect->right= + r->right; rect-> bottom = bottom; + r++;} return 1;} /* handle an + overlapping band for subtract_region */ + static int subtract_overlapping(struct region *pReg, + const rectangle_t*r1, const rectangle_t*r1End, const + rectangle_t *r2,const rectangle_t *r2End,int top,int + bottom){int left=r1->left; while((r1!=r1End + )&&(r2!=r2End)){ if (r2->right <= + left) r2++; else if (r2->left <= + left){left =r2-> right; if(left>= + r1->right){r1++; if(r1!=r1End)left=r1->left + ;}else r2++;}else if(r2->left<r1->right){rectangle_t + *rect=add_rect(pReg); if(!rect)return 0; rect->left= + left;rect->top=top;rect->right=r2->left;rect->bottom + =bottom;left=r2->right;if (left>=r1->right + ){r1++; if(r1 != r1End) left=r1-> + left;}else r2++; } else {if (r1-> + right > left ) { rectangle_t*rect + =add_rect(pReg); if(!rect)return 0;rect + ->left=left;rect->top=top;rect->right=r1->right;rect + ->bottom=bottom;}r1++;if(r1!=r1End) left=r1->left;}} + while(r1!=r1End){rectangle_t*rect=add_rect(pReg);if( + !rect)return 0;rect->left= left; rect->top= + top;rect->right= r1->right;rect-> + bottom=bottom;r1 ++;if(r1!=r1End) + left= r1->left;} return 1;}/*handle a + non-overlapping band for union_region*/static int + union_non_overlapping( struct region *pReg, const + rectangle_t *r, const rectangle_t *rEnd, int top,int + bottom){while(r != rEnd){rectangle_t *rect=add_rect( + pReg);if(!rect)return 0; rect->left = r-> + left; rect->top= top;rect->right= + r->right; rect-> bottom=bottom; r + ++;} return 1;} /* handle an overlapping band for union_region */ static int + union_overlapping(struct region*pReg,const rectangle_t *r1,const rectangle_t + *r1End, const rectangle_t *r2,const rectangle_t *r2End,int top, int bottom){ + #define MERGERECT(r)if((pReg->num_rects!=0)&&(pReg->rects[pReg->num_rects-1\ + ].top==top)&&(pReg->rects[ pReg->num_rects-1].bottom\ + ==bottom) && (pReg->rects[ pReg->num_rects -1].right\ + >=r->left)){if(pReg->rects [pReg->num_rects-1].right<\ + r->right){pReg->rects[pReg ->num_rects-1].right = r->\ + right;}}else {rectangle_t* rect = add_rect(pReg);if(\ + !rect)return 0;rect->top= top;rect->bottom=bottom;\ + rect->left=r->left;rect ->right = r->right;}r++; + while((r1!=r1End)&&(r2 !=r2End)){if(r1->left<r2 + ->left){MERGERECT(r1);} else{MERGERECT(r2);}}if( + r1!=r1End){do{MERGERECT(r1);}while(r1!= + r1End);}else while (r2!=r2End){ + MERGERECT(r2);}return 1; + #undef MERGERECT + }/*create an empty region*/ + struct region*create_empty_region(void + ){struct region*region;if(!(region=mem_alloc(sizeof + (*region))))return NULL;if (!(region->rects=mem_alloc + (RGN_DEFAULT_RECTS *sizeof (*region->rects )))){free( + region);return NULL;}region ->size = RGN_DEFAULT_RECTS; + region->num_rects=0;region ->extents.left=0; region-> + extents.top = 0; region-> extents.right = 0;region-> + extents.bottom = 0; return region;}/* create a region + from request data */struct region* create_region_from_req_data + (const void*data,data_size_t size){ unsigned int alloc_rects; + struct region*region;const rectangle_t *rects = data; + int nb_rects = size/sizeof( rectangle_t ); /* special + case: empty region can be specified by a single all- + zero rectangle*/if(nb_rects== 1&&!memcmp(rects,&empty_rect + ,sizeof(empty_rect)))nb_rects =0;if(!validate_rectangles + (rects,nb_rects)){set_error (STATUS_INVALID_PARAMETER) + ;return NULL;}if(!(region= mem_alloc(sizeof(*region) + ))) return NULL; alloc_rects = max(nb_rects, + RGN_DEFAULT_RECTS);if(!(region->rects + = mem_alloc( alloc_rects * + sizeof(*region-> + rects)))){free(region);return + NULL;}region->size=alloc_rects; region-> + num_rects=nb_rects;memcpy (region->rects, rects, + nb_rects*sizeof(*rects)); set_region_extents(region + );return region;}/*free a region */void free_region + (struct region*region){free (region->rects);free(region + );}/*set region to a simple rectangle*/void set_region_rect + (struct region *region, const rectangle_t*rect){if + (!is_rect_empty ( rect )){ region ->num_rects=1;region->rects + [0]=region->extents=*rect; }else{ region->num_rects=0;region + ->extents=empty_rect;}} /* retrieve the region data + for sending to the client*/ rectangle_t*get_region_data + (const struct region*region ,data_size_t max_size, + data_size_t *total_size ){ const rectangle_t *data = + region->rects;if(!(*total_size =region->num_rects*sizeof( + rectangle_t))){/* return a single empty rect for empty + regions*/*total_size=sizeof (empty_rect);data=&empty_rect + ;}if (max_size >= *total_size)return memdup(data,* + total_size);set_error(STATUS_BUFFER_OVERFLOW + );return NULL;}/*retrieve the region + data for sending to the + client and free + the region at the same time + */rectangle_t*get_region_data_and_free + (struct region *region, data_size_t max_size, + data_size_t*total_size) {rectangle_t*ret=region + ->rects;if(!(*total_size =region->num_rects*sizeof + (rectangle_t))){/* return a single empty rect for + empty regions*/*total_size =sizeof( empty_rect );if( + max_size>=sizeof(empty_rect )){ret=memdup(&empty_rect, + sizeof( empty_rect ));free( region->rects);}}if(max_size + <*total_size){free( region ->rects); set_error( + STATUS_BUFFER_OVERFLOW ); ret = NULL;}free(region);return + ret;} /* check if a given region is empty*/int is_region_empty + (const struct region*region ){return region->num_rects == 0;}/* + get the extents rect of a region */void get_region_extents + (const struct region*region ,rectangle_t*rect){*rect= + region->extents;}/* add an offset to a region */void + offset_region(struct region *region, int x, int y ){ + rectangle_t*rect,*end;if(! region->num_rects)return; + for(rect=region->rects,end =rect+region->num_rects; + rect<end;rect++)offset_rect(rect,x,y);offset_rect( + ®ion->extents,x,y);}/*mirror a region + relative to a window client + rect */ void + mirror_region(const rectangle_t + *client_rect,struct region*region){int start + ,end,i,j;for(start=0;start <region->num_rects;start= + end+1){for(end=start;end <region->num_rects-1;end + ++)if(region->rects[end+1] .top!=region->rects[end]. + top)break;for(i=start,j=end ;i<j;i++,j--){rectangle_t + rect=region->rects[j];region ->rects[i]=region->rects[j + ];region->rects[j] = rect; mirror_rect(client_rect,& + region->rects[j]);mirror_rect (client_rect,®ion->rects + [i]);}if(i==j)mirror_rect( client_rect,®ion->rects + [i]);} mirror_rect( client_rect, ®ion->extents );}/* scale a region for a + given dpi factor */ void scale_region( struct region * region, unsigned int + + + + + + + + + + dpi_from,unsigned int dpi_to ){rectangle_t + *rect,*end;if(!region->num_rects)return;for( + rect=region->rects, end=rect+region->num_rects + ;rect<end;rect++)scale_dpi_rect(rect,dpi_from, + dpi_to); scale_dpi_rect(®ion->extents, + dpi_from,dpi_to);} /* make a copy of a region; + returns dst or NULL on error */ struct region* + copy_region ( struct region *dst, const struct + region*src){if(dst == src)return dst; if(dst-> + size<src->num_rects){rectangle_t*rect=realloc( + dst->rects,src->num_rects*sizeof(*rect)); if(! + rect){set_error(STATUS_NO_MEMORY);return NULL; + }dst->rects=rect;dst->size=src->num_rects;}dst + ->num_rects=src->num_rects; dst->extents=src-> + extents; memcpy( dst->rects,src->rects,src-> + num_rects*sizeof(*dst->rects)); return dst;} + /* compute the intersection of two regions + into dst, which can be one of the source + regions*/struct region*intersect_region( + struct region*dst,const struct region + *src1,const struct region *src2) + {if (!src1->num_rects||! + src2->num_rects||! + EXTENTCHECK( + &src1-> + extents + ,&src2-> + extents + )){dst-> + num_rects + =0;dst-> + extents + .left=0 + ;dst-> + extents + .top=0 + ;dst-> + extents + .right= + 0;dst-> + extents + .bottom= + 0;return + dst;}if(! + region_op + (dst,src1,src2 + ,intersect_overlapping,NULL, + NULL))return NULL;set_region_extents(dst);return dst;}
-#define RGN_DEFAULT_RECTS 2
-#define EXTENTCHECK(r1, r2) \ - ((r1)->right > (r2)->left && \ - (r1)->left < (r2)->right && \ - (r1)->bottom > (r2)->top && \ - (r1)->top < (r2)->bottom)
-typedef int (*overlap_func_t)( struct region *reg, const rectangle_t *r1, const rectangle_t *r1End, - const rectangle_t *r2, const rectangle_t *r2End, int top, int bottom ); -typedef int (*non_overlap_func_t)( struct region *reg, const rectangle_t *r, - const rectangle_t *rEnd, int top, int bottom );
-static const rectangle_t empty_rect; /* all-zero rectangle for empty regions */ - -/* add a rectangle to a region */ -static inline rectangle_t *add_rect( struct region *reg ) -{ - if (reg->num_rects >= reg->size) - { - rectangle_t *new_rect = realloc( reg->rects, 2 * sizeof(rectangle_t) * reg->size ); - if (!new_rect) - { - set_error( STATUS_NO_MEMORY ); - return NULL; - } - reg->rects = new_rect; - reg->size *= 2; - } - return reg->rects + reg->num_rects++; -} - -/* make sure all the rectangles are valid and that the region is properly y-x-banded */ -static inline int validate_rectangles( const rectangle_t *rects, unsigned int nb_rects ) -{ - const rectangle_t *ptr, *end; - - for (ptr = rects, end = rects + nb_rects; ptr < end; ptr++) - { - if (is_rect_empty( ptr )) return 0; /* empty rectangle */ - if (ptr == end - 1) break; - if (ptr[0].top == ptr[1].top) /* same band */ - { - if (ptr[0].bottom != ptr[1].bottom) return 0; /* not same y extent */ - if (ptr[0].right >= ptr[1].left) return 0; /* not properly x ordered */ - } - else /* new band */ - { - if (ptr[0].bottom > ptr[1].top) return 0; /* not properly y ordered */ - } - } - return 1; -} - -/* attempt to merge the rects in the current band with those in the */ -/* previous one. Used only by region_op. */ -static int coalesce_region( struct region *pReg, int prevStart, int curStart ) -{ - int curNumRects; - rectangle_t *pRegEnd = &pReg->rects[pReg->num_rects]; - rectangle_t *pPrevRect = &pReg->rects[prevStart]; - rectangle_t *pCurRect = &pReg->rects[curStart]; - int prevNumRects = curStart - prevStart; - int bandtop = pCurRect->top; - - for (curNumRects = 0; - (pCurRect != pRegEnd) && (pCurRect->top == bandtop); - curNumRects++) - { - pCurRect++; - } - - if (pCurRect != pRegEnd) - { - pRegEnd--; - while (pRegEnd[-1].top == pRegEnd->top) pRegEnd--; - curStart = pRegEnd - pReg->rects; - pRegEnd = pReg->rects + pReg->num_rects; - } - - if ((curNumRects == prevNumRects) && (curNumRects != 0)) - { - pCurRect -= curNumRects; - if (pPrevRect->bottom == pCurRect->top) - { - do - { - if ((pPrevRect->left != pCurRect->left) || - (pPrevRect->right != pCurRect->right)) return curStart; - pPrevRect++; - pCurRect++; - prevNumRects -= 1; - } while (prevNumRects != 0); - - pReg->num_rects -= curNumRects; - pCurRect -= curNumRects; - pPrevRect -= curNumRects; - - do - { - pPrevRect->bottom = pCurRect->bottom; - pPrevRect++; - pCurRect++; - curNumRects -= 1; - } while (curNumRects != 0); - - if (pCurRect == pRegEnd) curStart = prevStart; - else do { *pPrevRect++ = *pCurRect++; } while (pCurRect != pRegEnd); - - } - } - return curStart; -} - -/* apply an operation to two regions */ -/* check the GDI version of the code for explanations */ -static int region_op( struct region *newReg, const struct region *reg1, const struct region *reg2, - overlap_func_t overlap_func, - non_overlap_func_t non_overlap1_func, - non_overlap_func_t non_overlap2_func ) -{ - int ybot, ytop, top, bot, prevBand, curBand; - const rectangle_t *r1BandEnd, *r2BandEnd; - - const rectangle_t *r1 = reg1->rects; - const rectangle_t *r2 = reg2->rects; - const rectangle_t *r1End = r1 + reg1->num_rects; - const rectangle_t *r2End = r2 + reg2->num_rects; - - rectangle_t *new_rects, *old_rects = newReg->rects; - int new_size, ret = 0; - - new_size = max( reg1->num_rects, reg2->num_rects ) * 2; - if (!(new_rects = mem_alloc( new_size * sizeof(*newReg->rects) ))) return 0; - - newReg->size = new_size; - newReg->rects = new_rects; - newReg->num_rects = 0; - - if (reg1->extents.top < reg2->extents.top) - ybot = reg1->extents.top; - else - ybot = reg2->extents.top; - - prevBand = 0; - - do - { - curBand = newReg->num_rects; - - r1BandEnd = r1; - while ((r1BandEnd != r1End) && (r1BandEnd->top == r1->top)) r1BandEnd++; - - r2BandEnd = r2; - while ((r2BandEnd != r2End) && (r2BandEnd->top == r2->top)) r2BandEnd++; - - if (r1->top < r2->top) - { - top = max(r1->top,ybot); - bot = min(r1->bottom,r2->top); - - if ((top != bot) && non_overlap1_func) - { - if (!non_overlap1_func( newReg, r1, r1BandEnd, top, bot )) goto done; - } - - ytop = r2->top; - } - else if (r2->top < r1->top) - { - top = max(r2->top,ybot); - bot = min(r2->bottom,r1->top); - - if ((top != bot) && non_overlap2_func) - { - if (!non_overlap2_func( newReg, r2, r2BandEnd, top, bot )) goto done; - } - - ytop = r1->top; - } - else - { - ytop = r1->top; - } - - if (newReg->num_rects != curBand) - prevBand = coalesce_region(newReg, prevBand, curBand); - - ybot = min(r1->bottom, r2->bottom); - curBand = newReg->num_rects; - if (ybot > ytop) - { - if (!overlap_func( newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot )) goto done; - } - - if (newReg->num_rects != curBand) - prevBand = coalesce_region(newReg, prevBand, curBand); - - if (r1->bottom == ybot) r1 = r1BandEnd; - if (r2->bottom == ybot) r2 = r2BandEnd; - } while ((r1 != r1End) && (r2 != r2End)); - - curBand = newReg->num_rects; - if (r1 != r1End) - { - if (non_overlap1_func) - { - do - { - r1BandEnd = r1; - while ((r1BandEnd < r1End) && (r1BandEnd->top == r1->top)) r1BandEnd++; - if (!non_overlap1_func( newReg, r1, r1BandEnd, max(r1->top,ybot), r1->bottom )) - goto done; - r1 = r1BandEnd; - } while (r1 != r1End); - } - } - else if ((r2 != r2End) && non_overlap2_func) - { - do - { - r2BandEnd = r2; - while ((r2BandEnd < r2End) && (r2BandEnd->top == r2->top)) r2BandEnd++; - if (!non_overlap2_func( newReg, r2, r2BandEnd, max(r2->top,ybot), r2->bottom )) - goto done; - r2 = r2BandEnd; - } while (r2 != r2End); - } - - if (newReg->num_rects != curBand) coalesce_region(newReg, prevBand, curBand); - - if ((newReg->num_rects < (newReg->size / 2)) && (newReg->size > 2)) - { - new_size = max( newReg->num_rects, RGN_DEFAULT_RECTS ); - if ((new_rects = realloc( newReg->rects, sizeof(*newReg->rects) * new_size ))) - { - newReg->rects = new_rects; - newReg->size = new_size; - } - } - ret = 1; -done: - free( old_rects ); - return ret; -} - -/* recalculate the extents of a region */ -static void set_region_extents( struct region *region ) -{ - rectangle_t *pRect, *pRectEnd; - - if (region->num_rects == 0) - { - region->extents.left = 0; - region->extents.top = 0; - region->extents.right = 0; - region->extents.bottom = 0; - return; - } - - pRect = region->rects; - pRectEnd = &pRect[region->num_rects - 1]; - - region->extents.left = pRect->left; - region->extents.top = pRect->top; - region->extents.right = pRectEnd->right; - region->extents.bottom = pRectEnd->bottom; - - while (pRect <= pRectEnd) - { - if (pRect->left < region->extents.left) region->extents.left = pRect->left; - if (pRect->right > region->extents.right) region->extents.right = pRect->right; - pRect++; - } -} - -/* handle an overlapping band for intersect_region */ -static int intersect_overlapping( struct region *pReg, - const rectangle_t *r1, const rectangle_t *r1End, - const rectangle_t *r2, const rectangle_t *r2End, - int top, int bottom ) - -{ - int left, right; - - while ((r1 != r1End) && (r2 != r2End)) - { - left = max(r1->left, r2->left); - right = min(r1->right, r2->right); - - if (left < right) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = left; - rect->top = top; - rect->right = right; - rect->bottom = bottom; - } - - if (r1->right < r2->right) r1++; - else if (r2->right < r1->right) r2++; - else - { - r1++; - r2++; - } - } - return 1; -} - -/* handle a non-overlapping band for subtract_region */ -static int subtract_non_overlapping( struct region *pReg, const rectangle_t *r, - const rectangle_t *rEnd, int top, int bottom ) -{ - while (r != rEnd) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = r->left; - rect->top = top; - rect->right = r->right; - rect->bottom = bottom; - r++; - } - return 1; -} - -/* handle an overlapping band for subtract_region */ -static int subtract_overlapping( struct region *pReg, - const rectangle_t *r1, const rectangle_t *r1End, - const rectangle_t *r2, const rectangle_t *r2End, - int top, int bottom ) -{ - int left = r1->left; - - while ((r1 != r1End) && (r2 != r2End)) - { - if (r2->right <= left) r2++; - else if (r2->left <= left) - { - left = r2->right; - if (left >= r1->right) - { - r1++; - if (r1 != r1End) - left = r1->left; - } - else r2++; - } - else if (r2->left < r1->right) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = left; - rect->top = top; - rect->right = r2->left; - rect->bottom = bottom; - left = r2->right; - if (left >= r1->right) - { - r1++; - if (r1 != r1End) - left = r1->left; - } - else r2++; - } - else - { - if (r1->right > left) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = left; - rect->top = top; - rect->right = r1->right; - rect->bottom = bottom; - } - r1++; - if (r1 != r1End) - left = r1->left; - } - } - - while (r1 != r1End) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = left; - rect->top = top; - rect->right = r1->right; - rect->bottom = bottom; - r1++; - if (r1 != r1End) left = r1->left; - } - return 1; -} - -/* handle a non-overlapping band for union_region */ -static int union_non_overlapping( struct region *pReg, const rectangle_t *r, - const rectangle_t *rEnd, int top, int bottom ) -{ - while (r != rEnd) - { - rectangle_t *rect = add_rect( pReg ); - if (!rect) return 0; - rect->left = r->left; - rect->top = top; - rect->right = r->right; - rect->bottom = bottom; - r++; - } - return 1; -} - -/* handle an overlapping band for union_region */ -static int union_overlapping( struct region *pReg, - const rectangle_t *r1, const rectangle_t *r1End, - const rectangle_t *r2, const rectangle_t *r2End, - int top, int bottom ) -{ -#define MERGERECT(r) \ - if ((pReg->num_rects != 0) && \ - (pReg->rects[pReg->num_rects-1].top == top) && \ - (pReg->rects[pReg->num_rects-1].bottom == bottom) && \ - (pReg->rects[pReg->num_rects-1].right >= r->left)) \ - { \ - if (pReg->rects[pReg->num_rects-1].right < r->right) \ - { \ - pReg->rects[pReg->num_rects-1].right = r->right; \ - } \ - } \ - else \ - { \ - rectangle_t *rect = add_rect( pReg ); \ - if (!rect) return 0; \ - rect->top = top; \ - rect->bottom = bottom; \ - rect->left = r->left; \ - rect->right = r->right; \ - } \ - r++; - - while ((r1 != r1End) && (r2 != r2End)) - { - if (r1->left < r2->left) - { - MERGERECT(r1); - } - else - { - MERGERECT(r2); - } - } - - if (r1 != r1End) - { - do - { - MERGERECT(r1); - } while (r1 != r1End); - } - else while (r2 != r2End) - { - MERGERECT(r2); - } - return 1; -#undef MERGERECT -} - - -/* create an empty region */ -struct region *create_empty_region(void) -{ - struct region *region; - - if (!(region = mem_alloc( sizeof(*region) ))) return NULL; - if (!(region->rects = mem_alloc( RGN_DEFAULT_RECTS * sizeof(*region->rects) ))) - { - free( region ); - return NULL; - } - region->size = RGN_DEFAULT_RECTS; - region->num_rects = 0; - region->extents.left = 0; - region->extents.top = 0; - region->extents.right = 0; - region->extents.bottom = 0; - return region; -} - -/* create a region from request data */ -struct region *create_region_from_req_data( const void *data, data_size_t size ) -{ - unsigned int alloc_rects; - struct region *region; - const rectangle_t *rects = data; - int nb_rects = size / sizeof(rectangle_t); - - /* special case: empty region can be specified by a single all-zero rectangle */ - if (nb_rects == 1 && !memcmp( rects, &empty_rect, sizeof(empty_rect) )) nb_rects = 0; - - if (!validate_rectangles( rects, nb_rects )) - { - set_error( STATUS_INVALID_PARAMETER ); - return NULL; - } - - if (!(region = mem_alloc( sizeof(*region) ))) return NULL; - - alloc_rects = max( nb_rects, RGN_DEFAULT_RECTS ); - if (!(region->rects = mem_alloc( alloc_rects * sizeof(*region->rects) ))) - { - free( region ); - return NULL; - } - region->size = alloc_rects; - region->num_rects = nb_rects; - memcpy( region->rects, rects, nb_rects * sizeof(*rects) ); - set_region_extents( region ); - return region; -} - -/* free a region */ -void free_region( struct region *region ) -{ - free( region->rects ); - free( region ); -} - -/* set region to a simple rectangle */ -void set_region_rect( struct region *region, const rectangle_t *rect ) -{ - if (!is_rect_empty( rect )) - { - region->num_rects = 1; - region->rects[0] = region->extents = *rect; - } - else - { - region->num_rects = 0; - region->extents = empty_rect; - } -} - -/* retrieve the region data for sending to the client */ -rectangle_t *get_region_data( const struct region *region, data_size_t max_size, data_size_t *total_size ) -{ - const rectangle_t *data = region->rects; - - if (!(*total_size = region->num_rects * sizeof(rectangle_t))) - { - /* return a single empty rect for empty regions */ - *total_size = sizeof(empty_rect); - data = &empty_rect; - } - if (max_size >= *total_size) return memdup( data, *total_size ); - set_error( STATUS_BUFFER_OVERFLOW ); - return NULL; -} - -/* retrieve the region data for sending to the client and free the region at the same time */ -rectangle_t *get_region_data_and_free( struct region *region, data_size_t max_size, data_size_t *total_size ) -{ - rectangle_t *ret = region->rects; - - if (!(*total_size = region->num_rects * sizeof(rectangle_t))) - { - /* return a single empty rect for empty regions */ - *total_size = sizeof(empty_rect); - if (max_size >= sizeof(empty_rect)) - { - ret = memdup( &empty_rect, sizeof(empty_rect) ); - free( region->rects ); - } - } - - if (max_size < *total_size) - { - free( region->rects ); - set_error( STATUS_BUFFER_OVERFLOW ); - ret = NULL; - } - free( region ); - return ret; -} - -/* check if a given region is empty */ -int is_region_empty( const struct region *region ) -{ - return region->num_rects == 0; -} - - -/* get the extents rect of a region */ -void get_region_extents( const struct region *region, rectangle_t *rect ) -{ - *rect = region->extents; -} - -/* add an offset to a region */ -void offset_region( struct region *region, int x, int y ) -{ - rectangle_t *rect, *end; - - if (!region->num_rects) return; - for (rect = region->rects, end = rect + region->num_rects; rect < end; rect++) - offset_rect( rect, x, y ); - offset_rect( ®ion->extents, x, y ); -} - -/* mirror a region relative to a window client rect */ -void mirror_region( const rectangle_t *client_rect, struct region *region ) -{ - int start, end, i, j; - - for (start = 0; start < region->num_rects; start = end + 1) - { - for (end = start; end < region->num_rects - 1; end++) - if (region->rects[end + 1].top != region->rects[end].top) break; - for (i = start, j = end; i < j; i++, j--) - { - rectangle_t rect = region->rects[j]; - region->rects[i] = region->rects[j]; - region->rects[j] = rect; - mirror_rect( client_rect, ®ion->rects[j] ); - mirror_rect( client_rect, ®ion->rects[i] ); - } - if (i == j) mirror_rect( client_rect, ®ion->rects[i] ); - } - mirror_rect( client_rect, ®ion->extents ); -} - - -/* scale a region for a given dpi factor */ -void scale_region( struct region *region, unsigned int dpi_from, unsigned int dpi_to ) -{ - rectangle_t *rect, *end; - - if (!region->num_rects) return; - for (rect = region->rects, end = rect + region->num_rects; rect < end; rect++) - scale_dpi_rect( rect, dpi_from, dpi_to ); - scale_dpi_rect( ®ion->extents, dpi_from, dpi_to ); -} - - -/* make a copy of a region; returns dst or NULL on error */ -struct region *copy_region( struct region *dst, const struct region *src ) -{ - if (dst == src) return dst; - - if (dst->size < src->num_rects) - { - rectangle_t *rect = realloc( dst->rects, src->num_rects * sizeof(*rect) ); - if (!rect) - { - set_error( STATUS_NO_MEMORY ); - return NULL; - } - dst->rects = rect; - dst->size = src->num_rects; - } - dst->num_rects = src->num_rects; - dst->extents = src->extents; - memcpy( dst->rects, src->rects, src->num_rects * sizeof(*dst->rects) ); - return dst; -} - -/* compute the intersection of two regions into dst, which can be one of the source regions */ -struct region *intersect_region( struct region *dst, const struct region *src1, - const struct region *src2 ) -{ - if (!src1->num_rects || !src2->num_rects || !EXTENTCHECK(&src1->extents, &src2->extents)) - { - dst->num_rects = 0; - dst->extents.left = 0; - dst->extents.top = 0; - dst->extents.right = 0; - dst->extents.bottom = 0; - return dst; - } - if (!region_op( dst, src1, src2, intersect_overlapping, NULL, NULL )) return NULL; - set_region_extents( dst ); - return dst; -}
/* compute the subtraction of two regions into dst, which can be one of the source regions */ struct region *subtract_region( struct region *dst, const struct region *src1,
Zebediah Figura z.figura12@gmail.com writes:
This patch introduces no functional change, but makes some ugly code a little prettier.
Finally a coding standard that we can all agree on!
Everybody please reformat your code accordingly.
Am Do., 1. Apr. 2021 um 10:52 Uhr schrieb Alexandre Julliard julliard@winehq.org:
Zebediah Figura z.figura12@gmail.com writes:
This patch introduces no functional change, but makes some ugly code a little prettier.
Finally a coding standard that we can all agree on!
Everybody please reformat your code accordingly.
I'm all in for it. Finally, git diffs have a much better chance of generating diffs of actual single word changes instead of showing whole line changes.
Thanks Zeb for this great job!
Regards, Kai
On 4/1/2021 12:04 PM, Kai Krakow wrote:
Am Do., 1. Apr. 2021 um 10:52 Uhr schrieb Alexandre Julliard julliard@winehq.org:
Zebediah Figura z.figura12@gmail.com writes:
This patch introduces no functional change, but makes some ugly code a little prettier.
Finally a coding standard that we can all agree on!
Everybody please reformat your code accordingly.
I'm all in for it. Finally, git diffs have a much better chance of generating diffs of actual single word changes instead of showing whole line changes.
Thanks Zeb for this great job!
Regards, Kai
Wow, this reads so much better! I can't believe this is C
On 01.04.2021 14:19, Jefferson Carpenter wrote:
On 4/1/2021 12:04 PM, Kai Krakow wrote:
Am Do., 1. Apr. 2021 um 10:52 Uhr schrieb Alexandre Julliard julliard@winehq.org:
Zebediah Figura z.figura12@gmail.com writes:
This patch introduces no functional change, but makes some ugly code a little prettier.
Finally a coding standard that we can all agree on!
Everybody please reformat your code accordingly.
I'm all in for it. Finally, git diffs have a much better chance of generating diffs of actual single word changes instead of showing whole line changes.
Thanks Zeb for this great job!
Regards, Kai
Wow, this reads so much better! I can't believe this is C
Please do winevulkan/vulkan_thunks.c next! Maybe i could manage to rebase those darn proton hacks with less effort! :)
S