QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: asmcos

窗口裁减

[复制链接]
发表于 2006-9-22 14:52:55 | 显示全部楼层
这个无法应付复杂的环境,会导致闪烁问题。

[quote:71c99277d6="danath"]为什么一定需要裁减矩形呢?

我尝试过的办法是:

1. 基于屏幕标记脏区域
2. 处理脏区域时计算所有与之有交叠的窗口
3. 按照Z序从下往上绘制[/quote]
回复

使用道具 举报

发表于 2006-10-6 16:47:53 | 显示全部楼层
[quote:12cbeebd41="linuxre"]这个无法应付复杂的环境,会导致闪烁问题。

[quote:12cbeebd41="danath"]为什么一定需要裁减矩形呢?

我尝试过的办法是:

1. 基于屏幕标记脏区域
2. 处理脏区域时计算所有与之有交叠的窗口
3. 按照Z序从下往上绘制[/quote][/quote]

这个办法原理上也是基于双缓冲的,我自己也试过,没有闪烁.
回复

使用道具 举报

发表于 2006-12-12 22:31:26 | 显示全部楼层
我觉得这样想是复杂化了;
楼主考察下我的方法怎么样!我也正在搞类似的东西。
目前正在慢慢实现,由于工作才不久时间,加上非计算机专业毕业,所以多半时间用到工作上,以免被老板炒了:)!进度很慢。

我的方法是,首先,保存一个全局RECT指针,并分配初始大小为SIZE的内存;

注:重绘的发生,要么窗口Z坐标改变要么被移动、打开、关闭(最前端,Z最大)的窗口裁剪;

1.被新打开的窗口裁剪

      不需要重绘其他窗口,只需绘制打开的窗口;

2.被移动后或关闭的窗口裁减

     计算出移动矩形的偏移,得到最多两个矩形,存入全局RECT指针的空间,

RECT指针依Z坐标向下传递,如果和下一Z坐标的窗口不发生裁剪,继续向下传递;

如果被裁减,计算裁剪后的区域,分割成几个矩形,存入RECT指针的空间,再向下传递,

直到Z坐标等于0(桌面窗口)或RECT的所有矩形被完全分割完。

此方法只需要一套单纯考虑两个矩形各种方式裁剪的算法;我在之前发的画线算法楼主有机会看看,不是说算法好坏,我觉得我考虑问题的方式可以让楼主借鉴,比方说画线想到的是画直线,让他自己找在某区域应该要怎么画,而不是画指定区域的线段。
回复

使用道具 举报

发表于 2006-12-12 22:35:56 | 显示全部楼层
新打开,关闭,和改变某窗口Z坐标(一般改变到最大,即当前窗口),这是一类。
移动是一类。
两类,呵呵,上面错了一点。
回复

使用道具 举报

发表于 2006-12-12 22:44:15 | 显示全部楼层
还是分类错误,关闭和移动一类的,需要重绘其它窗口,但发不发生重绘视情况而定
回复

使用道具 举报

发表于 2006-12-12 23:02:28 | 显示全部楼层
不过画窗口中的运动的时针需要别的方法,不然可能导致大量不必要的计算,呵呵,还没考虑好怎么实现。或许自身运动的重绘需要保存可见区效率才能高点。
回复

使用道具 举报

发表于 2006-12-13 10:35:32 | 显示全部楼层
今天天亮才回家,在车上想了个办法解决窗口中本身运动物体的重绘,另外分配一个和屏幕一样大小的矩形区域的内存块,以窗口的ID值依Z序来填充窗口区域,投影到XY面(屏幕),得到以Z序覆盖的标志各窗口的可见区,
1.在窗口不移动情况下不更新Z序时,绘点只需要先查看该点ID值是否和窗口本身ID值相同,决定是否需要重绘。TOPMOST则不检查。
2.如果窗口只更新Z序,直接覆盖写到对应区与上;然后用1法重绘。
3.移动或关闭TOPMOST窗口,用我以上帖内容的方法先计算更新整个标志区(加点改进,结合现在用的标志区,应该不需要RECT指针这个方法)。
回复

使用道具 举报

 楼主| 发表于 2006-12-13 13:00:42 | 显示全部楼层
我以前是用的
:另外分配一个和屏幕一样大小的矩形区域的内存块,以窗口的ID值依Z序来填充窗口区域,

但是有个问题,当窗口发生是,要获取窗口的尺寸,轮询窗口的ID。效率也不快。

后来看X window.等其他的窗口的实现。
就写成了现在的 eGUI的代码。


我现在正在做eGUI窗口的拖动,和关闭。
这类算法。我会参考Xwindow.

如果您有什么高见,欢迎讨论。
回复

使用道具 举报

 楼主| 发表于 2006-12-13 13:03:58 | 显示全部楼层
eGUI 现在正在支持 gtk 1.0.0 。
回复

使用道具 举报

发表于 2006-12-13 13:58:38 | 显示全部楼层
//画屏幕水平直线,不检查合法性;
void Screen_Draw_Hline(int y, int x0,int x1, int Color);
//取得水平直线在矩形中合法的水平线段;
void Get_Rect_Hline(RECT *rect,int *y, int *x0,int *x1);
//在矩形中画水平直线;要求合法的矩形(在屏幕内);
void Draw_Rect_Hline(RECT *rect,int y, int x0,int x1, int Color);
//取得窗口中需要更新的矩形(在屏幕内);
void Get_Window_Invalidated(WINDOW *window,RECT *rect,int nrect);
//在窗口中画水平直线;
void Draw_Window_Hline(WINDOW *window,int y, int x0,int x1, int Color);

void Screen_Draw_Hline(int y, int x0,int x1, int Color)
{
        //用的FRAMMEBUFFER,BPP=16;
        unsigned short *offset = Screen.baseaddr + Screen.width * y + x0;
        while(x0 <= x1)
        {
                *offset++ = Color;
        }
}

void Get_Rect_Hline(RECT *rect,int *y, int *x0,int *x1);
{
        if(*y < rect->y0 || *y > rect->y1)
        {
                *y = -1;
                return;
        }
        if((*x0< rect->x0 && *x1< rect->x0) || (*x0 > rect->x1 && *x1 > rect->x1))
        {
                *y = -1;
                return;
        }
       
        if(*x0 > *x1)
        {
                temp = *x0;
                x0         = *x1;
                *x1         = temp;
        }
       
        if(*x0 < rect->x0)
        {
                *x0 = rect->x0;
        }
        if(*x1 > rect->x1)
        {
                *x1 = rect->x1;
        }
}

void Draw_Rect_Hline(RECT *rect,int y, int x0,int x1, int Color)
{
        Get_Rect_Hline(rect, &y, &x0, &x1);
        if(y>0)
        {
                Screen_Draw_Hline(y, x0, x1, Color);
        }
}

void Get_Window_Invalidated(WINDOW *window,RECT *rect,int nrect)
{
        //暂时没想好,因为我还没想好窗口因该定义成什么样的结构比较合适。
        //目前想到,因该有个屏幕和所有窗口的全局MASK表,等等,还没定下来。
}

void Draw_Window_Hline(WINDOW *window,int y, int x0,int x1, int Color)
{
        int nrect;
        RECT *prect;
        Get_Window_Invalidated(window,prect,&nrect);
        for(;nrect>0;nrect--)
        {
                Draw_Rect_Hline(prect+nrect-1, y, x0, x1, Color);
        }
        free(prect);
}
回复

使用道具 举报

发表于 2006-12-13 14:07:30 | 显示全部楼层
我相信我的这段代码的思路可以让很多人收益,因为一个思考模式和设计模式的问题,不仅方便以后写代码,而且,不容易让人在复杂情况下昏头,可以简单化复杂事情,虽然在简单情况下复杂化了,貌似看起来不值得这样做!
回复

使用道具 举报

发表于 2006-12-13 14:28:08 | 显示全部楼层
比方说你要让窗口更新指定区域,而其它画线画什么的都已经用了,不然要知道更新指定区域,需要大量计算,还要考虑周全,从代码上也不够简洁!参数又容易搞硬编码。

我想问楼主,如果你要对某窗口指定区域进行更新,其他画线函数参数有不便更改,你是怎么做的?我还没仔细看你的关于重绘的代码。一般都是自己有方案之后再参考别人的,不然参考成习惯,然后就不喜欢动脑了。再者这样可以很清晰看到自己思维方式和别人有什么不同。:)
我觉得的MICROSOFT能够方便实现指定更新区域,搞法肯定和我的类似,以及我觉得他的PAINT消息后的重绘,就是直接调用相同代码向屏幕上绘的,而不需要绘到别的地方,再复制到屏幕的。
回复

使用道具 举报

发表于 2006-12-13 14:34:47 | 显示全部楼层
有个地方搞错了,刚写的代码,呵呵,
Get_Window_Invalidated,返回RECT指针或者,传入RECT **rect;
不好意思刚写的代码,仓促了点!
回复

使用道具 举报

 楼主| 发表于 2006-12-14 12:13:50 | 显示全部楼层
void Get_Window_Invalidated(WINDOW *window,RECT *rect,int nrect)
{
//暂时没想好,因为我还没想好窗口因该定义成什么样的结构比较合适。
//目前想到,因该有个屏幕和所有窗口的全局MASK表,等等,还没定下来。
}


确实有些难度.

我会给你画一张图说明此问题。
回复

使用道具 举报

 楼主| 发表于 2006-12-14 12:16:54 | 显示全部楼层
其实,只有横线不用画点。可以通过memcpy来实现。

竖线,斜线最终都要用画点来实现。 还是最后在画点里判断。是否显示比较好。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-29 07:25 , Processed in 0.070740 second(s), 13 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表