static void test_ellipse(void) { GpStatus status; GpPath *path; GpPointF points[2]; points[0].X = 7.0; points[0].Y = 11.0; points[1].X = 13.0; points[1].Y = 17.0; GdipCreatePath(FillModeAlternate, &path); status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5); expect(Ok, status); GdipAddPathLine2(path, points, 2); status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0); expect(Ok, status); GdipClosePathFigure(path); status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0); expect(Ok, status); ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE); GdipDeletePath(path); }
static void test_flatten(void) { GpStatus status; GpPath *path; GpMatrix *m; status = GdipCreatePath(FillModeAlternate, &path); expect(Ok, status); status = GdipCreateMatrix(&m); expect(Ok, status); /* NULL arguments */ status = GdipFlattenPath(NULL, NULL, 0.0); expect(InvalidParameter, status); status = GdipFlattenPath(NULL, m, 0.0); expect(InvalidParameter, status); /* flatten empty path */ status = GdipFlattenPath(path, NULL, 1.0); expect(Ok, status); status = GdipTransformPath(path, 0); expect(Ok, status); status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 50.0); expect(Ok, status); status = GdipFlattenPath(path, NULL, 1.0); expect(Ok, status); ok_path(path, flattenellipse_path, sizeof(flattenellipse_path)/sizeof(path_test_t), TRUE); status = GdipResetPath(path); expect(Ok, status); status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 100.0); expect(Ok, status); status = GdipFlattenPath(path, NULL, 1.0); expect(Ok, status); ok_path(path, flattenline_path, sizeof(flattenline_path)/sizeof(path_test_t), FALSE); status = GdipResetPath(path); expect(Ok, status); status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 50.0, 0.0, 90.0); expect(Ok, status); status = GdipFlattenPath(path, NULL, 1.0); expect(Ok, status); ok_path(path, flattenarc_path, sizeof(flattenarc_path)/sizeof(path_test_t), TRUE); /* easy case - quater of a full circle */ status = GdipResetPath(path); expect(Ok, status); status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0); expect(Ok, status); status = GdipFlattenPath(path, NULL, 1.0); expect(Ok, status); ok_path(path, flattenquater_path, sizeof(flattenquater_path)/sizeof(path_test_t), FALSE); GdipDeleteMatrix(m); GdipDeletePath(path); }
/*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); } }
GpStatus WINGDIPAPI GdipAddPathEllipseI(GpPath *path, INT x, INT y, INT width, INT height) { return GdipAddPathEllipse(path,(REAL)x,(REAL)y,(REAL)width,(REAL)height); }
static void test_combinereplace(void) { GpStatus status; GpRegion *region, *region2; GpPath *path; GpRectF rectf; UINT needed; DWORD buf[50]; rectf.X = rectf.Y = 0.0; rectf.Width = rectf.Height = 100.0; status = GdipCreateRegionRect(&rectf, ®ion); expect(Ok, status); /* replace with the same rectangle */ status = GdipCombineRegionRect(region, &rectf,CombineModeReplace); expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); expect(Ok, status); expect(36, needed); status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); expect(Ok, status); expect(36, needed); expect_dword(buf, 28); trace("buf[1] = %08x\n", buf[1]); expect_magic((DWORD*)(buf + 2)); expect_dword(buf + 3, 0); expect_dword(buf + 4, RGNDATA_RECT); /* replace with path */ status = GdipCreatePath(FillModeAlternate, &path); expect(Ok, status); status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0); expect(Ok, status); status = GdipCombineRegionPath(region, path, CombineModeReplace); expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); expect(Ok, status); expect(156, needed); status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); expect(Ok, status); expect(156, needed); expect_dword(buf, 148); trace("buf[1] = %08x\n", buf[1]); expect_magic((DWORD*)(buf + 2)); expect_dword(buf + 3, 0); expect_dword(buf + 4, RGNDATA_PATH); GdipDeletePath(path); /* replace with infinite rect */ status = GdipCreateRegion(®ion2); expect(Ok, status); status = GdipCombineRegionRegion(region, region2, CombineModeReplace); expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); expect(Ok, status); expect(20, needed); status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); expect(Ok, status); expect(20, needed); expect_dword(buf, 12); trace("buf[1] = %08x\n", buf[1]); expect_magic((DWORD*)(buf + 2)); expect_dword(buf + 3, 0); expect_dword(buf + 4, RGNDATA_INFINITE_RECT); GdipDeleteRegion(region2); /* more complex case : replace with a combined region */ status = GdipCreateRegionRect(&rectf, ®ion2); expect(Ok, status); status = GdipCreatePath(FillModeAlternate, &path); expect(Ok, status); status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 250.0); expect(Ok, status); status = GdipCombineRegionPath(region2, path, CombineModeUnion); expect(Ok, status); GdipDeletePath(path); status = GdipCombineRegionRegion(region, region2, CombineModeReplace); expect(Ok, status); GdipDeleteRegion(region2); status = GdipGetRegionDataSize(region, &needed); expect(Ok, status); expect(180, needed); status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); expect(Ok, status); expect(180, needed); expect_dword(buf, 172); trace("buf[1] = %08x\n", buf[1]); expect_magic((DWORD*)(buf + 2)); expect_dword(buf + 3, 2); expect_dword(buf + 4, CombineModeUnion); GdipDeleteRegion(region); }