随便找个GUI中的绘图函数,就可以大致看出他的做法:
/*********************************************************************
*
* GUI_DrawLine
*/
void GUI_DrawLine(int x0, int y0, int x1, int y1) {
GUI_LOCK();
#if (GUI_WINSUPPORT)
WM_ADDORG(x0,y0);
WM_ADDORG(x1,y1);
WM_ITERATE_START(NULL); {
#endif
GL_DrawLine (x0, y0, x1, y1);
#if (GUI_WINSUPPORT)
} WM_ITERATE_END();
#endif
GUI_UNLOCK();
}
支持窗体就是支持了剪切,简单的这么理解吧!所以WM_ADDORG()、WM_ITERATE_START()和WM_ITERATE_END()可以看作是支持裁剪需要调用的几个函数。
#define WM_ADDORGX(x) x += GUI_Context.xOff
#define WM_ADDORGY(y) y += GUI_Context.yOff
#define WM_ADDORG(x0,y0) WM_ADDORGX(x0); WM_ADDORGY(y0)
这里通过WM_SelectWindow选择窗体,设置GUI_Context中的xOff和yOff。在绘制图形之前调用WM_ADDORG就可以将窗体的这个起始坐标加上去了,这样就实现了在不同窗体上的绘制。
接着是WM_ITERATE_START:
#define WM_ITERATE_START(pRect) \
{ \
if (WM__InitIVRSearch(pRect)) \
do {
#define WM_ITERATE_END() \
} while (WM__GetNextIVR()); \
}
这里主要涉及到两个函数,WM__InitIVRSearch()和WM__GetNextIVR()。WM__InitIVRSearch()函数不用细看,就干最后两句:
_ClipContext.ClientRect = r;
return WM__GetNextIVR();
如果是有效窗体,则直接返回存在有效区域,如果没有则找到第一个剪切区域r,保存在ClipContext.ClientRect中,然后调用WM__GetNextIVR()来找下一个有效区域。
同样也是看最后几行:
_ClipContext.CurRect = r;
保存在_ClipContext.CurRect 中。
◎支持GUI_WINSUPPORT才能支持区域裁剪,所以很多地方可以查找GUI_WINSUPPORT来判断哪部分代码与裁剪相关
◎GUI_Context这个全局变量包含了LCD相关信息、GL相关信息、字符相关信息、窗体相关信息、内存设备相关信息、抗锯齿相关信息。
◎ucgui中带裁剪的图形绘制是通过两个步骤实现,首先是IVR(无效区域)的查找,在每找到一个无效区域之后对所绘图形进行裁剪。(minigui中是找到所有之后再逐个绘制的)
◎_ClipContext为剪切过程中使用的一个临时变量
阅读(2665) | 评论(0) | 转发(0) |