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

📄 stencil.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / software 2D rasterizer module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *		 */#include "rast_soft.h"EVGStencil *evg_solid_brush();EVGStencil *evg_gf_sr_texture_brush();EVGStencil *evg_linear_gradient_brush();EVGStencil *evg_radial_gradient_brush();GF_Color color_interpolate(u32 a, u32 b, u8 pos) { 	u32 ca = ((a>>24)     )*(u32)(0xFF-pos)+((b>>24)     )*(u32)pos;	u32 cr = ((a>>16)&0xFF)*(u32)(0xFF-pos)+((b>>16)&0xFF)*(u32)pos;	u32 cg = ((a>> 8)&0xFF)*(u32)(0xFF-pos)+((b>> 8)&0xFF)*(u32)pos;	u32 cb = ((a    )&0xFF)*(u32)(0xFF-pos)+((b    )&0xFF)*(u32)pos;	return	(((ca+(ca>>8)+1)>>8)<<24)|			(((cr+(cr>>8)+1)>>8)<<16)|			(((cg+(cg>>8)+1)>>8)<< 8)|			(((cb+(cb>>8)+1)>>8)    );}/*	Generic gradient tools*/#define EVGGRADIENTBUFFERSIZE	(1<<EVGGRADIENTBITS)#define EVGGRADIENTMAXINTPOS		EVGGRADIENTBUFFERSIZE - 1static void gradient_update(EVG_BaseGradient *_this){	s32 i, c;	s32 start, end, diff;	Fixed maxPos = INT2FIX(EVGGRADIENTMAXINTPOS);	if (_this->pos[0]>=0) {		if(_this->pos[0]>0) {			end = FIX2INT(gf_mulfix(_this->pos[0], maxPos));			for (i=0; i<= end;i++) {				_this->pre[i] = _this->col[0];			}		}		for (c=0; c<EVGGRADIENTSLOTS;c++) {			if (_this->pos[c]<0) break;			if (_this->pos[c+1]>=0) {				start = FIX2INT(gf_mulfix(_this->pos[c], maxPos));				end = FIX2INT(gf_mulfix(_this->pos[c+1], maxPos));				diff = end-start;				if (diff) {					for (i=start;i<=end;i++) {						_this->pre[i] = color_interpolate(_this->col[c], _this->col[c+1],							(u8) ( ( (i-start) * 255) / diff) );					}				}			} else {				start = FIX2INT(gf_mulfix(_this->pos[c+0], maxPos));				for(i=start;i<=EVGGRADIENTMAXINTPOS;i++) {					_this->pre[i] = _this->col[c];				}			}		}	}}static u32 gradient_get_color(EVG_BaseGradient *_this, s32 pos) {	s32 max_pos = 1 << EVGGRADIENTBITS;	switch (_this->mod) {	case GF_GRADIENT_MODE_SPREAD:		if (pos<0) pos = -pos;		return _this->pre[(pos & max_pos) ?  EVGGRADIENTMAXINTPOS - (pos % max_pos) :  pos % max_pos];	case GF_GRADIENT_MODE_REPEAT:		while (pos < 0) pos += max_pos;		return _this->pre[pos % max_pos];	case GF_GRADIENT_MODE_PAD:	default:		return _this->pre[ MIN(EVGGRADIENTMAXINTPOS, MAX((s32) 0, pos))];	}}GF_Err evg_stencil_set_gradient_interpolation(GF_STENCIL p, Fixed *pos, GF_Color *col, u32 count){	EVG_BaseGradient *_this = (EVG_BaseGradient *) p;	if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;	if (count>=EVGGRADIENTSLOTS-1) return GF_OUT_OF_MEM;	memcpy(_this->col, col, sizeof(GF_Color) * count);	memcpy(_this->pos, pos, sizeof(Fixed) * count);	_this->col[count] = 0;	_this->pos[count] = -FIX_ONE;	gradient_update(_this);	return GF_OK;}GF_Err evg_stencil_set_gradient_mode(GF_STENCIL p, GF_GradientMode mode){	EVG_BaseGradient *_this = (EVG_BaseGradient *) p;	if ( (_this->type != GF_STENCIL_LINEAR_GRADIENT) && (_this->type != GF_STENCIL_RADIAL_GRADIENT) ) return GF_BAD_PARAM;	_this->mod = mode;	return GF_OK;}/*	Generic stencil*/GF_STENCIL evg_stencil_new(GF_Raster2D *_dr, GF_StencilType type){	EVGStencil *st;	switch (type) {	case GF_STENCIL_SOLID:		st = evg_solid_brush();		break;	case GF_STENCIL_LINEAR_GRADIENT:		st = evg_linear_gradient_brush();		break;	case GF_STENCIL_RADIAL_GRADIENT:		st = evg_radial_gradient_brush();		break;	case GF_STENCIL_TEXTURE:		st = evg_gf_sr_texture_brush();		break;	default:		return 0L;	}	if (st) {		gf_mx2d_init(st->pmat);		gf_mx2d_init(st->smat);		gf_cmx_init(&st->cmat);	}	return st;}void evg_stencil_delete(GF_STENCIL st){	EVGStencil *_this = (EVGStencil *) st;	switch(_this->type) {	case GF_STENCIL_SOLID:	case GF_STENCIL_LINEAR_GRADIENT:	case GF_STENCIL_RADIAL_GRADIENT:		free(_this);		return;	case GF_STENCIL_TEXTURE:	{		EVG_Texture *tx = (EVG_Texture *)_this;		/*destroy conversion buffer if any*/		if ( tx->conv_buf) free( tx->conv_buf );		/*destroy local texture iof any*/		if (tx->owns_texture && tx->pixels) free(tx->pixels);		free(_this);	}		return;	}}GF_Err evg_stencil_set_matrix(GF_STENCIL st, GF_Matrix2D *mx){	EVGStencil *_this = (EVGStencil *)st;	if (!_this || _this->type>GF_STENCIL_TEXTURE) return GF_BAD_PARAM;	if (mx) {		gf_mx2d_copy(_this->smat, *mx);	} else {		gf_mx2d_init(_this->smat);	}	return GF_OK;}/*	Solid color stencil*/EVGStencil *evg_solid_brush(){	EVG_Brush *tmp;	GF_SAFEALLOC(tmp, EVG_Brush);	if (!tmp) return 0L;	tmp->fill_run = NULL;	tmp->color = 0xFF000000;	tmp->type = GF_STENCIL_SOLID;	return (EVGStencil *) tmp;}GF_Err evg_stencil_set_brush_color(GF_STENCIL st, GF_Color c){	EVG_Brush *_this = (EVG_Brush *) st;	if (!_this  || (_this ->type != GF_STENCIL_SOLID) ) return GF_BAD_PARAM;	_this->color = c;	return GF_OK;}/*	linear gradient stencil*/static void lgb_fill_run(EVGStencil *p, EVGSurface *surf, s32 x, s32 y, u32 count) {	Fixed _res;	s32 val, inc;	u32 *data = surf->stencil_pix_run;	u32 shifter = (EVGGRADIENTSCALEBITS - EVGGRADIENTBITS);	EVG_LinearGradient *_this = (EVG_LinearGradient *) p;	/*no need to move x & y to fixed*/	_res = (Fixed) (x * _this->smat.m[0] + y * _this->smat.m[1] + _this->smat.m[2]);	/*but remove val to int*/	val = FIX2INT(_res);	inc = FIX2INT(_this->smat.m[0]);	while (count) {		*data++ = gradient_get_color((EVG_BaseGradient *)_this, (val >> shifter) ); 		val += inc;		count--;	}}GF_Err evg_stencil_set_linear_gradient(GF_STENCIL st, Fixed start_x, Fixed start_y, Fixed end_x, Fixed end_y){	GF_Matrix2D mtx;	GF_Point2D s;	Fixed f;	EVG_LinearGradient *_this = (EVG_LinearGradient *) st;	if (_this->type != GF_STENCIL_LINEAR_GRADIENT) return GF_BAD_PARAM;	_this->start.x = start_x;	_this->start.y = start_y;	_this->end.x = end_x;	_this->end.y = end_y;	s.x = end_x - start_x;	s.y = end_y - start_y;	f = gf_v2d_len(&s);	if (f) f = gf_invfix(f);	gf_mx2d_init(mtx);	mtx.m[2] = - _this->start.x;	mtx.m[5] = - _this->start.y;	_this->vecmat = mtx;	gf_mx2d_init(mtx);	gf_mx2d_add_rotation(&mtx, 0, 0, - gf_atan2(s.y, s.x));	gf_mx2d_add_matrix(&_this->vecmat, &mtx);	gf_mx2d_init(mtx);	gf_mx2d_add_scale(&mtx, f, f);	gf_mx2d_add_matrix(&_this->vecmat, &mtx);	return GF_OK;}EVGStencil *evg_linear_gradient_brush(){	s32 i;	EVG_LinearGradient *tmp;	GF_SAFEALLOC(tmp, EVG_LinearGradient);	if (!tmp) return 0L;	gf_mx2d_init(tmp->vecmat);	tmp->fill_run = lgb_fill_run;	tmp->type = GF_STENCIL_LINEAR_GRADIENT;	for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;	evg_stencil_set_linear_gradient((EVGStencil *)tmp, 0, 0, FIX_ONE, 0);	return (EVGStencil *) tmp;}/*	radial gradient stencil*/static void rg_fill_run(EVGStencil *p, EVGSurface *surf, s32 _x, s32 _y, u32 count) {	Fixed x, y, dx, dy, b, val;	Bool has_cmat;	s32 pos;	u32 col;	u32 *data = surf->stencil_pix_run;	EVG_RadialGradient *_this = (EVG_RadialGradient *) p;	x = INT2FIX(_x);	y = INT2FIX(_y);	gf_mx2d_apply_coords(&_this->smat, &x, &y);	has_cmat = _this->cmat.identity ? 0 : 1;	dx = x - _this->d_f.x;	dy = y - _this->d_f.y;	while (count) {		b = gf_mulfix(_this->rad, gf_mulfix(dx, _this->d_f.x) + gf_mulfix(dy,  _this->d_f.y));		val = gf_mulfix(b, b) + gf_mulfix(_this->rad, gf_mulfix(dx, dx)+gf_mulfix(dy, dy));		b += gf_sqrt(val);		pos = FIX2INT(EVGGRADIENTBUFFERSIZE*b);		if (has_cmat) {			col = gradient_get_color((EVG_BaseGradient *)_this, pos);			*data++ = gf_cmx_apply(&p->cmat, col);		} else {		*data++ = gradient_get_color((EVG_BaseGradient *)_this, pos);		}		dx += _this->d_i.x;		dy += _this->d_i.y;		count--;	}}void evg_radial_init(EVG_RadialGradient *_this) {	GF_Point2D p0, p1;	p0.x = p0.y = p1.y = 0;	p1.x = FIX_ONE;	gf_mx2d_apply_point(&_this->smat, &p0);	gf_mx2d_apply_point(&_this->smat, &p1);	_this->d_i.x = p1.x - p0.x;	_this->d_i.y = p1.y - p0.y;	_this->rad = FIX_ONE - gf_mulfix(_this->d_f.x, _this->d_f.x) - gf_mulfix(_this->d_f.y, _this->d_f.y);	if (_this->rad) {		_this->rad = gf_invfix(_this->rad);	} else {		_this->rad = EVGGRADIENTBUFFERSIZE;	}}EVGStencil *evg_radial_gradient_brush(){	s32 i;	EVG_RadialGradient *tmp;	GF_SAFEALLOC(tmp, EVG_RadialGradient);	if (!tmp) return 0L;	tmp->fill_run = rg_fill_run;	tmp->type = GF_STENCIL_RADIAL_GRADIENT;	for(i=0; i<EVGGRADIENTSLOTS; i++) tmp->pos[i]=-1;	tmp->center.x = tmp->center.y = FIX_ONE/2;	tmp->focus = tmp->center;	tmp->radius = tmp->center;	return (EVGStencil *) tmp;}GF_Err evg_stencil_set_radial_gradient(GF_STENCIL st, Fixed cx, Fixed cy, Fixed fx, Fixed fy, Fixed x_radius, Fixed y_radius){	EVG_RadialGradient *_this = (EVG_RadialGradient *) st;	if (_this->type != GF_STENCIL_RADIAL_GRADIENT) return GF_BAD_PARAM;	_this->center.x = cx;	_this->center.y = cy;	_this->focus.x = fx;	_this->focus.y = fy;	_this->radius.x = x_radius;	_this->radius.y = y_radius;	return GF_OK;}/*	Texture stencil */static s32mul255(s32 a, s32 b){	return ((a+1) * b) >> 8;}#if 0/*thx to charcoal for the bilinear filter*/static u32 EVG_LERP(u32 c0, u32 c1, u8 t){	s32 a0, r0, g0, b0;	s32 a1, r1, g1, b1;	s32 a2, r2, g2, b2;	a0 = GF_COL_A(c0);	r0 = GF_COL_R(c0);	g0 = GF_COL_G(c0);	b0 = GF_COL_B(c0);	a1 = GF_COL_A(c1);	r1 = GF_COL_R(c1);	g1 = GF_COL_G(c1);	b1 = GF_COL_B(c1);	a2 = a0 + mul255(t, (a1 - a0));	r2 = r0 + mul255(t, (r1 - r0));	g2 = g0 + mul255(t, (g1 - g0));	b2 = b0 + mul255(t, (b1 - b0));

⌨️ 快捷键说明

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