《操作系统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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值