11.8 消除闪烁(2)(harib08h)
ps:看书比较急,有错误的地方欢迎指正,不细致的地方我会持续的修改
11.8 消除闪烁(2)(harib08h)
11.7 消除闪烁(1)(harib08g)存在的问题: 鼠标放在计时器上会有 闪烁,产生原因:会先绘制计时器,再绘制鼠标
书上的解决办法:
创造一个类VRAM,存储 图层号码,用于绘制。优点:似乎也可以同时解决点击问题。缺点:占内存,变复杂
另一种解决办法:
对 sheet_refresh进行改造,若指定图层上方有与指定图层相交的图层,则不再重绘 相交的区域
需考虑:1.如何判断其上有要显示的图层
struct SHEET *sheet_havehigher(struct SHEET *sht)//判断sht图层上是否有更高的图层
{
struct SHTCTL *ctl;
ctl=sht->ctl;
int i;
i=sht->height;
for (i ; i < MAX_SHEETS; i++) {
if (ctl->sheets0[i].flags == 1) {
return 1; //有
}
}
return 0;//无
}*/
void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1)
{
if (sht->height >= 0) {
if(sheet_havehigher(sht)==0){/*这里!*/
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height);
}else{/*这里!*/
sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height+1);
}
}
return;
}
上面的代码 sheet_havehigher用于判断指定图层上方有没有图层,sheet_refresh用于重绘
但上面的代码并没有解决闪烁问题,反而出现以下问题
数字不会变化,上方的数字也没有变化,只有鼠标滑过其上方才会重绘
上方代码的不足:
我们应该判断指定图层的上方指定区域内有没有比他更高的图层,且是此图层刷新后也需要刷新的,但这里却错误的判断了图层,即也许指定图层的绘制区域在中间,但比他图层高的鼠标在角落,二者并没有相交,也不会绘制指定区域。
结论:单纯利用图层高度无法判断,无法判断遮罩
疑问
在之前对sheet_refreshsub的优化中,似乎已经处理了重叠时的重新描画问题,为什么此处还是因为重绘高速计数器所在的层出现了问题
- 以下对书上的解决办法进行说明
先对 bootpack.h和sheet.c进行修改,增加map (书P214)
- sheet_refreshmap
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, sid, *map = ctl->map;
struct SHEET *sht;
if (vx0 < 0) { vx0 = 0; }
if (vy0 < 0) { vy0 = 0; }
if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }
if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }
for (h = h0; h <= ctl->top; h++) {
sht = ctl->sheets[h];
sid = sht - ctl->sheets0; /* 将进行了减法的地址作为图层号码使用 */
buf = sht->buf;
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < 0) { bx0 = 0; }
if (by0 < 0) { by0 = 0; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
if (buf[by * sht->bxsize + bx] != sht->col_inv) {
map[vy * ctl->xsize + vx] = sid;
}
}
}
}
return;
}
作用:从下至上输入map,buf经过多次修改(覆盖),最终buf中的数据即为屏幕上所显示的图层的图层号
- sheet_refreshsub
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
{
int h, bx, by, vx, vy, bx0, by0, bx1, by1;
unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;
struct SHEET *sht;
/* 如果refresh的范围超出了画面则修正 */
if (vx0 < 0) { vx0 = 0; }
if (vy0 < 0) { vy0 = 0; }
if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }
if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }
for (h = h0; h <= h1; h++) {
sht = ctl->sheets[h];
buf = sht->buf;
sid = sht - ctl->sheets0;
/* 利用vx0~vy1,对bx0~by1进行倒推 */
bx0 = vx0 - sht->vx0;
by0 = vy0 - sht->vy0;
bx1 = vx1 - sht->vx0;
by1 = vy1 - sht->vy0;
if (bx0 < 0) { bx0 = 0; }
if (by0 < 0) { by0 = 0; }
if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
if (by1 > sht->bysize) { by1 = sht->bysize; }
for (by = by0; by < by1; by++) {
vy = sht->vy0 + by;
for (bx = bx0; bx < bx1; bx++) {
vx = sht->vx0 + bx;
if (map[vy * ctl->xsize + vx] == sid) {
/* 如果该层的图层号码与map中的相同,则显示 */
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
}
}
}
}
return;
}
sheet_refreshsub的作用:
根据map中的信息,来绘制
注意:形参有所优化,增加h1,因为有时不需要刷新到最上层,目前不理解在调用函数时是怎么确定h2的,另外,如书中所言,此时未考虑透明与不透明之间的转换
sheet_updown的优化也较为简单,看书P218即可
总结:
产生闪烁的原因,在第一次是因为刷新时会按顺序连指定图层的下方的图层也一起进行刷新,而在第二次是因为会刷新指定图层上方的也需刷新的图层(如鼠标),这样两次刷新会产生闪烁。第一次的解决方案,为缩小从下到上刷新的范围,即之刷新指定图层以上,但这并不能解决第二次的问题。由此产生第二次的解决方案,即书上的方案,另外存储屏幕上显示画面是由哪个图层提供的信息。这就好比,以前我们是用很多张大小不一的纸张叠起来,从一面来看画面,而现在变成了,用拼图(图层的一部分)拼出整个画面。从这个角度,我在上面的疑问中提到的“如何判断其上有要显示的图层”,其解决办法就是书中使用的map,那么还有其他方法吗?不增加map可以做到吗?或者不像map这样记录的过多?现在暂时想不到其他解决方案。
11.8 消除闪烁(2)(harib08h)的更多相关文章
- Java中用双缓冲技术消除闪烁
在Java编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的paint(Graphics)方法,在方法中使用GUI函数实现窗口重绘的过程.连贯变换的窗口会不断地调用update(Graphi ...
- Java swing JFrame用repaint出现闪烁的问题解决
这几天用swing写登录页面背景动图的时候发现一直会有闪烁(我的类是继承JFrame),就来搜原因后发现好像是因为repaint会调用update()方法中的清屏操作导致闪烁. 我当时看的是这个文章 ...
- angular的时间指令 以及防止闪烁问题
1.点击事件 <!doctype html><html lang="en"><head> <meta charset="UTF- ...
- Wtl之奇技淫巧篇:一、SDI如何居中显示视图
Wtl的sdi应用,视图默认铺满框架的客户区.视图通常用modeless对话框,所有的界面元素都拥挤在左上角,这明显很丑陋.我们尝试让视图居中显示,保持原始大小,这是个很典型的问题,看似简单,诸多细节 ...
- 《30天自制操作系统》11_day_学习笔记
harib08a: 鼠标的显示问题:我们可以看到,鼠标移到窗口最右侧之后就不能再移动了,而WIN中,鼠标是可以移动到最右边隐藏起来的.怎么办?把鼠标指针显示的范围扩宽就行!我们来修改一下HariMai ...
- 转:YUV RGB 常见视频格式解析
转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而Y ...
- YUV格式具体解释
YUV是指亮度參量和色度參量分开表示的像素格式,而这样分开的优点就是不但能够避免相互干扰,还能够减少色度的採样率而不会对图像质量影响太大.YUV是一个比較笼统地说法,针对它的详细排列方式,能够分为非常 ...
- YUY格式
YUV格式有两大类:planar和packed. 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V. 对于packed的YUV格式,每个像素点的Y ...
- 图像处理之基础---yuv420及其rgb,bayer, yuv, RGB的相互转换详解
YUV格式解析1(播放器——project2) 根据板卡api设计实现yuv420格式的视频播放器 打开*.mp4;*.264类型的文件,实现其播放. 使用的视频格式是YUV420格式 YUV格式 ...
- 模拟试题A
模拟试题A 一.单项选择题(2′*12=24′) 1.下面各种坐标变换中,会产生变换前后维度的改变的是( ) A)建模变换 B)观察变换 C)投影变换 D)视口变换 2.下列描述深度缓冲消隐算法的特点 ...
随机推荐
- React工程化实践之UI组件库
分享日期: 2022-11-08 分享内容: 组件不是 React 特有的概念,但是 React 将组件化的思想发扬光大,可谓用到了极致.良好的组件设计会是良好的应用开发基础,这一讲就让我们谈一谈Re ...
- AD9834配置
SPI设置 注意,虽然手册上CPOL(CLK空闲时电平)为低,但实测是是高电平 连接 SYNC 为片选引脚,使用时拉低 FSE/PSE为频率与相位寄存器选择,均拉低即可 void SPI_Write_ ...
- python pip 下载库速度慢,2命令永久解决
背景:pip 下载速度慢,超时 加速:永久性2条命令,拿去不谢 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/si ...
- Spring Cloud学习记录
Eureka和zookeeper都是注册中心为什么zookeeper不适合? 1.CAP原则.一致性,可用性,分区容错性,最多满足两种.zookeeper遵循CP原则,实际项目中不应该为了一致性失去可 ...
- latex常见的错误(自己经常出现的)
1. undifned control consequence 有非法的命令---有可能没有导入对应的宏包.见latex常用的宏包. 2. See the amsmath package docum ...
- create-react-app react 使用dll抽离公共库,大幅缩减项目体积,及项目打包速度
1.安装依赖(clean-webpack-plugin.add-asset-html-webpack-plugin.webpack-cli) yarn add clean-webpack-plugin ...
- postgresql Extract 函数的使用
Extract 属于 SQL 的 DML(即数据库管理语言)函数,同样,InterBase 也支持 Extract,它主要用于从一个日期或时间型的字段内抽取年.月.日.时.分.秒数据,因此,它支持其关 ...
- hexo相对路径图片显示
说明 hexo的图片默认不支持相对路径.需要配置 post_asset_folder 选项,设置从false改成true之后支持.但是要求图片目录必须和文件名相同. 由于我在typore下的markd ...
- NOIP2014普及组
T2]比例简化 其实比较简单,主要是比较的方法以前没看过吧 要学会知识迁移啊! #include<iostream> #include<cstring> #include< ...
- Laravel安装第一步:Windows 10 上laravel下载与安装需要注意。
1.下载了laravel,查看composer.json文件,搞清楚它需要的PHP版本 2.不要用 composer install !!! 用 composer -vvv install 这样 ...