This source file includes following definitions.
- gdip_new_stencil
- gdip_delete_stencil
- gdip_stencil_set_matrix
- gdip_set_brush_color
- gdip_set_gradient_mode
- gdip_set_linear_gradient
- gdip_recompute_line_gradient
- gdip_recompute_radial_gradient
- gdip_set_radial_gradient
- gdip_set_gradient_interpolation
- gdip_set_vertex_path
- gdip_set_vertex_center
- gdip_set_vertex_colors
- gdip_init_driver_grad
#include "gdip_priv.h"
GF_STENCIL gdip_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;
}
static
void gdip_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) gf_free(_sten->conv_buf);
if (_sten->cols) delete [] _sten->cols;
if (_sten->pos) delete [] _sten->pos;
gf_free(_sten);
}
static
GF_Err gdip_stencil_set_matrix(GF_STENCIL _this, GF_Matrix2D *mat)
{
GPSTEN();
GPMATRIX();
if (_sten->pMat) GdipDeleteMatrix(_sten->pMat);
_sten->pMat = _mat;
return GF_OK;
}
static
GF_Err gdip_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;
}
static
GF_Err gdip_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 = GF_TRUE;
return GF_OK;
}
static
GF_Err gdip_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 = GF_TRUE;
return GF_OK;
}
void gdip_recompute_line_gradient(GF_STENCIL _this)
{
GpPointF start, end;
u32 i, k;
REAL w, h;
GPSTEN();
if (!_sten->needs_rebuild) return;
_sten->needs_rebuild = GF_FALSE;
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;
}
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];
GdipSetLineWrapMode(_sten->pLinear, WrapModeTileFlipXY);
GdipSetLinePresetBlend(_sten->pLinear, cols, pos, 2+_sten->num_pos);
delete [] cols;
delete [] pos;
}
void gdip_recompute_radial_gradient(GF_STENCIL _this)
{
s32 repeat, k;
u32 i;
GpPointF pt;
GpMatrix *mat;
GPSTEN();
if (!_sten->needs_rebuild) return;
_sten->needs_rebuild = GF_FALSE;
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);
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];
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;
pt = _sten->focal;
pt.X -= _sten->center.X;
pt.Y -= _sten->center.Y;
GdipSetPathGradientCenterPoint(_sten->pRadial, &pt);
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);
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;
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);
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 gdip_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);
_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 = GF_TRUE;
return GF_OK;
}
static
GF_Err gdip_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;
_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 = GF_TRUE;
return GF_OK;
}
static
GF_Err gdip_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 gdip_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;
}
static
GF_Err gdip_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 gdip_init_driver_grad(GF_Raster2D *driver)
{
driver->stencil_new = gdip_new_stencil;
driver->stencil_delete = gdip_delete_stencil;
driver->stencil_set_matrix = gdip_stencil_set_matrix;
driver->stencil_set_brush_color = gdip_set_brush_color;
driver->stencil_set_gradient_mode = gdip_set_gradient_mode;
driver->stencil_set_linear_gradient = gdip_set_linear_gradient;
driver->stencil_set_radial_gradient = gdip_set_radial_gradient;
driver->stencil_set_gradient_interpolation = gdip_set_gradient_interpolation;
driver->stencil_set_vertex_path = gdip_set_vertex_path;
driver->stencil_set_vertex_center = gdip_set_vertex_center;
driver->stencil_set_vertex_colors = gdip_set_vertex_colors;
}