《操作系统30天》-合川秀实-学习日志day11
这次的日志就不把书上的东西照搬过来了,写一点关于这个纸娃娃操作系统的理解。
一、添加一个窗口图层有哪些步骤?(格式:文字说明+对应代码)
第一步:定义图层包 (结构体SHTCTL),建立图层(SHEET),建立缓冲区buf(地址)
第二步:初始化图层
第三步:分配内存
第四步:初始化图层背景(把图层写进显卡)+内容初始化(图层内容填充)
第五步:设置图层显示位置的起始坐标(X0,Y0)+设置图层高度
二、教材202页,为什么鼠标移动到最右边后左边会出现鼠标图案,为什么右边只有一个鼠标,左边却有很多?
我们由上一天内容知道,图层移动的时候会调用sheet_refreshsub()和sheet_slide这两个函数:
对鼠标的刷新:
我们知道鼠标的坐标是经过修正的,所以传入的old图层的起始位置其实是在合理范围内。
查看refreshsub函数:
对我们有用的是最后的显示部分,因为不管鼠标在哪显示,都用用到像素点
如果按照书上的方法修改,根据像素点公式(一维计算)会导致刷新的像素点往后偏移16位(相当于往右),所以在屏幕左边会出现鼠标。对刷新old图层来说,传入的参数vx0=mx和vx1>xsize,对新图层来说,也是vx0=mx和vx1>xize,而且老图层和新图层的vx1值是相同的,因为当我们把鼠标放到最右边的时候,传入的mx都是同一个值,所以计算出的vx1也是同一个值(mx+16),这个时候两次调用的bx1相同,会先刷新一次老的,再刷新一次新的,那还是在原来的位置,所以鼠标只能在左边的固定范围内出现。刷新的时候因为屏幕的背景是按照一样的计算公式填充的,所以在边界移动的时候会有痕迹保留,也就说old的值还存在背景中,背景图层在刷新的时候会把“遗留”下来的一起刷新,可能是鼠标的颜色,也可能是黑色,验证我的说法:
改正方法:在sheet_refreshsub函数里面的循环刷新之前,添加判断
三、教材216页,每个图层的sid是如何设置的?具体数值等于多少?
Sid变量首次出现在sheet_refreshmap函数中,保存的是每个图层相对于sheets0的位置,作者给出的解释是减法计算得出的(地址)图层号码,所以说实际上sid是一个地址,是sheet ID的缩写,出现在函数中是这种形式:
图像形式:相当于一个图层体包含的多个图层每个图层有固定的地址,用当前图层的地址减去最下面图层的地址就可以得出当前的sid号了
可以理解成图层的标号1,2,3………
四、教材216-217页,结合代码,解释刷新函数(sheet_refreshsub)的参数和实现逻辑。
Ctl是表示保存图层的结构体,坐标值就是传入大小(vx0,vy0)->(vx1,vy1),h0表示从h0层开始刷新map,直到h1层。
实现逻辑:若h0=1,h1=3当绘制图层1(sid)时,遍历map,遇到1时绘制,否则不绘制;之后绘制图层2,遍历map,遇到2进行绘制;同理,图层3也是。在count计数中,每一次计数后的画面绘制中,只需要遍历map,绘制计数窗口的图层就可以了,消除了鼠标闪烁。
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的范围超出了画面则修正 */
for (h = h0; h <= h1; h++) {
/*只刷新h0-h1范围内的图层*/
sht = ctl->sheets[h];
buf = sht->buf;
sid = sht - ctl->sheets0;
/*计算每个图层的sid,在下面的叠加部分进行刷新*/
/* 利用vx0~vy1对bx0~by1进行倒推*/
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) {
/* 判断是否可以绘制(比如说当前图层号码为2,那么只绘制2那层)*/
vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];
}
}
}
}
return;
}
五、教材217页,结合代码,解释滑动函数(sheet_slide)的参数和实现逻辑,注意内部调用sheet_refreshmap和sheet_refreshsub时的传参,特别是高度参数,为什么这样传。
slide函数实现的是图层的滑动,刷新移动前的位置,再刷新移动后的位置
void sheet_slide(struct SHEET *sht, int vx0, int vy0)
{
struct SHTCTL *ctl = sht->ctl;
int old_vx0 = sht->vx0, old_vy0 = sht->vy0;
sht->vx0 = vx0;
sht->vy0 = vy0;
/* old_vx0,old_vy0表示原来的图层*/
/* vx0,vy0表示新的图层*/
if (sht->height >= 0) { /* 如果正在显示,按照新图层的信息进行刷新*/
sheet_refreshmap(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize, 0);
/* 绘制原来图层位置的新地图,因为是原来的位置,图层移走了,无法判断图层移动之后的情况,所有要从0开始刷新 */
sheet_refreshmap(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize, sht->height);
/* 绘制新图层位置的新地图,新地图只需要从当前的高度开始刷新,下面的被覆盖不用刷新,只需要刷新高度以上的 */
sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize, 0, sht->height - 1);
/* 原来位置的地图发生了改变(刷新),所以相应的我的图层要根据地图来刷新 */
sheet_refreshsub(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize, sht->height, sht->height);
/* 新的图层地图只是在新图层的高度以上进行了刷新,所以新高度的地图已经绘制好了,直接按照地图刷新当前这一高度的图层就可以了 */
}
return;
}