22.消除图层刷新闪烁

简介

上节实现了一个简单的消息框输出字符串显示功能,但是对图层的刷新还存在可以优化的地方,尤其是在快速变化字符时将会出现图层闪烁的问题。

目标

快速显示字符串到指定图层上时没有必要在刷新图层遮住的窗体,只需要刷新窗体和该窗体之后的窗体。

1.win_sheet.c
修改sheet_refreshRect,增加sht图层窗口,表示刷新该图层及其该图层之后的窗体。

void sheet_refreshRect(SHTCTL *ctl,SHEET *sht,int x,int y,int width,int height){

	unsigned char *vram = ctl->vram;
	for(int h=sht->weight;h<=ctl->top;h++){
		SHEET *sht = ctl->sheets[h];
		//获取最大的原点
		int x0 = x > sht->x ? x : sht->x;
		int y0 = y > sht->y ? y : sht->y;

		//获取右下角最小坐标
		int x2 = x+width < sht->x+sht->width ? x+width : sht->x+sht->width;
		int y2 = y+height < sht->y+sht->height ? y+height : sht->y+sht->height;

		
		if(x2<x0 || y2<y0){//没有相交
			continue;
		}

		//(x0,y0),(x2,y2) 共同组成相交矩形

		//向显存写入相交部分的信息
		for(int i=y0;i<y2;i++){
			for(int j=x0;j<x2;j++){
				//此时的i、j是相对屏幕的坐标,图层缓冲区坐标相对自身,相当于是从(0,0)开始的
				int off = (i-sht->y)*sht->width+(j-sht->x);
				char val = sht->buf[off];
				if(val != sht->col_inv){
					vram[i*ctl->xsize+j] = val;
				}
			}
		}	
	}
}

2.os.c
增加字符显示输出背景色参数,防止下次字符显示时图层缓存区中该区域有垃圾数据。

void putChar(unsigned char *addr,int x,int y,unsigned char col,unsigned char bc,unsigned char ch,int winW){
	
	unsigned char *pch = _ascii+(ch-0x20)*16;
	for(int i=0;i<16;i++){
		unsigned char temp = pch[i];
		int off = (y+i)*winW;
		
		//显示的字形最左边的是低地址,右侧的是高地址。例如:0x80,则高地址部分显示在内存的低地址,
		//最低位的应该偏移7
		//else为了消除该像素点上一次的颜色,填充为透明色
		if((temp & 0x01) != 0){
			addr[off+x+7] = col;
		}
		else{
			addr[off+x+7] = bc;
		}

		if((temp & 0x02) != 0){
			addr[off+x+6] = col;
		}
		else{
			addr[off+x+6] = bc;
		}

		if((temp & 0x04) != 0){
			addr[off+x+5] = col;
		}
		else{
			addr[off+x+5] = bc;
		}

		if((temp & 0x08) != 0){
			addr[off+x+4] = col;
		}	
		else{
			addr[off+x+4] = bc;
		}

		if((temp & 0x10) != 0){
			addr[off+x+3] = col;
		}
		else{
			addr[off+x+3] = bc;
		}

		if((temp & 0x20) != 0){
			addr[off+x+2] = col;
		}
		else{
			addr[off+x+2] = bc;
		}

		if((temp & 0x40) != 0){
			addr[off+x+1] = col;
		}
		else{
			addr[off+x+1] = bc;
		}
	
		if((temp & 0x80) != 0){
			addr[off+x+0] = col;
		}
		else{
			addr[off+x+0] = bc;
		}
	}
}

修改showString增加字符串显示的背景色

void showString(SHTCTL *shtctl,SHEET *sht, int x, int y,unsigned char col,unsigned char bc,char *str){
	int offX = x,offY = y;
	for(int i=0;str[i] != 0;i++){
		if(offX>sht->width-8){
			offX = 0;
			offY += 16;
		}
		putChar(sht->buf,offX,offY,col,bc,str[i],sht->width);
		offX += 8;
	}
	sheet_refreshRect(shtctl,sht,sht->x,sht->y+y,sht->width,offY-y+16);
}

runloop函数实现持续输出

static void runloop(){

	AddrRangeDes *memDes = (AddrRangeDes *)mem_block_buf();
	int memCount = mem_block_count();
	int memId = -1;

	int index = 0;
	
    for(; ;){

		if(_keybufInfo.len>0){
			io_cli();
			int len = _keybufInfo.len;
			for(int t=0;t<len;t++){
				char data = fifo8_get(&_keybufInfo);
				
				if(data == 0x1c){
					
					memId++;
					if(memId==memCount){
						memId=0;
					}
					showMemInfo(memDes+memId,memId);
				}
			}

			io_sti();
		}
		else if(_mousebufInfo.len>0){
			io_cli();
			int len = _mousebufInfo.len;
			mouseCursorMoved(&_mouseDes,COLOR_INVISIBLE);

			io_sti();
		}
		else{
       		index++;
			int len = 0;
			_tempArr[len++] = '0';
			_tempArr[len++] = 'x';

			for(int j=0;j<4;j++){
				int temp = char2HexStr(((char *)&index)[3-j]);
				_tempArr[len++] = ((char *)&temp)[0];
				_tempArr[len++] = ((char *)&temp)[1];
				
			}
			_tempArr[len] = 0;
			showString(_shtctl,_shtMsg,10,54,COL8_FFFFFF,COL8_C6C6C6,_tempArr);
		}
		
    }
}

3.效果如下:
22.消除图层刷新闪烁