简介
前面绘制的鼠标在移动时会擦除已有的图像,实现图像的重叠效果需要对图像分层。 图像叠加处理的原理很简单,就是给图像分层,从低下往上面画,便可以实现叠加的效果。 计算机桌面上有三个窗口程序,A、B、C。B位于A之上,C位于B之上。要实现这种效果,只需要先画A(盖住了桌面一部分)、再画B(盖住了A和桌面一部分)、再画C(盖住了B和桌面一部分)。
目标
新建图层窗口管理器:
win_sheet.h:
#ifndef WIN_SHEET_H
#define WIN_SHEET_H
#include "memman.h"
//图层的数据结构
typedef struct _SHEET {
unsigned char *buf;
int width, height, x, y, col_inv, weight, flags;
}SHEET;
/*
buf用来记录图层上所描画内容的地址。
图层的整体大小:width、height。
图层在画面上位置的坐标:x、y。
col_inv为透明色色号。
weight 为图层显示层级权重
flags用于存放有关图层的各种设定信息。(使用状况)
*/
#define MAX_SHEETS 256
typedef struct _SHTCTL {
unsigned char *vram;
int xsize, ysize, top;
SHEET *sheets[MAX_SHEETS];
SHEET sheets0[MAX_SHEETS];
}SHTCTL;
#define SIZE_OF_SHEET 32
#define SIZE_OF_SHTCTL 9232
SHTCTL *shtctl_init(MEMMAN *memman, unsigned char *vram,int xsize, int ysize);
SHEET *sheet_alloc(SHTCTL *ctl);
void sheet_free(SHTCTL *ctl,SHEET *sht);
void sheet_setRect(int x,int y,int width,int height,int col_inv,SHEET *sht, unsigned char *buf);
void sheet_setWeight(SHTCTL *ctl,SHEET *sht, int weight);
int sheet_refresh(SHTCTL *ctl);
void sheet_slide(SHTCTL *ctl,SHEET *sht, int vx0, int vy0);
#endif
win_sheet.c:
#include "win_sheet.h"
#define SHEET_FREE 0
#define SHEET_USE 1
SHTCTL *shtctl_init(MEMMAN *memman, unsigned char *vram,int xsize, int ysize){
SHTCTL *ctl = (SHTCTL *)mem_alloc(memman, SIZE_OF_SHTCTL);
if (ctl == 0) {
return 0;
}
ctl->vram = vram;
ctl->xsize = xsize;
ctl->ysize = ysize;
ctl->top = -1;
for (int i = 0; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = SHEET_FREE;
}
return ctl;
}
SHEET *sheet_alloc(SHTCTL *ctl){
SHEET *sht;
for (int i = 0; i < MAX_SHEETS; i++) {
if (ctl->sheets0[i].flags == 0) {
sht = &ctl->sheets0[i];
ctl->sheets[i] = sht;
sht->flags = SHEET_USE;//标记为正在使用
sht->weight = -1; //隐藏
return sht;
}
}
return 0;
}
void sheet_free(SHTCTL *ctl,SHEET *sht){
sheet_setWeight(ctl,sht,-1);
sht->weight = -1;
sht->flags = SHEET_FREE;
}
void sheet_setRect(int x,int y,int width,int height,int col_inv,SHEET *sht, unsigned char *buf){
sht->x = x;
sht->y = y;
sht->width = width;
sht->height = height;
sht->buf = buf;
sht->col_inv = col_inv;
}
void sheet_setWeight(SHTCTL *ctl,SHEET *sht, int weight){
//存储设置前的窗口权重信息
int old = sht->weight;
//进行修正
if (weight > ctl->top + 1) {
weight = ctl->top + 1;
}
if (weight < -1) {
weight = -1;
}
sht->weight = weight;
int h;
if (old > weight) {//窗口往管理器数组前面移动
if (weight >= 0) {//还需要显示,只是显示在相对底层
for (h = old; h > weight; h--) {//weight之后old之间的数据往数组后面搬移
ctl->sheets[h] = ctl->sheets[h-1];
ctl->sheets[h]->weight = h;
}
ctl->sheets[weight] = sht;
} else {//不需要显示了
if (ctl->top > old) {
for (h = old; h < ctl->top; h++) {//old 位置被old后面的数据覆盖
ctl->sheets[h] = ctl->sheets[h+1];
ctl->sheets[h]->weight = h;
}
}
ctl->top--;
}
} else if (old < weight) {//窗口向管理器数组后面移动
if (old >= 0) {//该窗口原来也是显示的
for (h = old; h < weight; h++) {
ctl->sheets[h] = ctl->sheets[h + 1];
ctl->sheets[h]->weight = h;
}
ctl->sheets[weight] = sht;
} else {//需要