⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 canvas.c

📁 可能有用,是关于c++的是因为要下个软件所以随便传了一个,抱歉了.刚学c++还不会弄什么,以后一定一定传好的东西.
💻 C
字号:
#include <malloc.h>
#include <assert.h>
#include <string.h>
#include "canvas.h"

#define CANVAS_PIPELINE_EXPAND 32

struct pipe_node {
	draw_func func;
	void *object;
	int x;
	int y;
};

struct canvas_block {
	pixel *ptr;
	struct pipe_node *pipeline;
	int total_object;
	int total_last;
	int capability_pipeline;
};

struct canvas {
	int width;
	int height;
	int pitch;
	int block_w;
	int block_h;
	struct canvas_block block[1];
};

static void drawfunc_clear(pixel *ptr,int pitch,void *object,int x,int y)
{
	int i;
	for (i=0;i<CANVAS_BLOCK_HEIGHT;i++) {
		memset(ptr,0,CANVAS_BLOCK_WIDTH*sizeof(pixel));
		ptr=(pixel*)((char*)ptr+pitch);
	}
}

static void canvas_block_resize(struct canvas_block *blk)
{
	const int size=blk->capability_pipeline+CANVAS_PIPELINE_EXPAND;
	const int newsize=size*sizeof(struct pipe_node);
	blk->capability_pipeline=size;
	blk->pipeline=(struct pipe_node*)realloc(blk->pipeline,newsize);
}

static void canvas_init(struct canvas *c,pixel *ptr,draw_func flip,void *flip_object)
{
	int pitch=c->pitch;
	int i,j;
	const int w=c->width;
	const int h=c->height;
	pixel *line=ptr;
	struct canvas_block *block=c->block;
	for (i=0;i<h;i+=CANVAS_BLOCK_HEIGHT) {
		for (j=0;j<w;j+=CANVAS_BLOCK_WIDTH) {
			block->ptr=line+j;
			block->pipeline=0;
			block->capability_pipeline=0;
			canvas_block_resize(block);
			block->total_object=1;
			block->total_last=0;
			block->pipeline[0].func=flip;
			block->pipeline[0].object=flip_object;
			block->pipeline[0].x=j;
			block->pipeline[0].y=i;
			++block;
		}
		line=(pixel*)((char*)line+pitch);
	}
}

struct canvas* canvas_create(int w,int h,pixel *ptr,int pitch,draw_func flip,void *flip_object)
{
	const int nw=(w+CANVAS_BLOCK_WIDTH-1)/CANVAS_BLOCK_WIDTH;
	const int nh=(h+CANVAS_BLOCK_HEIGHT-1)/CANVAS_BLOCK_HEIGHT;
	struct canvas *c=(struct canvas *)malloc(
		sizeof(struct canvas)-sizeof(struct canvas_block)+
		sizeof(struct canvas_block)*(nw*nh)
	);

	c->width=w;
	c->height=h;
	c->block_w=nw;
	c->block_h=nh;
	c->pitch=pitch;
	canvas_init(c,ptr,flip,flip_object);
	return c;
}

void canvas_release(struct canvas *c)
{
	int i,j;
	const int w=c->block_w;
	const int h=c->block_h;
	struct canvas_block *block=c->block;
	for (i=0;i<h;i++) {
		for (j=0;j<w;j++) {
			free(block->pipeline);
			++block;
		}
	}
	free(c);
}

struct object_2d { COMMON_HEADER } ;

void canvas_draw(struct canvas *c,draw_func func,void *object,int x,int y)
{
	struct object_2d *obj=(struct object_2d *)object;
	int left,right,top,bottom;
	unsigned dirty=obj->dirty;
	if (obj->width<=0 || obj->height<=0)
		return;
	obj->dirty=0;
	left=(x-=obj->kx);
	top=(y-=obj->ky);
	right=left+obj->width-1;
	bottom=top+obj->height-1;

	// clip to canvas
	if (left<0) {
		left=0;
	}
	else if (left>=c->width) {
		return;
	}
	if (top<0) {
		top=0;
	}
	else if (top>=c->height) {
		return;
	}
	if (right>c->width-1) {
		right=c->width-1;
	}
	else if (right<0) {
		return;
	}
	if (bottom>c->height-1) {
		bottom=c->height-1;
	}
	else if (bottom<0) {
		return;
	}

	// splite to blocks
	do {
		int i,j;
		int w=right/CANVAS_BLOCK_WIDTH;
		int h=bottom/CANVAS_BLOCK_HEIGHT;
		int from_x=left/CANVAS_BLOCK_WIDTH;
		int from_y=top/CANVAS_BLOCK_HEIGHT;
		struct canvas_block *block=&c->block[from_y*c->block_w];
		for (i=from_y;i<=h;i++) {
			for (j=from_x;j<=w;j++) {
				struct canvas_block *blk=&block[j];
				struct pipe_node *node;
				if (blk->total_object==blk->capability_pipeline) {
					canvas_block_resize(blk);
				}
				node=&blk->pipeline[blk->total_object++];
				node->func=func;
				node->object=object;
				node->x=x-j*CANVAS_BLOCK_WIDTH;
				node->y=y-i*CANVAS_BLOCK_HEIGHT;
				blk->total_last|=dirty;
			}
			block+=c->block_w;
		}
	} while(0);
}

void canvas_update(struct canvas *c)
{
	int i,j;
	struct canvas_block *blk=c->block;
	int pitch=c->pitch;
	for (i=c->block_w*c->block_h;i>0;--i,++blk) {
		if (blk->total_object!=blk->total_last) {
			pixel *ptr=blk->ptr;
			drawfunc_clear(ptr,pitch,0,0,0);
			for (j=blk->total_object-1;j>=0;j--) {
				struct pipe_node *node=&blk->pipeline[j];
				node->func(ptr,pitch,node->object,node->x,node->y);
			}
			blk->total_last=blk->total_object;
		}
		blk->total_object=1;
	}
}

void canvas_redraw(struct canvas *c)
{
	int i;
	struct canvas_block *blk=c->block;
	int pitch=c->pitch;
	for (i=c->block_w*c->block_h;i>0;--i,++blk) {
		blk->total_last=0;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -