static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
{
    GpMatrix *real_transform;
    GpStatus stat;

    stat = GdipCreateMatrix3(&metafile->src_rect, metafile->playback_points, &real_transform);

    if (stat == Ok)
    {
        REAL scale = units_to_pixels(1.0, metafile->page_unit, 96.0);

        if (metafile->page_unit != UnitDisplay)
            scale *= metafile->page_scale;

        stat = GdipScaleMatrix(real_transform, scale, scale, MatrixOrderPrepend);

        if (stat == Ok)
            stat = GdipMultiplyMatrix(real_transform, metafile->world_transform, MatrixOrderPrepend);

        if (stat == Ok)
            stat = GdipSetWorldTransform(metafile->playback_graphics, real_transform);

        GdipDeleteMatrix(real_transform);
    }

    return stat;
}
示例#2
0
/*GDIplus is completely bugged here, we MUST build the gradient in local coord system and apply translation
after, otherwise performances are just horrible*/
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);
	/*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);
	}
}
示例#3
0
static
GF_Err gdip_surface_fill(GF_SURFACE _this, GF_STENCIL stencil)
{
	GpStatus ret;
	GpMatrix *newmat;
	struct _stencil *_sten;
	GPGRAPH();
	if (!_this) return GF_BAD_PARAM;
	if (!_graph->current) return GF_OK;
	_sten = (struct _stencil *)stencil;
	assert(_sten);

#ifdef NODRAW
	return GF_OK;
#endif


	if (_graph->clip) GdipSetClipPath(_graph->graph, _graph->clip, CombineModeReplace);

	switch (_sten->type) {
	case GF_STENCIL_SOLID:
		assert(_sten->pSolid);
		GdipFillPath(_graph->graph, _sten->pSolid, _graph->current);
		break;
	case GF_STENCIL_LINEAR_GRADIENT:
		if (_sten->pMat) {
			/*rebuild gradient*/
			gdip_recompute_line_gradient(_sten);

			GdipResetTextureTransform((GpTexture*)_sten->pLinear);
			if (_sten->pMat) {
				GdipCloneMatrix(_sten->pMat, &newmat);
			} else {
				GdipCreateMatrix(&newmat);
			}
			GdipMultiplyMatrix(newmat, _sten->pLinearMat, MatrixOrderPrepend);
			GdipSetTextureTransform((GpTexture*)_sten->pLinear, newmat);
			GdipDeleteMatrix(newmat);
		}
		GdipFillPath(_graph->graph, _sten->pLinear, _graph->current);
		break;
	case GF_STENCIL_RADIAL_GRADIENT:
		/*build gradient*/
		gdip_recompute_radial_gradient(_sten);

		GdipSetCompositingQuality(_graph->graph, CompositingQualityHighSpeed);
		GdipSetInterpolationMode(_graph->graph, InterpolationModeLowQuality);
		GdipSetSmoothingMode(_graph->graph, SmoothingModeHighSpeed);

		/*check if we need to draw solid background (GDIplus doesn't implement padded mode on path gradients)*/
		if (_sten->pSolid) {
			GpPath *tr;
			GdipClonePath(_sten->circle, &tr);
			GdipTransformPath(tr, _sten->pMat);
			GdipSetClipPath(_graph->graph, tr, CombineModeExclude);
			GdipFillPath(_graph->graph, _sten->pSolid, _graph->current);
			GdipDeletePath(tr);
			GdipResetClip(_graph->graph);
			if (_graph->clip) GdipSetClipPath(_graph->graph, _graph->clip, CombineModeReplace);
		}
		GdipFillPath(_graph->graph, _sten->pRadial, _graph->current);
		break;
	case GF_STENCIL_VERTEX_GRADIENT:
		assert(_sten->pRadial);
		if (_sten->pMat) GdipSetTextureTransform((GpTexture*)_sten->pRadial, _sten->pMat);
		ret = GdipFillPath(_graph->graph, _sten->pRadial, _graph->current);
		break;
	case GF_STENCIL_TEXTURE:
		gdip_load_texture(_sten);
		if (_sten->pTexture) {
			GpMatrix *newmat;
			GdipResetTextureTransform((GpTexture*)_sten->pTexture);
			if (_sten->pMat) {
				GdipCloneMatrix(_sten->pMat, &newmat);
			} else {
				GdipCreateMatrix(&newmat);
			}
			/*gdip flip*/
			if (_graph->center_coords && !(_sten->tiling&GF_TEXTURE_FLIP) )
				GdipScaleMatrix(newmat, 1, -1, MatrixOrderPrepend);
			else if (!_graph->center_coords && (_sten->tiling&GF_TEXTURE_FLIP) )
				GdipScaleMatrix(newmat, 1, -1, MatrixOrderPrepend);

			GdipSetTextureTransform((GpTexture*)_sten->pTexture, newmat);
			GdipDeleteMatrix(newmat);

			GdipSetInterpolationMode(_graph->graph, (_sten->tFilter==GF_TEXTURE_FILTER_HIGH_QUALITY) ? InterpolationModeHighQuality : InterpolationModeLowQuality);
			GdipFillPath(_graph->graph, _sten->pTexture, _graph->current);
		}
		break;
	}
	return GF_OK;
}