19.分层实现窗口叠加

本文介绍如何通过图层窗口管理器实现图像叠加效果,涉及win_sheet.h/c的创建,内存管理模块的调整,图形显示的优化,以及makefile的引入以简化编译过程。在内存管理方面修复了以前的bug,并展示了运行效果,确保了系统健壮性。
摘要由CSDN通过智能技术生成

简介

前面绘制的鼠标在移动时会擦除已有的图像,实现图像的重叠效果需要对图像分层。 图像叠加处理的原理很简单,就是给图像分层,从低下往上面画,便可以实现叠加的效果。 计算机桌面上有三个窗口程序,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 {//需要
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值