作者在 2009-06-30 12:51:23 发布以下内容
浅析μC/GUI-v3.90a之WM_ITERATE_START剪切域计算宏
浅析μC/GUI-v3.90a之WM_ITERATE_START剪切域计算宏
文章来源:http://gliethttp.cublog.cn
接续《浅析μC/GUI-v3.90a之GUI_DispString函数》讨论WM_ITERATE_START剪切域计算宏
//剪切域宗旨:本hWin内部被控件占用的部分不用绘制;窗体Z序中比本hWin窗体高的窗体遮盖住本hWin的部分不用绘制;
//本hWin超出parent窗体边界的部分不用绘制;窗体的窗体Z序比本hWin的parent窗体高的窗体遮盖住本hWin需要绘制的部分不需要绘制;
//这就是剪切域绘制的宗旨,让绘制部分最小,通过复杂的cpu计算,避免窗体互相遮盖部分的重复绘制,提高显式速度,增加lcd使用寿命.[gliethttp]
//计算完剪切域之后,通过WM__ActivateClipRect()将会使_ClipContext.CurRect传递给GUI_Context.ClipRect,最终影响绘图的有效空间
//拿对当前hWin进行GUI_Clear()来说,剪切域的绘制顺序是上到下窄条依次绘制,在上到下的过程中又会由左到右依次计算绘制
-------------------------------------------------------------------------------------
1.
...
{
r = *pr;
#if GUI_WINSUPPORT
WM_ADDORG(r.x0, r.y0);
WM_ADDORG(r.x1, r.y1); //平移矩形r
WM_ITERATE_START(&r) { //计算r矩形区域内的剪切域
#endif
GUI_Context.DispPosX = r.x0;
GUI_Context.DispPosY = r.y0;
_DispLine(s, MaxNumChars, &r);
#if GUI_WINSUPPORT
} WM_ITERATE_END();
#endif
}
...
-------------------------------------------------------------------------------------
2.WM_ITERATE_START宏
gui/wm/WM_GUI.h
#define WM_ITERATE_START(pRect) \
{ \
if (WM__InitIVRSearch(pRect)) \ //构造循环体
do {
-------------------------------------------------------------------------------------
3.WM__InitIVRSearch()函数
gui/wm/WM.c
int WM__InitIVRSearch(const GUI_RECT* pMaxRect) {
GUI_RECT r;
WM_Obj* pAWin;
GUI_ASSERT_LOCK();
if (WM_IsActive==0) {
WM__ActivateClipRect();
return 1;
}
if (++_ClipContext.EntranceCnt > 1) //如果重入,返回,保持计算操作的唯一性
return 1;
pAWin = WM_H2P(GUI_Context.hAWin); //当前句柄,详情请参考《浅析μC/GUI-v3.98之WM_H2P()句柄hWin转内存函数》
_ClipContext.Cnt = -1;
if (WM__PaintCallbackCnt) { //从回调函数进入的剪切计算
WM__GetInvalidRectAbs(pAWin, &r); //r=pWin->InvalidRect;r存放pWin失效矩形区
} else {
if (pAWin->Status & WM_SF_ISVIS) {
r = pAWin->Rect; //不是回调函数引起的剪切计算,那么整个pWin窗体作为失效区域
} else {
--_ClipContext.EntranceCnt; //窗体属性为不可见
return 0;
}
}
if (pMaxRect) {
GUI__IntersectRect(&r, pMaxRect); //r依据pMaxRect,缩小自己的矩形区域
}
/* If user has reduced the cliprect size, reduce the rectangle */
if (GUI_Context.WM__pUserClipRect) {
WM_Obj* pWin = pAWin; //用户指定了失效重绘区域,那么继续缩小r的矩形区域
GUI_RECT rUser = *(GUI_Context.WM__pUserClipRect);
#if WM_SUPPORT_TRANSPARENCY
if (WM__hATransWindow) { //具有半透明属性
pWin = WM_H2P(WM__hATransWindow);
}
#endif
WM__Client2Screen(pWin, &rUser); //以pWin(x0,y0)位坐标原点,平移rUser矩形
GUI__IntersectRect(&r, &rUser); //继续缩小r矩形区
}
#if WM_SUPPORT_TRANSPARENCY
if (WM__hATransWindow) { //如果有半透明窗体,那么需要继续缩小剪切域r
if (WM__ClipAtParentBorders(&r, WM__hATransWindow) == 0) {
--_ClipContext.EntranceCnt;
return 0;
}
}
#endif
//主要进行如下五步操作:
//一.以上所有工作主要是是计算当前激活窗体hWin自身与pMaxRect的平面剪切区域r,
//二.接下来WM__ClipAtParentBorders()函数完成和hWin所有父窗体边框剪切,如果有一个父窗体属性为不可见,直接0退出
if (WM__ClipAtParentBorders(&r, GUI_Context.hAWin) == 0) {
--_ClipContext.EntranceCnt;
return 0;
}
_ClipContext.ClientRect = r; //保存r重绘区域到IVR专用单元_ClipContext.ClientRect
return WM__GetNextIVR(); //hWin自己的、所有父窗体的同级兄弟窗体与该r进行平面、三维立体z序混合剪切
} //pWin->hNext其实从窗口Z序来讲,是在pWin上面的控件,而不把pWin->hNext叫作hWin的兄弟
//pWin->hNext以及hNext->hNext都有权力覆盖hWin窗体,因为他们在窗口Z序的比hWin更靠近顶层处
-------------------------------------------------------------------------------------
4.WM__GetInvalidRectAbs()函数
gui/wm/WM.c
static void WM__GetInvalidRectAbs(WM_Obj* pWin, GUI_RECT* pRect) {
*pRect = pWin->InvalidRect;
}
-------------------------------------------------------------------------------------
5.WM__GetNextIVR()函数
gui/wm/WM.c
int WM__GetNextIVR(void) {
#if GUI_SUPPORT_CURSOR
static char _CursorHidden;
#endif
if (WM_IsActive==0) {
return 0;
}
if (_ClipContext.EntranceCnt > 1) {
_ClipContext.EntranceCnt--;
return 0;
} //非法性检查
#if GUI_SUPPORT_CURSOR
if (_CursorHidden) {
_CursorHidden = 0;
(*GUI_CURSOR_pfTempUnhide) (); //如果当前鼠标,即上一次进入时鼠标不可见,那么显示鼠标
}
#endif
++_ClipContext.Cnt;
/* Find next rectangle and use it as ClipRect */
//三.与窗口Z序比hWin->parent大的窗体进行剪切计算,缩小本次hWin绘制的区域
//四.与窗口Z序比hWin大的窗体进行剪切计算,继续缩小本次hWin绘制的区域
//五.与hWin窗体内部所有Child控件进行剪切计算,继继续缩小本次hWin绘制的区域
if (!_FindNext_IVR()) { //见函数6的注解
_ClipContext.EntranceCnt--;
return 0;
}
WM__ActivateClipRect();
/* Hide cursor if necessary */
#if GUI_SUPPORT_CURSOR
if (GUI_CURSOR_pfTempHide) {
_CursorHidden = (*GUI_CURSOR_pfTempHide) ( &_ClipContext.CurRect);
}
#endif
return 1;
}
-------------------------------------------------------------------------------------
6._FindNext_IVR()函数
//2007-07-11 gliethttp宗旨就是:本hWin内部被控件占用的部分不用绘制,窗体Z序中比本hWin窗体高的窗体遮盖住本hWin的部分不用绘制
//本hWin超出parent窗体边界的部分不用绘制,窗体的窗体Z序比本hWin的parent窗体高的窗体遮盖住本hWin需要绘制的部分不需要绘制
//这样就是剪切域绘制的宗旨了,让绘制部分最小,通过复杂的cpu计算,避免窗体遮盖部分的重复绘制,提高显式速度,增加lcd使用寿命.
gui/wm/WM.c
static int _FindNext_IVR(void) {
WM_HMEM hParent;
GUI_RECT r;
WM_Obj* pAWin;
WM_Obj* pParent;
r = _ClipContext.CurRect;
//1.设置r的初始化值
if (_ClipContext.Cnt == 0) { //如果从WM__InitIVRSearch()->WM__GetNextIVR()->_FindNext_IVR()进入
r.x0 = _ClipContext.ClientRect.x0; //那么_ClipContext.Cnt==0成立,将WM__InitIVRSearch()计算的存储到_ClipContext.ClientRect的剪切域
r.y0 = _ClipContext.ClientRect.y0; //读取到r中
} else {
r.x0 = _ClipContext.CurRect.x1+1; //接续上一已经绘制的窄条剪切域,继续进行其它窄条剪切域的计算
r.y0 = _ClipContext.CurRect.y0; //绘制顺序是上到下窄条依次绘制,在上到下的过程中又会由左到右依次计算绘制
if (r.x0 > _ClipContext.ClientRect.x1) {
NextStripe: /* go down to next stripe */
r.x0 = _ClipContext.ClientRect.x0;
r.y0 = _ClipContext.CurRect.y1+1;
}
}
//2.检测剪切计算完成否
if (r.y0 >_ClipContext.ClientRect.y1) {
return 0;
}
//3.寻找pRect->y1这个下边沿在所有和pRect存在剪切关系控件窗体中的最小位置,即:"r.y1靠上计算"
pAWin = WM_H2P(GUI_Context.hAWin);
if (r.x0 == _ClipContext.ClientRect.x0) {
r.y1 = _ClipContext.ClientRect.y1;
r.x1 = _ClipContext.ClientRect.x1;
/* Iterate over all windows which are above */
/* Check all siblings above (Iterate over Parents and top siblings (hNext) */
for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
//_Findy1就是寻找pRect->y1这个下边沿的最小位置
pParent = WM_H2P(hParent); //计算GUI_Context.hAWin自己的哥们窗体[Z序比hWin高的窗口],
_Findy1(pParent->hNext, &r, NULL); //和父窗体的哥们窗体分别和r剪切域[Z序比老爹高的窗口]
//2007-07-11 gliethttp _Findy1()计算pParent->hNext和hNext->hNext等窗口Z序比pParent窗口Z序大的r剪切域
//举例:如A,B两个窗口,A窗口Z序比B窗口Z序大,那么A就在B的上面,A可以覆盖B,但B不能覆盖A,因为A窗口Z序比B窗口Z序大
}
/* Check all children */
_Findy1(pAWin->hFirstChild, &r, NULL); //对pWin窗体内部的所有孩子控件进行同样的r剪切计算
}
//4.调整pRect->x0到所有存在剪切关系的控件窗口的最右边rWinClipped.x1+1处,即:"r.x0靠右计算"
Find_x0:
r.x1 = r.x0;
{
hParent = GUI_Context.hAWin;
}
for (; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
if (_Findx0(pParent->hNext, &r, NULL)) {
goto Find_x0; //如果pParent的窗口Z序上层中存在和该r剪切区域,调整r.x0到
} //相应窗口Z序对应窗口的x1+1处,goto Find_x0继续计算接下来的pParent
} //就这样一直将r.x0调整到所有与r存在剪切关系的窗口Z序上层窗体的右边x1+1处
/* Check all children */
if (_Findx0(pAWin->hFirstChild, &r, NULL)) { //在自己hWin窗体内的所有孩子控件进行r.x0靠右计算
goto Find_x0;
}
//5.如果r.x0 > r.x1即,r的右边框,那么该窄条剪切域完毕.goto NextStripe去找下一个窄条剪切域
r.x1 = _ClipContext.ClientRect.x1; //恢复"r.x0靠右计算"中破坏了的r.x1
if (r.x1 < r.x0) {
_ClipContext.CurRect = r;
goto NextStripe; //x0过界,计算下一个需要重绘窄条剪切域
}
//6.调整pRect->x1到所有存在剪切关系的控件窗口的最左边rWinClipped.x0-1处,即:"r.x1靠左计算"
{
hParent = GUI_Context.hAWin;
}
for (; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
_Findx1(pParent->hNext, &r, NULL);
}
/* Check all children */
_Findx1(pAWin->hFirstChild, &r, NULL); //在自己hWin窗体内的所有孩子控件进行r.x1靠左计算
if (_ClipContext.Cnt >200) {
return 0; //最大嵌套数目
}
_ClipContext.CurRect = r;
return 1; //2007-07-11 gliethttp计算完毕;通过WM__ActivateClipRect()将会使
} //_ClipContext.CurRect传递给GUI_Context.ClipRect,来影响绘图的有效空间
-------------------------------------------------------------------------------------
6._Findy1()函数
gui/wm/WM.c
static void _Findy1(WM_HWIN iWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin; //_Findy1就是寻找pRect->y1这个下边沿的最小位置
for (; iWin; iWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找y1.
int Status = (pWin = WM_H2P(iWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) { //指定了剪切参考
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect; //pWin->Rect作为剪切参考
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
if (pWin->Rect.y0 > pRect->y0) {
ASSIGN_IF_LESS(pRect->y1, rWinClipped.y0 - 1); //将pRect->y1和rWinClipped矩形的上边延y0对齐
} else {
ASSIGN_IF_LESS(pRect->y1, rWinClipped.y1); //将pRect->y1和rWinClipped矩形的下边延y1对齐
}
} else {
/* Check all children*/
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
_Findy1(hChild, pRect, &rWinClipped);
}
}
}
}
}
}
-------------------------------------------------------------------------------------
6._Findx0()函数
gui/wm/WM.c
static int _Findx0(WM_HWIN hWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin;
int r = 0;
for (; hWin; hWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找x0.
int Status = (pWin = WM_H2P(hWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) {
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect;
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
pRect->x0 = rWinClipped.x1+1; //调整pRect->x0到所有存在剪切关系的控件窗口的右边rWinClipped.x1+1处
r = 1;
} else {
/* Check all children */ //半透明处理
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
if (_Findx0(hChild, pRect, &rWinClipped)) {
r = 1;
}
}
}
}
}
}
return r;
}
-------------------------------------------------------------------------------------
6._Findx1()函数
static void _Findx1(WM_HWIN hWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin;
for (; hWin; hWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找x1.
int Status = (pWin = WM_H2P(hWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) {
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect;
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
pRect->x1 = rWinClipped.x0-1; //调整pRect->x1到所有存在剪切关系的控件窗口的左边rWinClipped.x0-1处
} else {
/* Check all children */ //半透明处理
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
_Findx1(hChild, pRect, &rWinClipped);
}
}
}
}
}
}
//剪切域宗旨:本hWin内部被控件占用的部分不用绘制;窗体Z序中比本hWin窗体高的窗体遮盖住本hWin的部分不用绘制;
//本hWin超出parent窗体边界的部分不用绘制;窗体的窗体Z序比本hWin的parent窗体高的窗体遮盖住本hWin需要绘制的部分不需要绘制;
//这就是剪切域绘制的宗旨,让绘制部分最小,通过复杂的cpu计算,避免窗体互相遮盖部分的重复绘制,提高显式速度,增加lcd使用寿命.[gliethttp]
//计算完剪切域之后,通过WM__ActivateClipRect()将会使_ClipContext.CurRect传递给GUI_Context.ClipRect,最终影响绘图的有效空间
//拿对当前hWin进行GUI_Clear()来说,剪切域的绘制顺序是上到下窄条依次绘制,在上到下的过程中又会由左到右依次计算绘制
-------------------------------------------------------------------------------------
1.
...
{
r = *pr;
#if GUI_WINSUPPORT
WM_ADDORG(r.x0, r.y0);
WM_ADDORG(r.x1, r.y1); //平移矩形r
WM_ITERATE_START(&r) { //计算r矩形区域内的剪切域
#endif
GUI_Context.DispPosX = r.x0;
GUI_Context.DispPosY = r.y0;
_DispLine(s, MaxNumChars, &r);
#if GUI_WINSUPPORT
} WM_ITERATE_END();
#endif
}
...
-------------------------------------------------------------------------------------
2.WM_ITERATE_START宏
gui/wm/WM_GUI.h
#define WM_ITERATE_START(pRect) \
{ \
if (WM__InitIVRSearch(pRect)) \ //构造循环体
do {
-------------------------------------------------------------------------------------
3.WM__InitIVRSearch()函数
gui/wm/WM.c
int WM__InitIVRSearch(const GUI_RECT* pMaxRect) {
GUI_RECT r;
WM_Obj* pAWin;
GUI_ASSERT_LOCK();
if (WM_IsActive==0) {
WM__ActivateClipRect();
return 1;
}
if (++_ClipContext.EntranceCnt > 1) //如果重入,返回,保持计算操作的唯一性
return 1;
pAWin = WM_H2P(GUI_Context.hAWin); //当前句柄,详情请参考《浅析μC/GUI-v3.98之WM_H2P()句柄hWin转内存函数》
_ClipContext.Cnt = -1;
if (WM__PaintCallbackCnt) { //从回调函数进入的剪切计算
WM__GetInvalidRectAbs(pAWin, &r); //r=pWin->InvalidRect;r存放pWin失效矩形区
} else {
if (pAWin->Status & WM_SF_ISVIS) {
r = pAWin->Rect; //不是回调函数引起的剪切计算,那么整个pWin窗体作为失效区域
} else {
--_ClipContext.EntranceCnt; //窗体属性为不可见
return 0;
}
}
if (pMaxRect) {
GUI__IntersectRect(&r, pMaxRect); //r依据pMaxRect,缩小自己的矩形区域
}
/* If user has reduced the cliprect size, reduce the rectangle */
if (GUI_Context.WM__pUserClipRect) {
WM_Obj* pWin = pAWin; //用户指定了失效重绘区域,那么继续缩小r的矩形区域
GUI_RECT rUser = *(GUI_Context.WM__pUserClipRect);
#if WM_SUPPORT_TRANSPARENCY
if (WM__hATransWindow) { //具有半透明属性
pWin = WM_H2P(WM__hATransWindow);
}
#endif
WM__Client2Screen(pWin, &rUser); //以pWin(x0,y0)位坐标原点,平移rUser矩形
GUI__IntersectRect(&r, &rUser); //继续缩小r矩形区
}
#if WM_SUPPORT_TRANSPARENCY
if (WM__hATransWindow) { //如果有半透明窗体,那么需要继续缩小剪切域r
if (WM__ClipAtParentBorders(&r, WM__hATransWindow) == 0) {
--_ClipContext.EntranceCnt;
return 0;
}
}
#endif
//主要进行如下五步操作:
//一.以上所有工作主要是是计算当前激活窗体hWin自身与pMaxRect的平面剪切区域r,
//二.接下来WM__ClipAtParentBorders()函数完成和hWin所有父窗体边框剪切,如果有一个父窗体属性为不可见,直接0退出
if (WM__ClipAtParentBorders(&r, GUI_Context.hAWin) == 0) {
--_ClipContext.EntranceCnt;
return 0;
}
_ClipContext.ClientRect = r; //保存r重绘区域到IVR专用单元_ClipContext.ClientRect
return WM__GetNextIVR(); //hWin自己的、所有父窗体的同级兄弟窗体与该r进行平面、三维立体z序混合剪切
} //pWin->hNext其实从窗口Z序来讲,是在pWin上面的控件,而不把pWin->hNext叫作hWin的兄弟
//pWin->hNext以及hNext->hNext都有权力覆盖hWin窗体,因为他们在窗口Z序的比hWin更靠近顶层处
-------------------------------------------------------------------------------------
4.WM__GetInvalidRectAbs()函数
gui/wm/WM.c
static void WM__GetInvalidRectAbs(WM_Obj* pWin, GUI_RECT* pRect) {
*pRect = pWin->InvalidRect;
}
-------------------------------------------------------------------------------------
5.WM__GetNextIVR()函数
gui/wm/WM.c
int WM__GetNextIVR(void) {
#if GUI_SUPPORT_CURSOR
static char _CursorHidden;
#endif
if (WM_IsActive==0) {
return 0;
}
if (_ClipContext.EntranceCnt > 1) {
_ClipContext.EntranceCnt--;
return 0;
} //非法性检查
#if GUI_SUPPORT_CURSOR
if (_CursorHidden) {
_CursorHidden = 0;
(*GUI_CURSOR_pfTempUnhide) (); //如果当前鼠标,即上一次进入时鼠标不可见,那么显示鼠标
}
#endif
++_ClipContext.Cnt;
/* Find next rectangle and use it as ClipRect */
//三.与窗口Z序比hWin->parent大的窗体进行剪切计算,缩小本次hWin绘制的区域
//四.与窗口Z序比hWin大的窗体进行剪切计算,继续缩小本次hWin绘制的区域
//五.与hWin窗体内部所有Child控件进行剪切计算,继继续缩小本次hWin绘制的区域
if (!_FindNext_IVR()) { //见函数6的注解
_ClipContext.EntranceCnt--;
return 0;
}
WM__ActivateClipRect();
/* Hide cursor if necessary */
#if GUI_SUPPORT_CURSOR
if (GUI_CURSOR_pfTempHide) {
_CursorHidden = (*GUI_CURSOR_pfTempHide) ( &_ClipContext.CurRect);
}
#endif
return 1;
}
-------------------------------------------------------------------------------------
6._FindNext_IVR()函数
//2007-07-11 gliethttp宗旨就是:本hWin内部被控件占用的部分不用绘制,窗体Z序中比本hWin窗体高的窗体遮盖住本hWin的部分不用绘制
//本hWin超出parent窗体边界的部分不用绘制,窗体的窗体Z序比本hWin的parent窗体高的窗体遮盖住本hWin需要绘制的部分不需要绘制
//这样就是剪切域绘制的宗旨了,让绘制部分最小,通过复杂的cpu计算,避免窗体遮盖部分的重复绘制,提高显式速度,增加lcd使用寿命.
gui/wm/WM.c
static int _FindNext_IVR(void) {
WM_HMEM hParent;
GUI_RECT r;
WM_Obj* pAWin;
WM_Obj* pParent;
r = _ClipContext.CurRect;
//1.设置r的初始化值
if (_ClipContext.Cnt == 0) { //如果从WM__InitIVRSearch()->WM__GetNextIVR()->_FindNext_IVR()进入
r.x0 = _ClipContext.ClientRect.x0; //那么_ClipContext.Cnt==0成立,将WM__InitIVRSearch()计算的存储到_ClipContext.ClientRect的剪切域
r.y0 = _ClipContext.ClientRect.y0; //读取到r中
} else {
r.x0 = _ClipContext.CurRect.x1+1; //接续上一已经绘制的窄条剪切域,继续进行其它窄条剪切域的计算
r.y0 = _ClipContext.CurRect.y0; //绘制顺序是上到下窄条依次绘制,在上到下的过程中又会由左到右依次计算绘制
if (r.x0 > _ClipContext.ClientRect.x1) {
NextStripe: /* go down to next stripe */
r.x0 = _ClipContext.ClientRect.x0;
r.y0 = _ClipContext.CurRect.y1+1;
}
}
//2.检测剪切计算完成否
if (r.y0 >_ClipContext.ClientRect.y1) {
return 0;
}
//3.寻找pRect->y1这个下边沿在所有和pRect存在剪切关系控件窗体中的最小位置,即:"r.y1靠上计算"
pAWin = WM_H2P(GUI_Context.hAWin);
if (r.x0 == _ClipContext.ClientRect.x0) {
r.y1 = _ClipContext.ClientRect.y1;
r.x1 = _ClipContext.ClientRect.x1;
/* Iterate over all windows which are above */
/* Check all siblings above (Iterate over Parents and top siblings (hNext) */
for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
//_Findy1就是寻找pRect->y1这个下边沿的最小位置
pParent = WM_H2P(hParent); //计算GUI_Context.hAWin自己的哥们窗体[Z序比hWin高的窗口],
_Findy1(pParent->hNext, &r, NULL); //和父窗体的哥们窗体分别和r剪切域[Z序比老爹高的窗口]
//2007-07-11 gliethttp _Findy1()计算pParent->hNext和hNext->hNext等窗口Z序比pParent窗口Z序大的r剪切域
//举例:如A,B两个窗口,A窗口Z序比B窗口Z序大,那么A就在B的上面,A可以覆盖B,但B不能覆盖A,因为A窗口Z序比B窗口Z序大
}
/* Check all children */
_Findy1(pAWin->hFirstChild, &r, NULL); //对pWin窗体内部的所有孩子控件进行同样的r剪切计算
}
//4.调整pRect->x0到所有存在剪切关系的控件窗口的最右边rWinClipped.x1+1处,即:"r.x0靠右计算"
Find_x0:
r.x1 = r.x0;
{
hParent = GUI_Context.hAWin;
}
for (; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
if (_Findx0(pParent->hNext, &r, NULL)) {
goto Find_x0; //如果pParent的窗口Z序上层中存在和该r剪切区域,调整r.x0到
} //相应窗口Z序对应窗口的x1+1处,goto Find_x0继续计算接下来的pParent
} //就这样一直将r.x0调整到所有与r存在剪切关系的窗口Z序上层窗体的右边x1+1处
/* Check all children */
if (_Findx0(pAWin->hFirstChild, &r, NULL)) { //在自己hWin窗体内的所有孩子控件进行r.x0靠右计算
goto Find_x0;
}
//5.如果r.x0 > r.x1即,r的右边框,那么该窄条剪切域完毕.goto NextStripe去找下一个窄条剪切域
r.x1 = _ClipContext.ClientRect.x1; //恢复"r.x0靠右计算"中破坏了的r.x1
if (r.x1 < r.x0) {
_ClipContext.CurRect = r;
goto NextStripe; //x0过界,计算下一个需要重绘窄条剪切域
}
//6.调整pRect->x1到所有存在剪切关系的控件窗口的最左边rWinClipped.x0-1处,即:"r.x1靠左计算"
{
hParent = GUI_Context.hAWin;
}
for (; hParent; hParent = pParent->hParent) {
pParent = WM_H2P(hParent);
_Findx1(pParent->hNext, &r, NULL);
}
/* Check all children */
_Findx1(pAWin->hFirstChild, &r, NULL); //在自己hWin窗体内的所有孩子控件进行r.x1靠左计算
if (_ClipContext.Cnt >200) {
return 0; //最大嵌套数目
}
_ClipContext.CurRect = r;
return 1; //2007-07-11 gliethttp计算完毕;通过WM__ActivateClipRect()将会使
} //_ClipContext.CurRect传递给GUI_Context.ClipRect,来影响绘图的有效空间
-------------------------------------------------------------------------------------
6._Findy1()函数
gui/wm/WM.c
static void _Findy1(WM_HWIN iWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin; //_Findy1就是寻找pRect->y1这个下边沿的最小位置
for (; iWin; iWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找y1.
int Status = (pWin = WM_H2P(iWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) { //指定了剪切参考
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect; //pWin->Rect作为剪切参考
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
if (pWin->Rect.y0 > pRect->y0) {
ASSIGN_IF_LESS(pRect->y1, rWinClipped.y0 - 1); //将pRect->y1和rWinClipped矩形的上边延y0对齐
} else {
ASSIGN_IF_LESS(pRect->y1, rWinClipped.y1); //将pRect->y1和rWinClipped矩形的下边延y1对齐
}
} else {
/* Check all children*/
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
_Findy1(hChild, pRect, &rWinClipped);
}
}
}
}
}
}
-------------------------------------------------------------------------------------
6._Findx0()函数
gui/wm/WM.c
static int _Findx0(WM_HWIN hWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin;
int r = 0;
for (; hWin; hWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找x0.
int Status = (pWin = WM_H2P(hWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) {
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect;
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
pRect->x0 = rWinClipped.x1+1; //调整pRect->x0到所有存在剪切关系的控件窗口的右边rWinClipped.x1+1处
r = 1;
} else {
/* Check all children */ //半透明处理
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
if (_Findx0(hChild, pRect, &rWinClipped)) {
r = 1;
}
}
}
}
}
}
return r;
}
-------------------------------------------------------------------------------------
6._Findx1()函数
static void _Findx1(WM_HWIN hWin, GUI_RECT* pRect, GUI_RECT* pParentRect) {
WM_Obj* pWin;
for (; hWin; hWin = pWin->hNext) { //窗体z序比hWin高的所有窗体中,剪切遮盖住本pRect的部分[gliethttp]:找x1.
int Status = (pWin = WM_H2P(hWin))->Status;
if (Status & WM_SF_ISVIS) {
GUI_RECT rWinClipped;
if (pParentRect) {
GUI__IntersectRects(&rWinClipped, &pWin->Rect, pParentRect);
} else {
rWinClipped = pWin->Rect;
}
if (GUI_RectsIntersect(pRect, &rWinClipped)) {
if ((Status & WM_SF_HASTRANS) == 0) {
pRect->x1 = rWinClipped.x0-1; //调整pRect->x1到所有存在剪切关系的控件窗口的左边rWinClipped.x0-1处
} else {
/* Check all children */ //半透明处理
WM_HWIN hChild;
WM_Obj* pChild;
for (hChild = pWin->hFirstChild; hChild; hChild = pChild->hNext) {
pChild = WM_H2P(hChild);
_Findx1(hChild, pRect, &rWinClipped);
}
}
}
}
}
}