1. 显示到屏幕上的图形界面信息要分层,比如最顶层是鼠标,中间是应用程序,最低是桌面。
2. 移动鼠标和窗口应用可以看为是移动图层。
3. 屏幕显示的原理是向显存内写信息,显存的地址在0x000a0000这个已经在前面见过了。
/*一个图层结构体*/
struct SHEET
{
unsigned char* buf;/*图层内容地址*/
int bxsize,bysize;/*图层大小*/
int vx0,vy0;/*图层在屏幕上位置*/
int col_inv;/*色号(调色板)*/
int height;/*图层高度*/
int flag;/*设定信息*/
};
/*管理多个图层结构体*/
#define MAX_SHEETS 256
struct SHTCTL
{
unsigned char *vram;/*VRAM地址*/
int xsize,ysize;/*屏幕宽高*/
int top;/*最上图层高度*/
struct SHEET * sheets[MAX_SHEETS];/*下面的图层信息混乱,所以按照高度进行排序*/
struct SHEET sheets0[MAX_SHEETS];/*保存所有图层信息*/
};
4. 内存空间的分配应使用前面学过的知识,不使用static分配,初始化图层管理节点,一次性分配足够大的管理空间
#define SHEET_USE 1
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
{
struct SHTCTL *ctl;
int i;
ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
if (ctl == 0) {
goto err;
}
ctl->vram = vram;
ctl->xsize = xsize;
ctl->ysize = ysize;
ctl->top = -1;
for (i = 0; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = 0;
}
err:
return ctl;
}
5. 生成未使用的图层,从已经分配管理图层中找到一个空闲的标记占用
struct SHEET *sheet_alloc(struct SHTCTL *ctl)
{
struct SHEET *sht;
int i;
for (i = 0; i < MAX_SHEETS; i++) {
if (ctl->sheets0[i].flags == 0) {
sht = &ctl->sheets0[i];
sht->flags = SHEET_USE;
sht->height = -1;
return sht;
}
}
return 0;
}
6. 设置图层,指定图层显示缓存区及其大小等
void sheet_setbuf(struct SHEET *sht, unsigned char *buf, int xsize, int ysize, int col_inv)
{
sht->buf = buf;
sht->bxsize = xsize;
sht->bysize = ysize;
sht->col_inv = col_inv;
return;
}
7. 设定某个图层的高度
void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height)
{
int h, old = sht->height;
/*修正高度*/
if (height > ctl->top + 1) {
height = ctl->top + 1;
}
if (height < -1) {
height = -1;
}
sht->height = height;
/*对sheets重新排列,线性数组的前后移动操作,不难*/
if (old > height) {
if (height >= 0) {
for (h = old; h > height; h--) {
ctl->sheets[h] = ctl->sheets[h - 1];
ctl->sheets[h]->height = h;
}
ctl->sheets[height] = sht;
} else {
if (ctl->top > old) {
for (h = old; h < ctl->top; h++) {
ctl->sheets[h] = ctl->sheets[h + 1];
ctl->sheets[h]->height = h;
}
}
ctl->top--;
}
sheet_refresh(ctl);
} else if (old < height) {
if (old >= 0) {
for (h = old; h < height; h++) {
ctl->sheets[h] = ctl->sheets[h + 1];
ctl->sheets[h]->height = h;
}
ctl->sheets[height] = sht;
} else {
for (h = ctl->top; h >= height; h--) {
ctl->sheets[h + 1] = ctl->sheets[h];
ctl->sheets[h + 1]->height = h + 1;
}
ctl->sheets[height] = sht;
ctl->top++;
}
sheet_refresh(ctl);
}
return;
}
8. 刷新各图层,写入显存,这个需要优化
void sheet_refresh(struct SHTCTL *ctl)
{
int h, bx, by, vx, vy;
unsigned char *buf, c, *vram = ctl->vram;
struct SHEET *sht;
for (h = 0; h <= ctl->top; h++) {
sht = ctl->sheets[h];
buf = sht->buf;
for (by = 0; by < sht->bysize; by++) {
vy = sht->vy0 + by;
for (bx = 0; bx < sht->bxsize; bx++) {
vx = sht->vx0 + bx;
c = buf[by * sht->bxsize + bx];
if (c != sht->col_inv) {
vram[vy * ctl->xsize + vx] = c;
}
}
}
}
return;
}
9. 移动图层
void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0)
{
sht->vx0 = vx0;
sht->vy0 = vy0;
if (sht->height >= 0) {
sheet_refresh(ctl);
}
return;
}
10. 释放图层
void sheet_free(struct SHTCTL* ctl,struct SHEET* sht)
{
if(sht->height>=0)
{
sheet_updown(ctl,sht,-1);
}
sht->flags=0;
return ;
}
11.优化略(计算得到图层交叉部分重绘,其它不用绘)