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

📄 gdip_grad.cpp

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 CPP
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / GDIplus 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 "gdip_priv.h"GF_STENCIL gf_new_stencil(GF_Raster2D *, GF_StencilType type){	struct _stencil *sten;		switch (type) {	case GF_STENCIL_SOLID:	case GF_STENCIL_LINEAR_GRADIENT:	case GF_STENCIL_RADIAL_GRADIENT:	case GF_STENCIL_VERTEX_GRADIENT:	case GF_STENCIL_TEXTURE:		break;	default:		return NULL;	}	SAFEALLOC(sten, struct _stencil);	sten->type = type;	sten->alpha = 255;	return (GF_STENCIL) sten;}staticvoid gf_delete_stencil(GF_STENCIL _this){	GPSTEN();	if (_sten->pSolid) GdipDeleteBrush(_sten->pSolid);	if (_sten->pTexture) GdipDeleteBrush(_sten->pTexture);	if (_sten->pLinear) GdipDeleteBrush(_sten->pLinear);	if (_sten->pRadial) GdipDeleteBrush(_sten->pRadial);	if (_sten->circle) GdipDeletePath(_sten->circle);	if (_sten->pMat) GdipDeleteMatrix(_sten->pMat);	if (_sten->pLinearMat) GdipDeleteMatrix(_sten->pLinearMat);	if (_sten->pBitmap) GdipDisposeImage(_sten->pBitmap);	if (_sten->conv_buf) free(_sten->conv_buf);	if (_sten->cols) delete [] _sten->cols;	if (_sten->pos) delete [] _sten->pos;	free(_sten);}staticGF_Err gf_stencil_set_matrix(GF_STENCIL _this, GF_Matrix2D *mat){	GPSTEN();	GPMATRIX();	if (_sten->pMat) GdipDeleteMatrix(_sten->pMat);	_sten->pMat = _mat;	return GF_OK;}staticGF_Err gf_set_brush_color(GF_STENCIL _this, GF_Color c){	GPSTEN();	CHECK_RET(GF_STENCIL_SOLID);	if (!_sten->pSolid) 		GdipCreateSolidFill(c, &_sten->pSolid);	else		GdipSetSolidFillColor(_sten->pSolid, c);	return GF_OK;}staticGF_Err gf_set_gradient_mode(GF_STENCIL _this, GF_GradientMode mode){	GPSTEN();	CHECK2_RET(GF_STENCIL_LINEAR_GRADIENT, GF_STENCIL_RADIAL_GRADIENT);	_sten->spread = mode;	_sten->needs_rebuild = 1;	return GF_OK;}static GF_Err gf_set_linear_gradient (GF_STENCIL _this, Fixed start_x, Fixed start_y, Fixed end_x, Fixed end_y){	GPSTEN();	CHECK_RET(GF_STENCIL_LINEAR_GRADIENT);	if (_sten->pLinear) GdipDeleteBrush(_sten->pLinear);	_sten->start.X = FIX2FLT(start_x);	_sten->start.Y = FIX2FLT(start_y);	_sten->end.X = FIX2FLT(end_x);	_sten->end.Y = FIX2FLT(end_y);	GdipCreateLineBrush(&_sten->start, &_sten->end, 0xFF000000, 0xFFFFFFFF, WrapModeTile, &_sten->pLinear);	if (!_sten->pLinearMat) GdipCreateMatrix(&_sten->pLinearMat);	GdipGetLineTransform(_sten->pLinear, _sten->pLinearMat);	_sten->needs_rebuild = 1;	return GF_OK;}void gf_recompute_line_gradient(GF_STENCIL _this){	GpPointF start, end;	u32 i, k;	REAL w, h;	GPSTEN();	if (!_sten->needs_rebuild) return;	_sten->needs_rebuild = 0;	if (_sten->pLinear) GdipDeleteBrush(_sten->pLinear);	GdipCreateLineBrush(&_sten->start, &_sten->end, 0xFFFF0000, 0xFFFF00FF, WrapModeTile, &_sten->pLinear);	switch (_sten->spread) {	case GF_GRADIENT_MODE_PAD:		break;	case GF_GRADIENT_MODE_SPREAD:		GdipSetLineWrapMode(_sten->pLinear, WrapModeTileFlipXY);		GdipSetLinePresetBlend(_sten->pLinear, (ARGB *) _sten->cols, _sten->pos, _sten->num_pos);		return;	case GF_GRADIENT_MODE_REPEAT:		GdipSetLineWrapMode(_sten->pLinear, WrapModeTile);		GdipSetLinePresetBlend(_sten->pLinear, (ARGB *) _sten->cols, _sten->pos, _sten->num_pos);		return;	}	/*currently gdiplus doesn't support padded mode on gradients, so update the line gradient by 	using a line 3 times longer*/	w = _sten->end.X - _sten->start.X;	h = _sten->end.Y - _sten->start.Y;	start.X = _sten->start.X - w;	start.Y = _sten->start.Y - h;	end.X = _sten->end.X + w;	end.Y = _sten->end.Y + h;	GdipCreateLineBrush(&start, &end, 0xFFFF0000, 0xFFFF00FF, WrapModeTile, &_sten->pLinear);	ARGB *cols = new ARGB[_sten->num_pos+2];	REAL *pos = new REAL[_sten->num_pos+2];	k=0;	for (i=0; i<_sten->num_pos; i++) {		cols[i+k] = _sten->cols[i];		pos[i+k] = (1 + _sten->pos[i])/3;		if (!i) {			pos[1] = pos[0];			cols[1] = cols[0];			k=1;			pos[0] = 0;		}	}	pos[_sten->num_pos+1] = 1.0;	cols[_sten->num_pos+1] = cols[_sten->num_pos];	/*since depending on gradient transform the padding is likely to be not big enough, use flipXY to assure that in most	cases the x3 dilatation is enough*/	GdipSetLineWrapMode(_sten->pLinear, WrapModeTileFlipXY);	GdipSetLinePresetBlend(_sten->pLinear, cols, pos, 2+_sten->num_pos);		delete [] cols;	delete [] pos;}/*GDIplus is completely bugged here, we MUST build the gradient in local coord system and apply translationafter, otherwise performances are just horrible*/void gf_recompute_radial_gradient(GF_STENCIL _this){	s32 repeat, k;	u32 i;	GpPointF pt;	GpMatrix *mat;	GPSTEN();	if (!_sten->needs_rebuild) return;	_sten->needs_rebuild = 0;	if (_sten->pRadial) {		GdipDeleteBrush(_sten->pRadial);		_sten->pRadial = NULL;	}	if (_sten->pSolid) {		GdipDeleteBrush(_sten->pSolid);		_sten->pSolid = NULL;	}	if (_sten->circle) {		GdipDeletePath(_sten->circle);		_sten->circle = NULL;	}	GdipCreatePath(FillModeAlternate, &_sten->circle);	/*get number of repeats*/	if (_sten->spread == GF_GRADIENT_MODE_PAD) {		GdipAddPathEllipse(_sten->circle, - _sten->radius.X, -_sten->radius.Y, 								2*_sten->radius.X, 2*_sten->radius.Y);			GdipCreatePathGradientFromPath(_sten->circle, &_sten->pRadial);		ARGB *blends = new ARGB[_sten->num_pos + 1];		/*radial blend pos are from bounds to center in gdiplus*/		blends[0] = _sten->cols[_sten->num_pos - 1];		for (i=0; i<_sten->num_pos;i++) {			blends[i+1] = _sten->cols[_sten->num_pos - i - 1];		}			REAL *pos = new REAL[_sten->num_pos + 1];		pos[0] = 0;		for (i=0; i<_sten->num_pos;i++) {			pos[i+1] = _sten->pos[i];		}		GdipSetPathGradientPresetBlend(_sten->pRadial, blends, pos, _sten->num_pos + 1);		delete [] blends;		delete [] pos;		/*set focal*/		pt = _sten->focal;		pt.X -= _sten->center.X;		pt.Y -= _sten->center.Y;		GdipSetPathGradientCenterPoint(_sten->pRadial, &pt);			/*set transform*/		GdipCreateMatrix(&mat);		GdipTranslateMatrix(mat, _sten->center.X, _sten->center.Y, MatrixOrderAppend);		if (_sten->pMat) GdipMultiplyMatrix(mat, _sten->pMat, MatrixOrderAppend);		GdipSetTextureTransform((GpTexture*)_sten->pRadial, mat);		GdipDeleteMatrix(mat);		/*create back brush*/		GdipCreateSolidFill(_sten->cols[_sten->num_pos - 1], &_sten->pSolid);		GdipResetPath(_sten->circle);		GdipAddPathEllipse(_sten->circle, - _sten->radius.X + _sten->center.X, -_sten->radius.Y + _sten->center.Y, 								2*_sten->radius.X, 2*_sten->radius.Y);	} else {		repeat = 10;		GdipAddPathEllipse(_sten->circle, - repeat * _sten->radius.X, - repeat*_sten->radius.Y, 								2*repeat*_sten->radius.X,  2*repeat*_sten->radius.Y);		GdipCreatePathGradientFromPath(_sten->circle, &_sten->pRadial);		GdipDeletePath(_sten->circle);		_sten->circle = NULL;		ARGB *blends = new ARGB[_sten->num_pos*repeat];		REAL *pos = new REAL[_sten->num_pos*repeat];		if (_sten->spread == GF_GRADIENT_MODE_REPEAT) {			for (k=0; k<repeat; k++) {				for (i=0; i<_sten->num_pos; i++) {					blends[k*_sten->num_pos + i] = _sten->cols[_sten->num_pos - i - 1];					pos[k*_sten->num_pos + i] = (k + _sten->pos[i]) / repeat;				}			}		} else {			for (k=0; k<repeat; k++) {				for (i=0; i<_sten->num_pos; i++) {					u32 index = (k%2) ? (_sten->num_pos-i-1) : i;					blends[k*_sten->num_pos + i] = _sten->cols[index];					if (k%2) {						pos[k*_sten->num_pos + i] = (k + (1 - _sten->pos[index]) ) / repeat;					} else {						pos[k*_sten->num_pos + i] = ( k + _sten->pos[i] ) / repeat;					}				}			}		}		GdipSetPathGradientPresetBlend(_sten->pRadial, blends, pos, _sten->num_pos*repeat);		delete [] pos;		delete [] blends;		/*set focal*/		pt = _sten->focal;		pt.X -= (1 - repeat) * (_sten->focal.X - _sten->center.X) + _sten->center.X;		pt.Y -= (1 - repeat) * (_sten->focal.Y - _sten->center.Y) + _sten->center.Y;		GdipSetPathGradientCenterPoint(_sten->pRadial, &pt);			/*set transform*/		GdipCreateMatrix(&mat);		GdipTranslateMatrix(mat, (1 - repeat) * (_sten->focal.X - _sten->center.X) + _sten->center.X,								(1 - repeat) * (_sten->focal.Y - _sten->center.Y) + _sten->center.Y, 								MatrixOrderAppend);		if (_sten->pMat) GdipMultiplyMatrix(mat, _sten->pMat, MatrixOrderAppend);		GdipSetTextureTransform((GpTexture*)_sten->pRadial, mat);		GdipDeleteMatrix(mat);		GdipSetPathGradientWrapMode(_sten->pRadial, WrapModeTileFlipXY);	}}static GF_Err gf_set_radial_gradient(GF_STENCIL _this, Fixed cx, Fixed cy, Fixed fx, Fixed fy, Fixed x_radius, Fixed y_radius){	GPSTEN();	CHECK_RET(GF_STENCIL_RADIAL_GRADIENT);	/*store focal info*/	_sten->radius.X = FIX2FLT(x_radius);	_sten->radius.Y = FIX2FLT(y_radius);	_sten->center.X = FIX2FLT(cx);	_sten->center.Y = FIX2FLT(cy);	_sten->focal.X = FIX2FLT(fx);	_sten->focal.Y = FIX2FLT(fy);	_sten->needs_rebuild = 1;	return GF_OK;}staticGF_Err gf_set_gradient_interpolation(GF_STENCIL _this, Fixed *pos, GF_Color *col, u32 count){	u32 i;	GPSTEN();	if (_sten->cols) delete [] _sten->cols;	if (_sten->pos) delete [] _sten->pos;	/*handle padding internally*/	_sten->cols = new ARGB[count];	_sten->pos = new REAL[count];	for (i=0; i<count; i++) _sten->pos[i] = FIX2FLT(pos[i]);	memcpy(_sten->cols, col, sizeof(ARGB)*count);	_sten->num_pos = count;	_sten->needs_rebuild = 1;	return GF_OK;}static GF_Err gf_set_vertex_path(GF_STENCIL _this, GF_Path *path){	GPSTEN();	GpPath *p;	CHECK_RET(GF_STENCIL_VERTEX_GRADIENT);	p = gdip_create_path(path);	if (_sten->pRadial) GdipDeleteBrush(_sten->pRadial);	GdipCreatePathGradientFromPath(p, &_sten->pRadial);	GdipDeletePath(p);	return GF_OK;}static GF_Err gf_set_vertex_center (GF_STENCIL _this, Fixed cx, Fixed cy, u32 color){	GpStatus ret;	GPSTEN();	CHECK_RET(GF_STENCIL_VERTEX_GRADIENT);	if (!_sten->pRadial) return GF_BAD_PARAM;	_sten->center.X = FIX2FLT(cx);	_sten->center.Y = FIX2FLT(cy);	ret = GdipSetPathGradientCenterPoint(_sten->pRadial, &_sten->center);	ret = GdipSetPathGradientCenterColor(_sten->pRadial, (ARGB) color);	return GF_OK;}staticGF_Err gf_set_vertex_colors (GF_STENCIL _this, u32 *colors, u32 nbCol){	int col = nbCol;	GPSTEN();	CHECK_RET(GF_STENCIL_VERTEX_GRADIENT);	GpStatus ret;	if (!_sten->pRadial) return GF_BAD_PARAM;	ret = GdipSetPathGradientSurroundColorsWithCount(_sten->pRadial, (ARGB *) colors, &col);	return GF_OK;}void gf_init_driver_grad(GF_Raster2D *driver){	driver->stencil_new = gf_new_stencil;	driver->stencil_delete = gf_delete_stencil;	driver->stencil_set_matrix = gf_stencil_set_matrix;	driver->stencil_set_brush_color = gf_set_brush_color;	driver->stencil_set_gradient_mode = gf_set_gradient_mode;	driver->stencil_set_linear_gradient = gf_set_linear_gradient;	driver->stencil_set_radial_gradient = gf_set_radial_gradient;	driver->stencil_set_gradient_interpolation = gf_set_gradient_interpolation;	driver->stencil_set_vertex_path = gf_set_vertex_path;	driver->stencil_set_vertex_center = gf_set_vertex_center;	driver->stencil_set_vertex_colors = gf_set_vertex_colors;}

⌨️ 快捷键说明

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