//----取得新增可视域----------------------------------------------------------- //功能: 出现在visible_clip中且不在visible_bak的区域,加入redraw_clip。 // 同时出现在visible_clip和visible_bak中的部分,留在visible_clip中 // 如果dest_blend==true,则仅在visible_bak出现的部分留在visible_bak // 否则,释放visiblvisible_bak //参数: gkwin,目标窗口 //返回: 无 //----------------------------------------------------------------------------- void __GK_GetNewClip(struct tagGkWinRsc *gkwin) { struct tagClipRect *redraw; //visible_clip-visible_bak多出的部分 struct tagClipRect *res; //visible_clip与visible_bak相交的clip if(gkwin->visible_bak != NULL) { __GK_ClipLinkSub(gkwin->visible_clip,gkwin->visible_bak,&res,&redraw); __GK_ClipLinkConnect(&gkwin->redraw_clip,redraw); gkwin->visible_clip = res; if(gkwin->dest_blend) { __GK_ClipLinkSub(gkwin->visible_bak,gkwin->visible_clip, &res,&redraw); gkwin->visible_bak = redraw; __GK_FreeClipQueue(res); } else { gkwin->visible_bak = __GK_FreeClipQueue(gkwin->visible_bak); } } else { __GK_ClipLinkConnect(&gkwin->redraw_clip,gkwin->visible_clip); gkwin->visible_clip = NULL; } }
//----取得新增可视域----------------------------------------------------------- //功能: 出现在visible_clip中且不在visible_bak的区域,加入redraw_clip。 // 同时出现在visible_clip和visible_bak中的部分,留在visible_clip中 // 如果dest_blend==true,则仅在visible_bak出现的部分留在visible_bak // 否则,释放visiblvisible_bak //参数: gkwin,目标窗口 //返回: 无 //----------------------------------------------------------------------------- void __GK_GetNewClip(struct GkWinRsc *gkwin) { struct ClipRect *redraw; //visible_clip-visible_bak多出的部分 struct ClipRect *res; //visible_clip与visible_bak相交的clip if(gkwin->visible_bak != NULL) { __GK_ClipLinkSub(gkwin->visible_clip,gkwin->visible_bak,&res,&redraw); __GK_ClipLinkConnect(&gkwin->redraw_clip,redraw); gkwin->visible_clip = res; if(gkwin->WinProperty.DestBlend == CN_GKWIN_DEST_VISIBLE) { __GK_ClipLinkSub(gkwin->visible_bak,gkwin->visible_clip, &res,&redraw); gkwin->visible_bak = redraw; __GK_FreeClipQueue(res); } else { gkwin->visible_bak = __GK_FreeClipQueue(gkwin->visible_bak); } } else { __GK_ClipLinkConnect(&gkwin->redraw_clip,gkwin->visible_clip); gkwin->visible_clip = NULL; } }
//----获取被修改区域----------------------------------------------------------- //功能: 获取一个窗口的被修改部分的剪切域,形成双向循环链表,链表中的clip以先 // 左->右,再上->下的顺序排列,并清零changed_msk数组。 //参数: gkwin,目标窗口 //返回: 链表指针,NULL表示窗口未被修改 //----------------------------------------------------------------------------- struct tagClipRect *__GK_GetChangedClip(struct tagGkWinRsc *gkwin) { struct tagClipRect *clip=NULL,*clip1,*tempclip,*clip_head = NULL; u8 *msk; u32 offset_bit,offset,msk_line_words; s16 loopx,loopy; bool_t start; s32 width,height; if(gkwin->change_flag == CN_GKWIN_CHANGE_ALL) //整个窗口均被修改 { clip = (struct tagClipRect *)Mb_Malloc(g_ptClipRectPool,0); if(clip != NULL) { clip->rect.left = gkwin->limit_left + gkwin->absx0; clip->rect.top = gkwin->limit_top + gkwin->absy0; clip->rect.right = gkwin->limit_right + gkwin->absx0; clip->rect.bottom = gkwin->limit_bottom + gkwin->absy0; clip->next = clip; clip->previous = clip; gkwin->change_flag = CN_GKWIN_CHANGE_NONE; return clip; //把整个窗口的可显示区域当作一个剪切域返回 } else return NULL; }else if(gkwin->change_flag == CN_GKWIN_CHANGE_NONE) //没有修改 { return NULL; }else //部分修改,先按x方向取得剪切域,再按y方向合并 { offset = 0; //首行字偏移量 msk = gkwin->changed_msk.bm_bits; width = gkwin->wm_bitmap->width; height = gkwin->wm_bitmap->height; msk_line_words = gkwin->changed_msk.linebytes; for(loopy = 0; loopy < height; loopy +=8) { start = false; //开始一段连续的被修改区域 offset_bit = 0; //起始块的位偏移 for(loopx = 0; loopx < width; loopx+=8) { if(msk[offset+offset_bit/8]&(u8)(1<<(8-(offset_bit%8)-1))) { //该块的changed flag为true。 if(start == false) //changed block开始被修改 { start = true; clip =(struct tagClipRect*)Mb_Malloc(g_ptClipRectPool,0); if(clip != NULL) { clip->rect.left = gkwin->absx0 + offset_bit*8; clip->rect.top = loopy + gkwin->absy0; clip->rect.right = clip->rect.left + 8; clip->rect.bottom = clip->rect.top + 8; } else { __GK_FreeClipQueue(clip_head); return NULL; } }else //changed block持续 { clip->rect.right += 8; } }else //如果本行的最后一块也是被改写的块,则程序不会走到这里 { if(start == true) //changed block结束 { __GK_ClipConnect(&clip_head,clip); start = false; } } offset_bit++; } //本行最后一块是被改写块,需要在这里把该区域加入被修改区域 if(start == true) __GK_ClipConnect(&clip_head,clip); offset += msk_line_words; } //至此,x方向条状clip已经生成,现在沿y方向合并 clip = clip_head; do{ clip1 = clip->next; while(clip1 != clip) { if((clip1->rect.left == clip->rect.left) &&(clip1->rect.right == clip->rect.right) &&((clip->rect.bottom)== clip1->rect.top))//可合并 { clip->rect.bottom += 8; clip1->previous->next = clip1->next; clip1->next->previous = clip1->previous; tempclip = clip1; clip1 = clip1->next; Mb_Free(g_ptClipRectPool,tempclip); }else clip1 = clip1->next; } clip = clip->next; }while(clip != clip_head); gkwin->change_flag = CN_GKWIN_CHANGE_NONE; } memset(msk,0,msk_line_words * gkwin->changed_msk.height); return clip_head; }
//----扫描可视域--------------------------------------------------------------- //功能: 1、把visible_clip备份到visible_bak中。 // 2、所有窗口生成新的visible_clip //参数: display,被扫描的显示器 //返回: false=失败,一般是因为剪切域池容量不够 //----------------------------------------------------------------------------- bool_t __GK_ScanNewVisibleClip(struct tagDisplayRsc *display) { struct tagGkWinRsc *tempwin; struct tagRectangle *rect; struct tagClipRect *clip,*clip1,*clip_head = NULL; s32 num,rect_left,rect_top,rect_right,rect_bottom,loop,temp; u8 *sort_array_x,*sort_array_y; num = (display->width+1)*sizeof(u8) + (display->height+1)*sizeof(u8); sort_array_x = M_MallocLc(num,0); if(sort_array_x == NULL) return false; sort_array_y = sort_array_x + display->width+1; memset(sort_array_x,0,num); tempwin = display->z_topmost; // rect_left = 0; // rect_top = 0; while(1) { //取窗口可视边框,该边框是窗口受祖先窗口限制后的矩形 temp = tempwin->limit_left-tempwin->left + tempwin->absx0; if(sort_array_x[temp] == 0) { sort_array_x[temp] = 1; // rect_left++; } temp = tempwin->limit_right-tempwin->left+tempwin->absx0; if(sort_array_x[temp] == 0) { sort_array_x[temp] = 1; // rect_left++; } temp = tempwin->limit_top-tempwin->top + tempwin->absy0; if(sort_array_y[temp] == 0) { sort_array_y[temp] = 1; // rect_top++; } temp = tempwin->limit_bottom-tempwin->top+tempwin->absy0; if(sort_array_y[temp] == 0) { sort_array_y[temp] = 1; // rect_top++; } //执行__GK_GetRedrawClipAll函数注释中的step1 //保存窗口原来的可视域 tempwin->visible_bak = tempwin->visible_clip; tempwin->visible_clip = NULL; if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } //处理桌面下的窗口,这些窗口肯定没有可视域 while(1) { tempwin = tempwin->z_back; if(tempwin == display->z_topmost) break; tempwin->visible_bak = tempwin->visible_clip; tempwin->visible_clip = NULL; } //按从左到右,从上到下的顺序(顺序不能改变)把所有垂直线、水平线围成的小clip //串成双向链表,由clip_head做链表头 rect_top = 0; temp = 0; for(rect_bottom =1;rect_bottom <= display->height; rect_bottom++) { if(sort_array_y[rect_bottom] == 0) continue; rect_left = 0; for(rect_right =1;rect_right <= display->width; rect_right++) { if(sort_array_x[rect_right] == 0) continue; clip = (struct tagClipRect*)Mb_Malloc(g_ptClipRectPool,0); if(clip != NULL) { clip->rect.left = rect_left; clip->rect.right = rect_right; clip->rect.top = rect_top; clip->rect.bottom = rect_bottom; rect_left = rect_right; __GK_ClipConnect(&clip_head,clip); //把小clip加入到链接起来 temp++; } else { __GK_FreeClipQueue(clip_head); free(sort_array_x); return false; //内存池不足,无法生成可视域队列 } } rect_top = rect_bottom; } free(sort_array_x); //下面判断小clip的归属,并把他们加入到所属win的new_clip队列中 tempwin = display->z_topmost; while(1) { clip = clip_head; for(loop = temp; loop >0; loop--) { rect = &(clip->rect); if((rect->left>=tempwin->limit_left-tempwin->left+tempwin->absx0) &&(rect->top>=tempwin->limit_top-tempwin->top+tempwin->absy0) &&(rect->right<=tempwin->limit_right-tempwin->left+tempwin->absx0) &&(rect->bottom<=tempwin->limit_bottom-tempwin->top+tempwin->absy0)) { //矩形在tempwin的可显示范围内,若不在则无需处理 //允许alpha或透明,区域将加入窗口可视域,但不从临时链表中删除。 if(tempwin->dest_blend) { clip1 = (struct tagClipRect*)Mb_Malloc(g_ptClipRectPool,0); if(clip1 != NULL) { *clip1 = *clip; } else { __GK_FreeClipQueue(clip_head); return false; //内存池不足,无法生成可视域队列 } }else //不允许透明和alpha,区域加入窗口可视域,从临时链表删除 { if(clip == clip_head) clip_head = clip_head->next; clip1 = clip; clip->previous->next = clip->next; clip->next->previous = clip->previous; temp--; } clip = clip->next; //把小clip加入到visible_clip队列中 __GK_ClipConnect(&tempwin->visible_clip,clip1); }else //矩形不在tpwin的可显示范围内,无需处理。 { clip = clip->next; } } __GK_CombineClip_s(tempwin->visible_clip);//合并clip,按先x后y的顺序合并 if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } return true; }
//----生成重绘区域------------------------------------------------------------- //功能: 扫描整个窗口链表,重新生成全部窗口的可视域,以及待重绘的clip,方法和过程: // 1、释放所有的visible_bak,把visible_clip转到visible_bak中。 // 2、重新生成所有win的visible_clip,并复制到 copy_clip 中临时保存。 // 3、visible_clip减去中visible_bak所得加入redraw_clip队列。剩余部分保留在 // visible_clip中。如果窗口的dest_blend == true,则visible_bak中保存 // 由可见变为不可见的部分,否则visible_bak将被释放。 // 4、从changed msk中提取changed_clip。 // 5、取visible_clip与changed_clip的交集,加入redraw_clip队列。 // 6、从z_top起,取visible_bak,扫描其后窗口的可视域,与其重叠的部分,加入 // redraw域。符合此条件的visible_bak,必定是因为窗口移开所致。 // 7、从z_top起,对dest_blend == true的win,扫描z轴中在其后面的 // win的visible_clip,与其需重绘部分重叠的,加入redraw_clip队列。 // 此后dest_blend != true的win的visible_clip可释放。 // 8、合并前几步产生的redraw_clip队列。 // 9、从z_top起,对任一dest_blend == true的win的visible_clip,扫描z轴中在其 // 后面的win的redraw_clip,重叠的部分加入redraw_clip队列,并合并之。 //参数: display,被扫描的显示器 //返回: false=失败,一般是因为剪切域池容量不够 //----------------------------------------------------------------------------- bool_t __GK_GetRedrawClipAll(struct tagDisplayRsc *display) { struct tagGkWinRsc *tempwin; struct tagGkWinRsc *special_win; struct tagClipRect *changed_clip,*tempclip1; if(display->reset_clip == true) //看是否需要重新生成可视域 { if(__GK_GetVisibleClip(display) == false) //完成step1、step2、step3 return false; display->reset_clip = false; } tempwin = display->desktop; while(1) { //扫描desktop到z_topmost之间的全部窗口,完成step4~5,在desktop后面的 //窗口不显示,或者在step1~3中已经全部转移到 redraw_clip 中,无需处理。 if(tempwin->visible_clip != NULL) { //备份visible_clip if(tempwin->copy_clip == NULL) //copy_clip可能已经在step1~3中设置了 tempwin->copy_clip = __GK_CopyClipLink(tempwin->visible_clip); //整个窗口全部被修改,整体绘制、窗口移动、拉伸、压缩会导致全体修改 //reset_clip == true成立的话,cn_gkwin_change_all的情况在 //__gk_get_visible_clip函数中已经完成,在该函数中完成,可以减轻不少 //运算量,而且对这里没有影响。 if(tempwin->change_flag == CN_GKWIN_CHANGE_ALL) { //全部可视域需重绘 __GK_ClipLinkConnect(&tempwin->redraw_clip, tempwin->visible_clip); tempwin->visible_clip = NULL; //可视域已经全部加入重绘域 tempwin->change_flag = CN_GKWIN_CHANGE_NONE; }else { //有部分修改 if(tempwin->change_flag == CN_GKWIN_CHANGE_PART) { //取得修改域 changed_clip = __GK_GetChangedClip(tempwin); //提取可视域中修改的区域 tempclip1 = __GK_GetClipLinkInts( &tempwin->visible_clip,changed_clip); __GK_FreeClipQueue(changed_clip); //把修改区域加入到redraw_clip中 __GK_ClipLinkConnect(&tempwin->redraw_clip,tempclip1); tempwin->change_flag = CN_GKWIN_CHANGE_NONE; } } // tempwin->visible_bak = NULL; } else tempwin->change_flag = CN_GKWIN_CHANGE_NONE; //清除changed_msk __GK_ShadingClear(tempwin); if(tempwin != display->z_topmost) tempwin = tempwin->z_top; else break; } //执行step6,改变位置的、dest_blend=true的窗口,改变前遮挡的其他窗口的 //可视域,加入redraw域。 special_win = display->z_topmost; while(1) { //窗口移动,伸缩会导致visible_bak != NULL if((special_win->dest_blend) && (special_win->visible_bak != NULL)) { tempwin = special_win->z_back; while(1) { // tempclip2 = __GK_CopyClipLink(special_win->visible_bak); //取得背景窗口需要重绘的区域 tempclip1 = __GK_GetClipLinkInts(&tempwin->visible_clip, special_win->visible_bak); // __GK_FreeClipQueue(tempclip2); //把修改区域加入到背景窗口redraw_clip中 __GK_ClipLinkConnect(&tempwin->redraw_clip,tempclip1); if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } special_win->visible_bak = __GK_FreeClipQueue(special_win->visible_bak); } if(special_win != display->desktop) special_win = special_win->z_back; else break; } //执行step7,窗口需要背景参与运算,此窗口内容有改变 special_win = display->z_topmost; while(1) { //hjj,step7和step9存在先后执行的情况,调用__gk_get_cliplink_ints_res //会对参数有影响(可能导致参数值改变),使用时应多做考虑 if(special_win->dest_blend) {//special_win需要背景参与运算才执行下面的程序 if(special_win->redraw_clip != NULL) { tempwin = special_win->z_back; while(1) { //取得背景窗口需要重绘的区域 tempclip1 = __GK_GetClipLinkInts(&tempwin->visible_clip, special_win->redraw_clip); //把修改区域加入到背景窗口redraw_clip中 __GK_ClipLinkConnect(&tempwin->redraw_clip,tempclip1); if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } } } else {//释放掉不需要背景参与运算的窗口的可视域 special_win->visible_clip = __GK_FreeClipQueue(special_win->visible_clip); } if(special_win != display->desktop) special_win = special_win->z_back; else break; } //执行step8,合并前几步产生的redraw_clip队列 tempwin = display->z_topmost; while(1) { //合并redraw_clip tempwin->redraw_clip = __GK_CombineClip(tempwin->redraw_clip); if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } //执行step9,本步骤无须判断desktop,故循环体有所不同 //需要背景参与运算的窗口,其背景改变 special_win = display->z_topmost; do{ if((special_win->dest_blend)&&(special_win->visible_clip != NULL)) {//special_win需要背景窗口参与运算,才执行下面的程序 tempwin = special_win; do{ tempwin = tempwin->z_back; //取得背景窗口的修改域 tempclip1 = __GK_GetClipLinkInts(&special_win->visible_clip, tempwin->redraw_clip); //把修改区域加入到窗口的redraw_clip中 __GK_ClipLinkConnect(&special_win->redraw_clip,tempclip1); }while(tempwin != display->desktop); //释放掉不需要使用的区域 special_win->visible_clip = __GK_FreeClipQueue(special_win->visible_clip); //合并redraw_clip special_win->redraw_clip = __GK_CombineClip(special_win->redraw_clip); } special_win = special_win->z_back; }while(special_win != display->desktop); //恢复visible_clip tempwin = display->z_topmost; while(1) { tempwin->visible_clip = tempwin->copy_clip; tempwin->copy_clip = NULL; if(tempwin != display->desktop) tempwin = tempwin->z_back; else break; } return true; }