2 * Copyright (C) 2007 Google (Evan Stade)
3 * Copyright (C) 2003-2004,2007 Novell, Inc. http://www.novell.com (Ravindra (rkumar@novell.com))
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "gdiplus_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus
);
38 /******************************************************************************
39 * GdipCloneBrush [GDIPLUS.@]
41 GpStatus WINGDIPAPI
GdipCloneBrush(GpBrush
*brush
, GpBrush
**clone
)
43 TRACE("(%p, %p)\n", brush
, clone
);
46 return InvalidParameter
;
49 case BrushTypeSolidColor
:
51 *clone
= heap_alloc_zero(sizeof(GpSolidFill
));
52 if (!*clone
) return OutOfMemory
;
53 memcpy(*clone
, brush
, sizeof(GpSolidFill
));
56 case BrushTypeHatchFill
:
58 GpHatch
*hatch
= (GpHatch
*)brush
;
60 return GdipCreateHatchBrush(hatch
->hatchstyle
, hatch
->forecol
, hatch
->backcol
, (GpHatch
**)clone
);
62 case BrushTypePathGradient
:{
63 GpPathGradient
*src
, *dest
;
67 *clone
= heap_alloc_zero(sizeof(GpPathGradient
));
68 if (!*clone
) return OutOfMemory
;
70 src
= (GpPathGradient
*) brush
;
71 dest
= (GpPathGradient
*) *clone
;
73 memcpy(dest
, src
, sizeof(GpPathGradient
));
75 stat
= GdipClonePath(src
->path
, &dest
->path
);
82 dest
->transform
= src
->transform
;
85 count
= src
->blendcount
;
86 dest
->blendcount
= count
;
87 dest
->blendfac
= heap_alloc_zero(count
* sizeof(REAL
));
88 dest
->blendpos
= heap_alloc_zero(count
* sizeof(REAL
));
89 dest
->surroundcolors
= heap_alloc_zero(dest
->surroundcolorcount
* sizeof(ARGB
));
90 pcount
= dest
->pblendcount
;
93 dest
->pblendcolor
= heap_alloc_zero(pcount
* sizeof(ARGB
));
94 dest
->pblendpos
= heap_alloc_zero(pcount
* sizeof(REAL
));
97 if(!dest
->blendfac
|| !dest
->blendpos
|| !dest
->surroundcolors
||
98 (pcount
&& (!dest
->pblendcolor
|| !dest
->pblendpos
))){
99 GdipDeletePath(dest
->path
);
100 heap_free(dest
->blendfac
);
101 heap_free(dest
->blendpos
);
102 heap_free(dest
->surroundcolors
);
103 heap_free(dest
->pblendcolor
);
104 heap_free(dest
->pblendpos
);
109 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
110 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
111 memcpy(dest
->surroundcolors
, src
->surroundcolors
, dest
->surroundcolorcount
* sizeof(ARGB
));
115 memcpy(dest
->pblendcolor
, src
->pblendcolor
, pcount
* sizeof(ARGB
));
116 memcpy(dest
->pblendpos
, src
->pblendpos
, pcount
* sizeof(REAL
));
121 case BrushTypeLinearGradient
:{
122 GpLineGradient
*dest
, *src
;
125 dest
= heap_alloc_zero(sizeof(GpLineGradient
));
126 if(!dest
) return OutOfMemory
;
128 src
= (GpLineGradient
*)brush
;
130 memcpy(dest
, src
, sizeof(GpLineGradient
));
132 count
= dest
->blendcount
;
133 dest
->blendfac
= heap_alloc_zero(count
* sizeof(REAL
));
134 dest
->blendpos
= heap_alloc_zero(count
* sizeof(REAL
));
135 pcount
= dest
->pblendcount
;
138 dest
->pblendcolor
= heap_alloc_zero(pcount
* sizeof(ARGB
));
139 dest
->pblendpos
= heap_alloc_zero(pcount
* sizeof(REAL
));
142 if (!dest
->blendfac
|| !dest
->blendpos
||
143 (pcount
&& (!dest
->pblendcolor
|| !dest
->pblendpos
)))
145 heap_free(dest
->blendfac
);
146 heap_free(dest
->blendpos
);
147 heap_free(dest
->pblendcolor
);
148 heap_free(dest
->pblendpos
);
153 dest
->transform
= src
->transform
;
155 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
156 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
160 memcpy(dest
->pblendcolor
, src
->pblendcolor
, pcount
* sizeof(ARGB
));
161 memcpy(dest
->pblendpos
, src
->pblendpos
, pcount
* sizeof(REAL
));
164 *clone
= &dest
->brush
;
167 case BrushTypeTextureFill
:
170 GpTexture
*texture
= (GpTexture
*)brush
;
171 GpTexture
*new_texture
;
174 stat
= GdipGetImageWidth(texture
->image
, &width
);
175 if (stat
!= Ok
) return stat
;
176 stat
= GdipGetImageHeight(texture
->image
, &height
);
177 if (stat
!= Ok
) return stat
;
179 stat
= GdipCreateTextureIA(texture
->image
, texture
->imageattributes
, 0, 0, width
, height
, &new_texture
);
183 new_texture
->transform
= texture
->transform
;
184 *clone
= &new_texture
->brush
;
192 ERR("not implemented for brush type %d\n", brush
->bt
);
193 return NotImplemented
;
196 TRACE("<-- %p\n", *clone
);
200 /* The first 8 items per entry are bitmaps for each row of the hatch style.
201 * The 9th item of the entry is a flag indicating anti-aliasing. */
202 static const unsigned char HatchBrushes
[][9] = {
203 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleHorizontal */
204 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, /* HatchStyleVertical */
205 { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, TRUE
}, /* HatchStyleForwardDiagonal */
206 { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, TRUE
}, /* HatchStyleBackwardDiagonal */
207 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff }, /* HatchStyleCross */
208 { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, TRUE
}, /* HatchStyleDiagonalCross */
209 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80 }, /* HatchStyle05Percent */
210 { 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00, 0x80 }, /* HatchStyle10Percent */
211 { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, /* HatchStyle20Percent */
212 { 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 }, /* HatchStyle25Percent */
213 { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa }, /* HatchStyle30Percent */
214 { 0x15, 0xaa, 0x55, 0xaa, 0x51, 0xaa, 0x55, 0xaa }, /* HatchStyle40Percent */
215 { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }, /* HatchStyle50Percent */
216 { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }, /* HatchStyle60Percent */
217 { 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77 }, /* HatchStyle70Percent */
218 { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 }, /* HatchStyle75Percent */
219 { 0xff, 0xfe, 0xff, 0xef, 0xff, 0xfe, 0xff, 0xef }, /* HatchStyle80Percent */
220 { 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff }, /* HatchStyle90Percent */
221 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, /* HatchStyleLightDownwardDiagonal */
222 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, /* HatchStyleLightUpwardDiagonal */
223 { 0x99, 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc }, /* HatchStyleDarkDownwardDiagonal */
224 { 0x99, 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33 }, /* HatchStyleDarkUpwardDiagonal */
225 { 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc1 }, /* HatchStyleWideDownwardDiagonal */
226 { 0xc1, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83 }, /* HatchStyleWideUpwardDiagonal */
227 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, /* HatchStyleLightVertical */
228 { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleLightHorizontal */
229 { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, /* HatchStyleNarrowVertical */
230 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, /* HatchStyleNarrowHorizontal */
231 { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, /* HatchStyleDarkVertical */
232 { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
233 { 0x00, 0x00, 0x11, 0x22, 0x44, 0x88, 0x00, 0x00 }, /* HatchStyleDashedDownwardDiagonal */
234 { 0x00, 0x00, 0x88, 0x44, 0x22, 0x11, 0x00, 0x00 }, /* HatchStyleDashedUpwardDiagonal */
235 { 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0 }, /* HatchStyleDashedHorizontal */
236 { 0x08, 0x08, 0x08, 0x08, 0x80, 0x80, 0x80, 0x80 }, /* HatchStyleDashedVertical */
237 { 0x04, 0x20, 0x01, 0x10, 0x02, 0x40, 0x08, 0x80 }, /* HatchStyleSmallConfetti */
238 { 0x8d, 0x0c, 0xc0, 0xd8, 0x1b, 0x03, 0x30, 0xb1 }, /* HatchStyleLargeConfetti */
239 { 0x18, 0x24, 0x42, 0x81, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleZigZag */
240 { 0xc0, 0x25, 0x18, 0x00, 0xc0, 0x25, 0x18, 0x00 }, /* HatchStyleWave */
241 { 0x81, 0x42, 0x24, 0x18, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleDiagonalBrick */
242 { 0x08, 0x08, 0x08, 0xff, 0x80, 0x80, 0x80, 0xff }, /* HatchStyleHorizontalBrick */
243 { 0x51, 0x22, 0x14, 0x88, 0x45, 0x22, 0x54, 0x88 }, /* HatchStyleWeave */
244 { 0xf0, 0xf0, 0xf0, 0xf0, 0x55, 0xaa, 0x55, 0xaa }, /* HatchStylePlaid */
245 { 0x80, 0x01, 0x80, 0x00, 0x10, 0x08, 0x10, 0x00 }, /* HatchStyleDivot */
246 { 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xaa }, /* HatchStyleDottedGrid */
247 { 0x00, 0x22, 0x00, 0x08, 0x00, 0x22, 0x00, 0x80 }, /* HatchStyleDottedDiamond */
248 { 0x01, 0x01, 0x02, 0x0c, 0x30, 0x48, 0x84, 0x03 }, /* HatchStyleShingle */
249 { 0x99, 0xff, 0x66, 0xff, 0x99, 0xff, 0x66, 0xff }, /* HatchStyleTrellis */
250 { 0xf8, 0xf8, 0x98, 0x77, 0x8f, 0x8f, 0x89, 0x77 }, /* HatchStyleSphere */
251 { 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88, 0xff }, /* HatchStyleSmallGrid */
252 { 0x99, 0x66, 0x66, 0x99, 0x99, 0x66, 0x66, 0x99 }, /* HatchStyleSmallCheckerBoard */
253 { 0x0f, 0x0f, 0x0f, 0x0f, 0xf0, 0xf0, 0xf0, 0xf0 }, /* HatchStyleLargeCheckerBoard */
254 { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, /* HatchStyleOutlinedDiamond */
255 { 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10 }, /* HatchStyleSolidDiamond */
258 GpStatus
get_hatch_data(GpHatchStyle hatchstyle
, const unsigned char **result
)
260 if (hatchstyle
< ARRAY_SIZE(HatchBrushes
))
262 *result
= HatchBrushes
[hatchstyle
];
266 return NotImplemented
;
269 /******************************************************************************
270 * GdipCreateHatchBrush [GDIPLUS.@]
272 GpStatus WINGDIPAPI
GdipCreateHatchBrush(GpHatchStyle hatchstyle
, ARGB forecol
, ARGB backcol
, GpHatch
**brush
)
274 TRACE("(%d, %ld, %ld, %p)\n", hatchstyle
, forecol
, backcol
, brush
);
276 if(!brush
) return InvalidParameter
;
278 if(hatchstyle
< HatchStyleMin
|| hatchstyle
> HatchStyleMax
)
279 return InvalidParameter
;
281 *brush
= heap_alloc_zero(sizeof(GpHatch
));
282 if (!*brush
) return OutOfMemory
;
284 (*brush
)->brush
.bt
= BrushTypeHatchFill
;
285 (*brush
)->forecol
= forecol
;
286 (*brush
)->backcol
= backcol
;
287 (*brush
)->hatchstyle
= hatchstyle
;
288 TRACE("<-- %p\n", *brush
);
293 static GpStatus
create_line_brush(const GpRectF
*rect
, ARGB startcolor
, ARGB endcolor
,
294 GpWrapMode wrap
, GpLineGradient
**line
)
296 *line
= heap_alloc_zero(sizeof(GpLineGradient
));
297 if(!*line
) return OutOfMemory
;
299 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
300 (*line
)->startcolor
= startcolor
;
301 (*line
)->endcolor
= endcolor
;
302 (*line
)->wrap
= wrap
;
303 (*line
)->gamma
= FALSE
;
304 (*line
)->rect
= *rect
;
305 (*line
)->blendcount
= 1;
306 (*line
)->blendfac
= heap_alloc_zero(sizeof(REAL
));
307 (*line
)->blendpos
= heap_alloc_zero(sizeof(REAL
));
309 if (!(*line
)->blendfac
|| !(*line
)->blendpos
)
311 heap_free((*line
)->blendfac
);
312 heap_free((*line
)->blendpos
);
318 (*line
)->blendfac
[0] = 1.0f
;
319 (*line
)->blendpos
[0] = 1.0f
;
321 (*line
)->pblendcolor
= NULL
;
322 (*line
)->pblendpos
= NULL
;
323 (*line
)->pblendcount
= 0;
325 GdipSetMatrixElements(&(*line
)->transform
, 1.0f
, 0.0f
, 0.0f
, 1.0f
, 0.0f
, 0.0f
);
330 static void linegradient_init_transform(const GpPointF
*startpoint
, const GpPointF
*endpoint
, GpLineGradient
*line
)
332 float trans_x
= line
->rect
.X
+ (line
->rect
.Width
/ 2.f
);
333 float trans_y
= line
->rect
.Y
+ (line
->rect
.Height
/ 2.f
);
334 float dx
= endpoint
->X
- startpoint
->X
;
335 float dy
= endpoint
->Y
- startpoint
->Y
;
336 float t_cos
, t_sin
, w_ratio
, h_ratio
;
340 h
= sqrtf(dx
* dx
+ dy
* dy
);
345 w_ratio
= (fabs(t_cos
) * line
->rect
.Width
+ fabs(t_sin
) * line
->rect
.Height
) / line
->rect
.Width
;
346 h_ratio
= (fabs(t_sin
) * line
->rect
.Width
+ fabs(t_cos
) * line
->rect
.Height
) / line
->rect
.Height
;
348 GdipSetMatrixElements(&line
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
350 GdipSetMatrixElements(&rot
, t_cos
, t_sin
, -1.f
* t_sin
, t_cos
, 0, 0);
352 /* center about the origin */
353 GdipTranslateMatrix(&line
->transform
, -trans_x
, -trans_y
, MatrixOrderAppend
);
355 /* scale to normalize gradient along gradient line (?) */
356 GdipScaleMatrix(&line
->transform
, w_ratio
, h_ratio
, MatrixOrderAppend
);
358 /* rotate so the gradient is horizontal */
359 GdipMultiplyMatrix(&line
->transform
, &rot
, MatrixOrderAppend
);
361 /* restore original offset in new coords */
362 GdipTranslateMatrix(&line
->transform
, trans_x
, trans_y
, MatrixOrderAppend
);
365 /******************************************************************************
366 * GdipCreateLineBrush [GDIPLUS.@]
368 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
369 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
370 GpWrapMode wrap
, GpLineGradient
**line
)
375 TRACE("(%s, %s, %lx, %lx, %d, %p)\n", debugstr_pointf(startpoint
),
376 debugstr_pointf(endpoint
), startcolor
, endcolor
, wrap
, line
);
378 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
379 return InvalidParameter
;
381 if (startpoint
->X
== endpoint
->X
&& startpoint
->Y
== endpoint
->Y
)
384 rect
.X
= startpoint
->X
< endpoint
->X
? startpoint
->X
: endpoint
->X
;
385 rect
.Y
= startpoint
->Y
< endpoint
->Y
? startpoint
->Y
: endpoint
->Y
;
386 rect
.Width
= fabs(startpoint
->X
- endpoint
->X
);
387 rect
.Height
= fabs(startpoint
->Y
- endpoint
->Y
);
389 if (rect
.Width
== 0.0f
)
391 rect
.X
-= rect
.Height
/ 2.0f
;
392 rect
.Width
= rect
.Height
;
394 else if (rect
.Height
== 0.0f
)
396 rect
.Y
-= rect
.Width
/ 2.0f
;
397 rect
.Height
= rect
.Width
;
400 stat
= create_line_brush(&rect
, startcolor
, endcolor
, wrap
, line
);
404 linegradient_init_transform(startpoint
, endpoint
, *line
);
406 TRACE("<-- %p\n", *line
);
411 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
412 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
413 GpWrapMode wrap
, GpLineGradient
**line
)
418 TRACE("(%p, %p, %lx, %lx, %d, %p)\n", startpoint
, endpoint
,
419 startcolor
, endcolor
, wrap
, line
);
421 if(!startpoint
|| !endpoint
)
422 return InvalidParameter
;
424 stF
.X
= (REAL
)startpoint
->X
;
425 stF
.Y
= (REAL
)startpoint
->Y
;
426 endF
.X
= (REAL
)endpoint
->X
;
427 endF
.Y
= (REAL
)endpoint
->Y
;
429 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
432 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
433 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
434 GpLineGradient
**line
)
438 TRACE("(%s, %lx, %lx, %d, %d, %p)\n", debugstr_rectf(rect
), startcolor
, endcolor
, mode
,
442 return InvalidParameter
;
446 case LinearGradientModeHorizontal
:
449 case LinearGradientModeVertical
:
452 case LinearGradientModeForwardDiagonal
:
455 case LinearGradientModeBackwardDiagonal
:
459 return InvalidParameter
;
462 return GdipCreateLineBrushFromRectWithAngle(rect
, startcolor
, endcolor
, angle
, TRUE
, wrap
, line
);
465 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
466 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
467 GpLineGradient
**line
)
471 TRACE("(%p, %lx, %lx, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
474 set_rect(&rectF
, rect
->X
, rect
->Y
, rect
->Width
, rect
->Height
);
475 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
478 /******************************************************************************
479 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
481 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF
* rect
,
482 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
483 GpLineGradient
**line
)
486 REAL exofs
, eyofs
, far_x
, far_y
;
487 REAL sin_angle
, cos_angle
, sin_cos_angle
;
490 TRACE("(%s, %lx, %lx, %.2f, %d, %d, %p)\n", debugstr_rectf(rect
), startcolor
, endcolor
, angle
, isAngleScalable
,
493 if (!rect
|| !line
|| wrap
== WrapModeClamp
)
494 return InvalidParameter
;
496 if (!rect
->Width
|| !rect
->Height
)
499 angle
= fmodf(angle
, 360);
512 if (angle
!= 90 && angle
!= -90)
513 angle
= atan((rect
->Width
/ rect
->Height
) * tan(deg2rad(angle
)));
515 angle
= deg2rad(angle
);
520 angle
= deg2rad(angle
);
523 sin_angle
= sinf(angle
);
524 cos_angle
= cosf(angle
);
525 sin_cos_angle
= sin_angle
* cos_angle
;
527 far_x
= rect
->X
+ rect
->Width
;
528 far_y
= rect
->Y
+ rect
->Height
;
532 start
.X
= min(rect
->X
, far_x
);
534 end
.X
= max(rect
->X
, far_x
);
537 else if (sin_cos_angle
>= 0)
539 start
.X
= min(rect
->X
, far_x
);
540 start
.Y
= min(rect
->Y
, far_y
);
541 end
.X
= max(rect
->X
, far_x
);
542 end
.Y
= max(rect
->Y
, far_y
);
546 start
.X
= max(rect
->X
, far_x
);
547 start
.Y
= min(rect
->Y
, far_y
);
548 end
.X
= min(rect
->X
, far_x
);
549 end
.Y
= max(rect
->Y
, far_y
);
552 stat
= create_line_brush(rect
, startcolor
, endcolor
, wrap
, line
);
553 if (stat
!= Ok
|| angle
== 0.0f
)
556 if (sin_cos_angle
>= 0)
558 exofs
= rect
->Height
* sin_cos_angle
+ rect
->Width
* cos_angle
* cos_angle
;
559 eyofs
= rect
->Height
* sin_angle
* sin_angle
+ rect
->Width
* sin_cos_angle
;
563 exofs
= rect
->Width
* sin_angle
* sin_angle
+ rect
->Height
* sin_cos_angle
;
564 eyofs
= -rect
->Width
* sin_cos_angle
+ rect
->Height
* sin_angle
* sin_angle
;
569 end
.X
= rect
->X
+ exofs
;
570 end
.Y
= rect
->Y
+ eyofs
;
576 start
.X
= rect
->X
+ exofs
;
577 start
.Y
= rect
->Y
+ eyofs
;
580 linegradient_init_transform(&start
, &end
, *line
);
585 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect
* rect
,
586 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
587 GpLineGradient
**line
)
589 TRACE("(%p, %lx, %lx, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
592 return GdipCreateLineBrushFromRectI(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
596 static GpStatus
create_path_gradient(GpPath
*path
, ARGB centercolor
, GpPathGradient
**grad
)
599 REAL sum_x
= 0, sum_y
= 0;
602 return InvalidParameter
;
604 if (path
->pathdata
.Count
< 2)
607 *grad
= heap_alloc_zero(sizeof(GpPathGradient
));
613 GdipSetMatrixElements(&(*grad
)->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
615 (*grad
)->blendfac
= heap_alloc_zero(sizeof(REAL
));
616 (*grad
)->blendpos
= heap_alloc_zero(sizeof(REAL
));
617 (*grad
)->surroundcolors
= heap_alloc_zero(sizeof(ARGB
));
618 if(!(*grad
)->blendfac
|| !(*grad
)->blendpos
|| !(*grad
)->surroundcolors
){
619 heap_free((*grad
)->blendfac
);
620 heap_free((*grad
)->blendpos
);
621 heap_free((*grad
)->surroundcolors
);
626 (*grad
)->blendfac
[0] = 1.0;
627 (*grad
)->blendpos
[0] = 1.0;
628 (*grad
)->blendcount
= 1;
630 (*grad
)->path
= path
;
632 (*grad
)->brush
.bt
= BrushTypePathGradient
;
633 (*grad
)->centercolor
= centercolor
;
634 (*grad
)->wrap
= WrapModeClamp
;
635 (*grad
)->gamma
= FALSE
;
636 for (i
=0; i
<path
->pathdata
.Count
; i
++)
638 sum_x
+= path
->pathdata
.Points
[i
].X
;
639 sum_y
+= path
->pathdata
.Points
[i
].Y
;
641 (*grad
)->center
.X
= sum_x
/ path
->pathdata
.Count
;
642 (*grad
)->center
.Y
= sum_y
/ path
->pathdata
.Count
;
644 (*grad
)->focus
.X
= 0.0;
645 (*grad
)->focus
.Y
= 0.0;
646 (*grad
)->surroundcolors
[0] = 0xffffffff;
647 (*grad
)->surroundcolorcount
= 1;
649 TRACE("<-- %p\n", *grad
);
654 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
655 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
660 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
663 return InvalidParameter
;
665 if(!points
|| count
<= 0)
668 stat
= GdipCreatePath(FillModeAlternate
, &path
);
672 stat
= GdipAddPathLine2(path
, points
, count
);
675 stat
= create_path_gradient(path
, 0xff000000, grad
);
678 GdipDeletePath(path
);
682 (*grad
)->wrap
= wrap
;
687 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
688 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
693 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
696 return InvalidParameter
;
698 if(!points
|| count
<= 0)
701 stat
= GdipCreatePath(FillModeAlternate
, &path
);
705 stat
= GdipAddPathLine2I(path
, points
, count
);
708 stat
= create_path_gradient(path
, 0xff000000, grad
);
711 GdipDeletePath(path
);
715 (*grad
)->wrap
= wrap
;
720 /******************************************************************************
721 * GdipCreatePathGradientFromPath [GDIPLUS.@]
723 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
724 GpPathGradient
**grad
)
729 TRACE("(%p, %p)\n", path
, grad
);
732 return InvalidParameter
;
737 stat
= GdipClonePath((GpPath
*)path
, &new_path
);
741 stat
= create_path_gradient(new_path
, 0xffffffff, grad
);
744 GdipDeletePath(new_path
);
750 /******************************************************************************
751 * GdipCreateSolidFill [GDIPLUS.@]
753 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
755 TRACE("(%lx, %p)\n", color
, sf
);
757 if(!sf
) return InvalidParameter
;
759 *sf
= heap_alloc_zero(sizeof(GpSolidFill
));
760 if (!*sf
) return OutOfMemory
;
762 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
763 (*sf
)->color
= color
;
765 TRACE("<-- %p\n", *sf
);
770 /******************************************************************************
771 * GdipCreateTexture [GDIPLUS.@]
774 * image [I] image to use
775 * wrapmode [I] optional
776 * texture [O] pointer to the resulting texturebrush
780 * FAILURE: element of GpStatus
782 GpStatus WINGDIPAPI
GdipCreateTexture(GpImage
*image
, GpWrapMode wrapmode
,
786 GpImageAttributes
*attributes
;
789 TRACE("%p, %d %p\n", image
, wrapmode
, texture
);
791 if (!(image
&& texture
))
792 return InvalidParameter
;
794 stat
= GdipGetImageWidth(image
, &width
);
795 if (stat
!= Ok
) return stat
;
796 stat
= GdipGetImageHeight(image
, &height
);
797 if (stat
!= Ok
) return stat
;
799 stat
= GdipCreateImageAttributes(&attributes
);
803 attributes
->wrap
= wrapmode
;
805 stat
= GdipCreateTextureIA(image
, attributes
, 0, 0, width
, height
,
808 GdipDisposeImageAttributes(attributes
);
814 /******************************************************************************
815 * GdipCreateTexture2 [GDIPLUS.@]
817 GpStatus WINGDIPAPI
GdipCreateTexture2(GpImage
*image
, GpWrapMode wrapmode
,
818 REAL x
, REAL y
, REAL width
, REAL height
, GpTexture
**texture
)
820 GpImageAttributes
*attributes
;
823 TRACE("%p %d %f %f %f %f %p\n", image
, wrapmode
,
824 x
, y
, width
, height
, texture
);
826 stat
= GdipCreateImageAttributes(&attributes
);
830 attributes
->wrap
= wrapmode
;
832 stat
= GdipCreateTextureIA(image
, attributes
, x
, y
, width
, height
,
835 GdipDisposeImageAttributes(attributes
);
841 /******************************************************************************
842 * GdipCreateTextureIA [GDIPLUS.@]
844 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
845 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
846 REAL height
, GpTexture
**texture
)
849 GpImage
*new_image
=NULL
;
851 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image
, imageattr
, x
, y
, width
, height
,
854 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
855 return InvalidParameter
;
859 if(image
->type
!= ImageTypeBitmap
){
860 FIXME("not implemented for image type %d\n", image
->type
);
861 return NotImplemented
;
864 status
= GdipCloneBitmapArea(x
, y
, width
, height
, PixelFormatDontCare
, (GpBitmap
*)image
, (GpBitmap
**)&new_image
);
868 *texture
= heap_alloc_zero(sizeof(GpTexture
));
870 status
= OutOfMemory
;
874 GdipSetMatrixElements(&(*texture
)->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
878 status
= GdipCloneImageAttributes(imageattr
, &(*texture
)->imageattributes
);
882 status
= GdipCreateImageAttributes(&(*texture
)->imageattributes
);
884 (*texture
)->imageattributes
->wrap
= WrapModeTile
;
888 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
889 (*texture
)->image
= new_image
;
895 TRACE("<-- %p\n", *texture
);
901 GdipDisposeImageAttributes((*texture
)->imageattributes
);
905 GdipDisposeImage(new_image
);
906 TRACE("<-- error %u\n", status
);
912 /******************************************************************************
913 * GdipCreateTextureIAI [GDIPLUS.@]
915 GpStatus WINGDIPAPI
GdipCreateTextureIAI(GpImage
*image
, GDIPCONST GpImageAttributes
*imageattr
,
916 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
918 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image
, imageattr
, x
, y
, width
, height
,
921 return GdipCreateTextureIA(image
,imageattr
,(REAL
)x
,(REAL
)y
,(REAL
)width
,(REAL
)height
,texture
);
924 GpStatus WINGDIPAPI
GdipCreateTexture2I(GpImage
*image
, GpWrapMode wrapmode
,
925 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
927 GpImageAttributes
*imageattr
;
930 TRACE("%p %d %d %d %d %d %p\n", image
, wrapmode
, x
, y
, width
, height
,
933 stat
= GdipCreateImageAttributes(&imageattr
);
937 imageattr
->wrap
= wrapmode
;
939 stat
= GdipCreateTextureIA(image
, imageattr
, x
, y
, width
, height
, texture
);
940 GdipDisposeImageAttributes(imageattr
);
946 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
948 TRACE("(%p, %p)\n", brush
, type
);
950 if(!brush
|| !type
) return InvalidParameter
;
957 GpStatus WINGDIPAPI
GdipGetHatchBackgroundColor(GpHatch
*brush
, ARGB
*backcol
)
959 TRACE("(%p, %p)\n", brush
, backcol
);
961 if(!brush
|| !backcol
) return InvalidParameter
;
963 *backcol
= brush
->backcol
;
968 GpStatus WINGDIPAPI
GdipGetHatchForegroundColor(GpHatch
*brush
, ARGB
*forecol
)
970 TRACE("(%p, %p)\n", brush
, forecol
);
972 if(!brush
|| !forecol
) return InvalidParameter
;
974 *forecol
= brush
->forecol
;
979 GpStatus WINGDIPAPI
GdipGetHatchStyle(GpHatch
*brush
, GpHatchStyle
*hatchstyle
)
981 TRACE("(%p, %p)\n", brush
, hatchstyle
);
983 if(!brush
|| !hatchstyle
) return InvalidParameter
;
985 *hatchstyle
= brush
->hatchstyle
;
990 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
992 TRACE("(%p)\n", brush
);
994 if(!brush
) return InvalidParameter
;
998 case BrushTypePathGradient
:
999 GdipDeletePath(((GpPathGradient
*) brush
)->path
);
1000 heap_free(((GpPathGradient
*) brush
)->blendfac
);
1001 heap_free(((GpPathGradient
*) brush
)->blendpos
);
1002 heap_free(((GpPathGradient
*) brush
)->surroundcolors
);
1003 heap_free(((GpPathGradient
*) brush
)->pblendcolor
);
1004 heap_free(((GpPathGradient
*) brush
)->pblendpos
);
1006 case BrushTypeLinearGradient
:
1007 heap_free(((GpLineGradient
*)brush
)->blendfac
);
1008 heap_free(((GpLineGradient
*)brush
)->blendpos
);
1009 heap_free(((GpLineGradient
*)brush
)->pblendcolor
);
1010 heap_free(((GpLineGradient
*)brush
)->pblendpos
);
1012 case BrushTypeTextureFill
:
1013 GdipDisposeImage(((GpTexture
*)brush
)->image
);
1014 GdipDisposeImageAttributes(((GpTexture
*)brush
)->imageattributes
);
1015 heap_free(((GpTexture
*)brush
)->bitmap_bits
);
1026 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
1029 TRACE("(%p, %p)\n", line
, usinggamma
);
1031 if(!line
|| !usinggamma
)
1032 return InvalidParameter
;
1034 *usinggamma
= line
->gamma
;
1039 GpStatus WINGDIPAPI
GdipGetLineWrapMode(GpLineGradient
*brush
, GpWrapMode
*wrapmode
)
1041 TRACE("(%p, %p)\n", brush
, wrapmode
);
1043 if(!brush
|| !wrapmode
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
1044 return InvalidParameter
;
1046 *wrapmode
= brush
->wrap
;
1051 GpStatus WINGDIPAPI
GdipGetPathGradientBlend(GpPathGradient
*brush
, REAL
*blend
,
1052 REAL
*positions
, INT count
)
1054 TRACE("(%p, %p, %p, %d)\n", brush
, blend
, positions
, count
);
1056 if(!brush
|| !blend
|| !positions
|| count
<= 0 || brush
->brush
.bt
!= BrushTypePathGradient
)
1057 return InvalidParameter
;
1059 if(count
< brush
->blendcount
)
1060 return InsufficientBuffer
;
1062 memcpy(blend
, brush
->blendfac
, count
*sizeof(REAL
));
1063 if(brush
->blendcount
> 1){
1064 memcpy(positions
, brush
->blendpos
, count
*sizeof(REAL
));
1070 GpStatus WINGDIPAPI
GdipGetPathGradientBlendCount(GpPathGradient
*brush
, INT
*count
)
1072 TRACE("(%p, %p)\n", brush
, count
);
1074 if(!brush
|| !count
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1075 return InvalidParameter
;
1077 *count
= brush
->blendcount
;
1082 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
1085 TRACE("(%p, %p)\n", grad
, point
);
1087 if(!grad
|| !point
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1088 return InvalidParameter
;
1090 point
->X
= grad
->center
.X
;
1091 point
->Y
= grad
->center
.Y
;
1096 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
1102 TRACE("(%p, %p)\n", grad
, point
);
1105 return InvalidParameter
;
1107 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
1110 point
->X
= gdip_round(ptf
.X
);
1111 point
->Y
= gdip_round(ptf
.Y
);
1117 GpStatus WINGDIPAPI
GdipGetPathGradientCenterColor(GpPathGradient
*grad
,
1120 TRACE("(%p,%p)\n", grad
, colors
);
1122 if (!grad
|| !colors
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1123 return InvalidParameter
;
1125 *colors
= grad
->centercolor
;
1130 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
1133 TRACE("(%p, %p, %p)\n", grad
, x
, y
);
1135 if(!grad
|| !x
|| !y
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1136 return InvalidParameter
;
1144 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
1147 TRACE("(%p, %p)\n", grad
, gamma
);
1149 if(!grad
|| !gamma
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1150 return InvalidParameter
;
1152 *gamma
= grad
->gamma
;
1157 GpStatus WINGDIPAPI
GdipGetPathGradientPath(GpPathGradient
*grad
, GpPath
*path
)
1161 TRACE("(%p, %p)\n", grad
, path
);
1164 FIXME("not implemented\n");
1166 return NotImplemented
;
1169 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
1172 TRACE("(%p, %p)\n", grad
, count
);
1174 if(!grad
|| !count
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1175 return InvalidParameter
;
1177 *count
= grad
->path
->pathdata
.Count
;
1182 GpStatus WINGDIPAPI
GdipGetPathGradientRect(GpPathGradient
*brush
, GpRectF
*rect
)
1186 TRACE("(%p, %p)\n", brush
, rect
);
1188 if(!brush
|| !rect
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1189 return InvalidParameter
;
1191 stat
= GdipGetPathWorldBounds(brush
->path
, rect
, NULL
, NULL
);
1196 GpStatus WINGDIPAPI
GdipGetPathGradientRectI(GpPathGradient
*brush
, GpRect
*rect
)
1201 TRACE("(%p, %p)\n", brush
, rect
);
1204 return InvalidParameter
;
1206 stat
= GdipGetPathGradientRect(brush
, &rectf
);
1207 if(stat
!= Ok
) return stat
;
1209 rect
->X
= gdip_round(rectf
.X
);
1210 rect
->Y
= gdip_round(rectf
.Y
);
1211 rect
->Width
= gdip_round(rectf
.Width
);
1212 rect
->Height
= gdip_round(rectf
.Height
);
1217 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1218 *grad
, ARGB
*argb
, INT
*count
)
1222 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1224 if(!grad
|| !argb
|| !count
|| (*count
< grad
->path
->pathdata
.Count
) || grad
->brush
.bt
!= BrushTypePathGradient
)
1225 return InvalidParameter
;
1227 for (i
=0; i
<grad
->path
->pathdata
.Count
; i
++)
1229 if (i
< grad
->surroundcolorcount
)
1230 argb
[i
] = grad
->surroundcolors
[i
];
1232 argb
[i
] = grad
->surroundcolors
[grad
->surroundcolorcount
-1];
1235 *count
= grad
->surroundcolorcount
;
1240 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorCount(GpPathGradient
*brush
, INT
*count
)
1242 TRACE("(%p, %p)\n", brush
, count
);
1244 if (!brush
|| !count
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1245 return InvalidParameter
;
1247 /* Yes, this actually returns the number of points in the path (which is the
1248 * required size of a buffer to get the surround colors), rather than the
1249 * number of surround colors. The real count is returned when getting the
1251 *count
= brush
->path
->pathdata
.Count
;
1256 GpStatus WINGDIPAPI
GdipGetPathGradientWrapMode(GpPathGradient
*brush
,
1257 GpWrapMode
*wrapmode
)
1259 TRACE("(%p, %p)\n", brush
, wrapmode
);
1261 if(!brush
|| !wrapmode
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1262 return InvalidParameter
;
1264 *wrapmode
= brush
->wrap
;
1269 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
1271 TRACE("(%p, %p)\n", sf
, argb
);
1274 return InvalidParameter
;
1281 /******************************************************************************
1282 * GdipGetTextureImage [GDIPLUS.@]
1284 GpStatus WINGDIPAPI
GdipGetTextureImage(GpTexture
*brush
, GpImage
**image
)
1286 TRACE("(%p, %p)\n", brush
, image
);
1288 if(!brush
|| !image
)
1289 return InvalidParameter
;
1291 return GdipCloneImage(brush
->image
, image
);
1294 /******************************************************************************
1295 * GdipGetTextureTransform [GDIPLUS.@]
1297 GpStatus WINGDIPAPI
GdipGetTextureTransform(GpTexture
*brush
, GpMatrix
*matrix
)
1299 TRACE("(%p, %s)\n", brush
, debugstr_matrix(matrix
));
1301 if(!brush
|| !matrix
)
1302 return InvalidParameter
;
1304 *matrix
= brush
->transform
;
1309 /******************************************************************************
1310 * GdipGetTextureWrapMode [GDIPLUS.@]
1312 GpStatus WINGDIPAPI
GdipGetTextureWrapMode(GpTexture
*brush
, GpWrapMode
*wrapmode
)
1314 TRACE("(%p, %p)\n", brush
, wrapmode
);
1316 if(!brush
|| !wrapmode
)
1317 return InvalidParameter
;
1319 *wrapmode
= brush
->imageattributes
->wrap
;
1324 /******************************************************************************
1325 * GdipMultiplyTextureTransform [GDIPLUS.@]
1327 GpStatus WINGDIPAPI
GdipMultiplyTextureTransform(GpTexture
* brush
,
1328 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1330 TRACE("(%p, %s, %d)\n", brush
, debugstr_matrix(matrix
), order
);
1332 if(!brush
|| !matrix
)
1333 return InvalidParameter
;
1335 return GdipMultiplyMatrix(&brush
->transform
, matrix
, order
);
1338 /******************************************************************************
1339 * GdipResetTextureTransform [GDIPLUS.@]
1341 GpStatus WINGDIPAPI
GdipResetTextureTransform(GpTexture
* brush
)
1343 TRACE("(%p)\n", brush
);
1346 return InvalidParameter
;
1348 return GdipSetMatrixElements(&brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1351 /******************************************************************************
1352 * GdipScaleTextureTransform [GDIPLUS.@]
1354 GpStatus WINGDIPAPI
GdipScaleTextureTransform(GpTexture
* brush
,
1355 REAL sx
, REAL sy
, GpMatrixOrder order
)
1357 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, sx
, sy
, order
);
1360 return InvalidParameter
;
1362 return GdipScaleMatrix(&brush
->transform
, sx
, sy
, order
);
1365 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
1366 GDIPCONST REAL
*factors
, GDIPCONST REAL
* positions
, INT count
)
1368 REAL
*new_blendfac
, *new_blendpos
;
1370 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1372 if(!brush
|| !factors
|| !positions
|| count
<= 0 || brush
->brush
.bt
!= BrushTypeLinearGradient
||
1373 (count
>= 2 && (positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)))
1374 return InvalidParameter
;
1376 new_blendfac
= heap_alloc_zero(count
* sizeof(REAL
));
1377 new_blendpos
= heap_alloc_zero(count
* sizeof(REAL
));
1379 if (!new_blendfac
|| !new_blendpos
)
1381 heap_free(new_blendfac
);
1382 heap_free(new_blendpos
);
1386 memcpy(new_blendfac
, factors
, count
* sizeof(REAL
));
1387 memcpy(new_blendpos
, positions
, count
* sizeof(REAL
));
1389 heap_free(brush
->blendfac
);
1390 heap_free(brush
->blendpos
);
1392 brush
->blendcount
= count
;
1393 brush
->blendfac
= new_blendfac
;
1394 brush
->blendpos
= new_blendpos
;
1399 GpStatus WINGDIPAPI
GdipGetLineBlend(GpLineGradient
*brush
, REAL
*factors
,
1400 REAL
*positions
, INT count
)
1402 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1404 if (!brush
|| !factors
|| !positions
|| count
<= 0 || brush
->brush
.bt
!= BrushTypeLinearGradient
)
1405 return InvalidParameter
;
1407 if (count
< brush
->blendcount
)
1408 return InsufficientBuffer
;
1410 memcpy(factors
, brush
->blendfac
, brush
->blendcount
* sizeof(REAL
));
1411 memcpy(positions
, brush
->blendpos
, brush
->blendcount
* sizeof(REAL
));
1416 GpStatus WINGDIPAPI
GdipGetLineBlendCount(GpLineGradient
*brush
, INT
*count
)
1418 TRACE("(%p, %p)\n", brush
, count
);
1420 if (!brush
|| !count
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
1421 return InvalidParameter
;
1423 *count
= brush
->blendcount
;
1428 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
1431 TRACE("(%p, %d)\n", line
, usegamma
);
1433 if(!line
|| line
->brush
.bt
!= BrushTypeLinearGradient
)
1434 return InvalidParameter
;
1436 line
->gamma
= usegamma
;
1441 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
1448 const int precision
= 16;
1449 REAL erf_range
; /* we use values erf(-erf_range) through erf(+erf_range) */
1453 TRACE("(%p, %0.2f, %0.2f)\n", line
, focus
, scale
);
1455 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0 || line
->brush
.bt
!= BrushTypeLinearGradient
)
1456 return InvalidParameter
;
1458 /* we want 2 standard deviations */
1459 erf_range
= 2.0 / sqrt(2);
1461 /* calculate the constants we need to normalize the error function to be
1462 between 0.0 and scale over the range we need */
1463 min_erf
= erf(-erf_range
);
1464 scale_erf
= scale
/ (-2.0 * min_erf
);
1470 for (i
=1; i
<precision
; i
++)
1472 positions
[i
] = focus
* i
/ precision
;
1473 factors
[i
] = scale_erf
* (erf(2 * erf_range
* i
/ precision
- erf_range
) - min_erf
);
1475 num_points
+= precision
;
1478 positions
[num_points
] = focus
;
1479 factors
[num_points
] = scale
;
1484 for (i
=1; i
<precision
; i
++)
1486 positions
[i
+num_points
-1] = (focus
+ ((1.0-focus
) * i
/ precision
));
1487 factors
[i
+num_points
-1] = scale_erf
* (erf(erf_range
- 2 * erf_range
* i
/ precision
) - min_erf
);
1489 num_points
+= precision
;
1490 positions
[num_points
-1] = 1.0;
1491 factors
[num_points
-1] = 0.0;
1494 return GdipSetLineBlend(line
, factors
, positions
, num_points
);
1497 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
1500 TRACE("(%p, %d)\n", line
, wrap
);
1502 if(!line
|| wrap
== WrapModeClamp
|| line
->brush
.bt
!= BrushTypeLinearGradient
)
1503 return InvalidParameter
;
1510 GpStatus WINGDIPAPI
GdipSetPathGradientBlend(GpPathGradient
*brush
, GDIPCONST REAL
*blend
,
1511 GDIPCONST REAL
*pos
, INT count
)
1513 REAL
*new_blendfac
, *new_blendpos
;
1515 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, pos
, count
);
1517 if(!brush
|| !blend
|| !pos
|| count
<= 0 || brush
->brush
.bt
!= BrushTypePathGradient
||
1518 (count
>= 2 && (pos
[0] != 0.0f
|| pos
[count
-1] != 1.0f
)))
1519 return InvalidParameter
;
1521 new_blendfac
= heap_alloc_zero(count
* sizeof(REAL
));
1522 new_blendpos
= heap_alloc_zero(count
* sizeof(REAL
));
1524 if (!new_blendfac
|| !new_blendpos
)
1526 heap_free(new_blendfac
);
1527 heap_free(new_blendpos
);
1531 memcpy(new_blendfac
, blend
, count
* sizeof(REAL
));
1532 memcpy(new_blendpos
, pos
, count
* sizeof(REAL
));
1534 heap_free(brush
->blendfac
);
1535 heap_free(brush
->blendpos
);
1537 brush
->blendcount
= count
;
1538 brush
->blendfac
= new_blendfac
;
1539 brush
->blendpos
= new_blendpos
;
1544 GpStatus WINGDIPAPI
GdipSetPathGradientLinearBlend(GpPathGradient
*brush
,
1545 REAL focus
, REAL scale
)
1551 TRACE("(%p,%0.2f,%0.2f)\n", brush
, focus
, scale
);
1553 if (!brush
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1554 return InvalidParameter
;
1558 factors
[num_points
] = 0.0;
1559 positions
[num_points
] = 0.0;
1563 factors
[num_points
] = scale
;
1564 positions
[num_points
] = focus
;
1569 factors
[num_points
] = 0.0;
1570 positions
[num_points
] = 1.0;
1574 return GdipSetPathGradientBlend(brush
, factors
, positions
, num_points
);
1577 GpStatus WINGDIPAPI
GdipSetPathGradientPresetBlend(GpPathGradient
*brush
,
1578 GDIPCONST ARGB
*blend
, GDIPCONST REAL
*pos
, INT count
)
1582 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, pos
, count
);
1584 if (!brush
|| !blend
|| !pos
|| count
< 2 || brush
->brush
.bt
!= BrushTypePathGradient
||
1585 pos
[0] != 0.0f
|| pos
[count
-1] != 1.0f
)
1587 return InvalidParameter
;
1590 new_color
= heap_alloc_zero(count
* sizeof(ARGB
));
1591 new_pos
= heap_alloc_zero(count
* sizeof(REAL
));
1592 if (!new_color
|| !new_pos
)
1594 heap_free(new_color
);
1599 memcpy(new_color
, blend
, sizeof(ARGB
) * count
);
1600 memcpy(new_pos
, pos
, sizeof(REAL
) * count
);
1602 heap_free(brush
->pblendcolor
);
1603 heap_free(brush
->pblendpos
);
1605 brush
->pblendcolor
= new_color
;
1606 brush
->pblendpos
= new_pos
;
1607 brush
->pblendcount
= count
;
1612 GpStatus WINGDIPAPI
GdipGetPathGradientPresetBlend(GpPathGradient
*brush
,
1613 ARGB
*blend
, REAL
*pos
, INT count
)
1615 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, pos
, count
);
1620 if (!brush
|| !blend
|| !pos
|| count
< 2 || brush
->brush
.bt
!= BrushTypePathGradient
)
1621 return InvalidParameter
;
1623 if (brush
->pblendcount
== 0)
1624 return GenericError
;
1626 if (count
!= brush
->pblendcount
)
1628 /* Native lines up the ends of each array, and copies the destination size. */
1629 FIXME("Braindead behavior on wrong-sized buffer not implemented.\n");
1630 return InvalidParameter
;
1633 memcpy(blend
, brush
->pblendcolor
, sizeof(ARGB
) * brush
->pblendcount
);
1634 memcpy(pos
, brush
->pblendpos
, sizeof(REAL
) * brush
->pblendcount
);
1639 GpStatus WINGDIPAPI
GdipGetPathGradientPresetBlendCount(GpPathGradient
*brush
,
1642 TRACE("(%p,%p)\n", brush
, count
);
1644 if (!brush
|| !count
|| brush
->brush
.bt
!= BrushTypePathGradient
)
1645 return InvalidParameter
;
1647 *count
= brush
->pblendcount
;
1652 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
1655 TRACE("(%p, %lx)\n", grad
, argb
);
1657 if(!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1658 return InvalidParameter
;
1660 grad
->centercolor
= argb
;
1664 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
1667 TRACE("(%p, %s)\n", grad
, debugstr_pointf(point
));
1669 if(!grad
|| !point
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1670 return InvalidParameter
;
1672 grad
->center
.X
= point
->X
;
1673 grad
->center
.Y
= point
->Y
;
1678 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
1683 TRACE("(%p, %p)\n", grad
, point
);
1686 return InvalidParameter
;
1688 ptf
.X
= (REAL
)point
->X
;
1689 ptf
.Y
= (REAL
)point
->Y
;
1691 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
1694 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
1697 TRACE("(%p, %.2f, %.2f)\n", grad
, x
, y
);
1699 if(!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1700 return InvalidParameter
;
1708 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
1711 TRACE("(%p, %d)\n", grad
, gamma
);
1713 if(!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1714 return InvalidParameter
;
1716 grad
->gamma
= gamma
;
1721 GpStatus WINGDIPAPI
GdipSetPathGradientPath(GpPathGradient
*grad
, GDIPCONST GpPath
*path
)
1725 TRACE("(%p, %p)\n", grad
, path
);
1728 FIXME("not implemented\n");
1730 return NotImplemented
;
1733 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
1734 REAL focus
, REAL scale
)
1740 const int precision
= 16;
1741 REAL erf_range
; /* we use values erf(-erf_range) through erf(+erf_range) */
1745 TRACE("(%p,%0.2f,%0.2f)\n", grad
, focus
, scale
);
1747 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0 || grad
->brush
.bt
!= BrushTypePathGradient
)
1748 return InvalidParameter
;
1750 /* we want 2 standard deviations */
1751 erf_range
= 2.0 / sqrt(2);
1753 /* calculate the constants we need to normalize the error function to be
1754 between 0.0 and scale over the range we need */
1755 min_erf
= erf(-erf_range
);
1756 scale_erf
= scale
/ (-2.0 * min_erf
);
1762 for (i
=1; i
<precision
; i
++)
1764 positions
[i
] = focus
* i
/ precision
;
1765 factors
[i
] = scale_erf
* (erf(2 * erf_range
* i
/ precision
- erf_range
) - min_erf
);
1767 num_points
+= precision
;
1770 positions
[num_points
] = focus
;
1771 factors
[num_points
] = scale
;
1776 for (i
=1; i
<precision
; i
++)
1778 positions
[i
+num_points
-1] = (focus
+ ((1.0-focus
) * i
/ precision
));
1779 factors
[i
+num_points
-1] = scale_erf
* (erf(erf_range
- 2 * erf_range
* i
/ precision
) - min_erf
);
1781 num_points
+= precision
;
1782 positions
[num_points
-1] = 1.0;
1783 factors
[num_points
-1] = 0.0;
1786 return GdipSetPathGradientBlend(grad
, factors
, positions
, num_points
);
1789 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1790 *grad
, GDIPCONST ARGB
*argb
, INT
*count
)
1792 ARGB
*new_surroundcolors
;
1795 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1797 if(!grad
|| !argb
|| !count
|| (*count
<= 0) || grad
->brush
.bt
!= BrushTypePathGradient
||
1798 (*count
> grad
->path
->pathdata
.Count
))
1799 return InvalidParameter
;
1801 num_colors
= *count
;
1803 /* If all colors are the same, only store 1 color. */
1806 for (i
=1; i
< num_colors
; i
++)
1807 if (argb
[i
] != argb
[i
-1])
1810 if (i
== num_colors
)
1814 new_surroundcolors
= heap_alloc_zero(num_colors
* sizeof(ARGB
));
1815 if (!new_surroundcolors
)
1818 memcpy(new_surroundcolors
, argb
, num_colors
* sizeof(ARGB
));
1820 heap_free(grad
->surroundcolors
);
1822 grad
->surroundcolors
= new_surroundcolors
;
1823 grad
->surroundcolorcount
= num_colors
;
1828 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
1831 TRACE("(%p, %d)\n", grad
, wrap
);
1833 if(!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1834 return InvalidParameter
;
1841 GpStatus WINGDIPAPI
GdipSetPathGradientTransform(GpPathGradient
*grad
,
1844 TRACE("(%p,%s)\n", grad
, debugstr_matrix(matrix
));
1846 if (!grad
|| !matrix
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1847 return InvalidParameter
;
1849 grad
->transform
= *matrix
;
1854 GpStatus WINGDIPAPI
GdipGetPathGradientTransform(GpPathGradient
*grad
,
1857 TRACE("(%p,%s)\n", grad
, debugstr_matrix(matrix
));
1859 if (!grad
|| !matrix
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1860 return InvalidParameter
;
1862 *matrix
= grad
->transform
;
1867 GpStatus WINGDIPAPI
GdipMultiplyPathGradientTransform(GpPathGradient
*grad
,
1868 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1870 TRACE("(%p,%s,%i)\n", grad
, debugstr_matrix(matrix
), order
);
1872 if (!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1873 return InvalidParameter
;
1875 return GdipMultiplyMatrix(&grad
->transform
, matrix
, order
);
1878 GpStatus WINGDIPAPI
GdipResetPathGradientTransform(GpPathGradient
*grad
)
1880 TRACE("(%p)\n", grad
);
1882 if (!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1883 return InvalidParameter
;
1885 return GdipSetMatrixElements(&grad
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1888 GpStatus WINGDIPAPI
GdipRotatePathGradientTransform(GpPathGradient
*grad
,
1889 REAL angle
, GpMatrixOrder order
)
1891 TRACE("(%p,%0.2f,%i)\n", grad
, angle
, order
);
1893 if (!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1894 return InvalidParameter
;
1896 return GdipRotateMatrix(&grad
->transform
, angle
, order
);
1899 GpStatus WINGDIPAPI
GdipScalePathGradientTransform(GpPathGradient
*grad
,
1900 REAL sx
, REAL sy
, GpMatrixOrder order
)
1902 TRACE("(%p,%0.2f,%0.2f,%i)\n", grad
, sx
, sy
, order
);
1904 if (!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1905 return InvalidParameter
;
1907 return GdipScaleMatrix(&grad
->transform
, sx
, sy
, order
);
1910 GpStatus WINGDIPAPI
GdipTranslatePathGradientTransform(GpPathGradient
*grad
,
1911 REAL dx
, REAL dy
, GpMatrixOrder order
)
1913 TRACE("(%p,%0.2f,%0.2f,%i)\n", grad
, dx
, dy
, order
);
1915 if (!grad
|| grad
->brush
.bt
!= BrushTypePathGradient
)
1916 return InvalidParameter
;
1918 return GdipTranslateMatrix(&grad
->transform
, dx
, dy
, order
);
1921 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
1923 TRACE("(%p, %lx)\n", sf
, argb
);
1926 return InvalidParameter
;
1932 /******************************************************************************
1933 * GdipSetTextureTransform [GDIPLUS.@]
1935 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
1936 GDIPCONST GpMatrix
*matrix
)
1938 TRACE("(%p, %s)\n", texture
, debugstr_matrix(matrix
));
1940 if(!texture
|| !matrix
)
1941 return InvalidParameter
;
1943 texture
->transform
= *matrix
;
1948 /******************************************************************************
1949 * GdipSetTextureWrapMode [GDIPLUS.@]
1951 * WrapMode not used, only stored
1953 GpStatus WINGDIPAPI
GdipSetTextureWrapMode(GpTexture
*brush
, GpWrapMode wrapmode
)
1955 TRACE("(%p, %d)\n", brush
, wrapmode
);
1958 return InvalidParameter
;
1960 brush
->imageattributes
->wrap
= wrapmode
;
1965 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
1968 TRACE("(%p, %lx, %lx)\n", brush
, color1
, color2
);
1970 if(!brush
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
1971 return InvalidParameter
;
1973 brush
->startcolor
= color1
;
1974 brush
->endcolor
= color2
;
1979 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
1981 TRACE("(%p, %p)\n", brush
, colors
);
1983 if(!brush
|| !colors
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
1984 return InvalidParameter
;
1986 colors
[0] = brush
->startcolor
;
1987 colors
[1] = brush
->endcolor
;
1992 /******************************************************************************
1993 * GdipRotateTextureTransform [GDIPLUS.@]
1995 GpStatus WINGDIPAPI
GdipRotateTextureTransform(GpTexture
* brush
, REAL angle
,
1996 GpMatrixOrder order
)
1998 TRACE("(%p, %.2f, %d)\n", brush
, angle
, order
);
2001 return InvalidParameter
;
2003 return GdipRotateMatrix(&brush
->transform
, angle
, order
);
2006 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
2013 TRACE("(%p,%.2f,%.2f)\n", brush
, focus
, scale
);
2015 if (!brush
) return InvalidParameter
;
2019 factors
[num_points
] = 0.0;
2020 positions
[num_points
] = 0.0;
2024 factors
[num_points
] = scale
;
2025 positions
[num_points
] = focus
;
2030 factors
[num_points
] = 0.0;
2031 positions
[num_points
] = 1.0;
2035 return GdipSetLineBlend(brush
, factors
, positions
, num_points
);
2038 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
2039 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
2043 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, positions
, count
);
2045 if (!brush
|| !blend
|| !positions
|| count
< 2 || brush
->brush
.bt
!= BrushTypeLinearGradient
||
2046 positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)
2048 return InvalidParameter
;
2051 new_color
= heap_alloc_zero(count
* sizeof(ARGB
));
2052 new_pos
= heap_alloc_zero(count
* sizeof(REAL
));
2053 if (!new_color
|| !new_pos
)
2055 heap_free(new_color
);
2060 memcpy(new_color
, blend
, sizeof(ARGB
) * count
);
2061 memcpy(new_pos
, positions
, sizeof(REAL
) * count
);
2063 heap_free(brush
->pblendcolor
);
2064 heap_free(brush
->pblendpos
);
2066 brush
->pblendcolor
= new_color
;
2067 brush
->pblendpos
= new_pos
;
2068 brush
->pblendcount
= count
;
2073 GpStatus WINGDIPAPI
GdipGetLinePresetBlend(GpLineGradient
*brush
,
2074 ARGB
*blend
, REAL
* positions
, INT count
)
2076 if (!brush
|| !blend
|| !positions
|| count
< 2 || brush
->brush
.bt
!= BrushTypeLinearGradient
)
2077 return InvalidParameter
;
2079 if (brush
->pblendcount
== 0)
2080 return GenericError
;
2082 if (count
< brush
->pblendcount
)
2083 return InsufficientBuffer
;
2085 memcpy(blend
, brush
->pblendcolor
, sizeof(ARGB
) * brush
->pblendcount
);
2086 memcpy(positions
, brush
->pblendpos
, sizeof(REAL
) * brush
->pblendcount
);
2091 GpStatus WINGDIPAPI
GdipGetLinePresetBlendCount(GpLineGradient
*brush
,
2094 if (!brush
|| !count
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
2095 return InvalidParameter
;
2097 *count
= brush
->pblendcount
;
2102 GpStatus WINGDIPAPI
GdipResetLineTransform(GpLineGradient
*brush
)
2104 TRACE("(%p)\n", brush
);
2107 return InvalidParameter
;
2109 return GdipSetMatrixElements(&brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
2112 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
2113 GDIPCONST GpMatrix
*matrix
)
2115 TRACE("(%p,%s)\n", brush
, debugstr_matrix(matrix
));
2117 if(!brush
|| !matrix
)
2118 return InvalidParameter
;
2120 brush
->transform
= *matrix
;
2125 GpStatus WINGDIPAPI
GdipGetLineTransform(GpLineGradient
*brush
, GpMatrix
*matrix
)
2127 TRACE("(%p,%s)\n", brush
, debugstr_matrix(matrix
));
2129 if(!brush
|| !matrix
)
2130 return InvalidParameter
;
2132 *matrix
= brush
->transform
;
2137 GpStatus WINGDIPAPI
GdipScaleLineTransform(GpLineGradient
*brush
, REAL sx
, REAL sy
,
2138 GpMatrixOrder order
)
2140 TRACE("(%p,%0.2f,%0.2f,%u)\n", brush
, sx
, sy
, order
);
2143 return InvalidParameter
;
2145 return GdipScaleMatrix(&brush
->transform
, sx
, sy
, order
);
2148 GpStatus WINGDIPAPI
GdipMultiplyLineTransform(GpLineGradient
*brush
,
2149 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
2151 TRACE("(%p,%s,%u)\n", brush
, debugstr_matrix(matrix
), order
);
2154 return InvalidParameter
;
2159 return GdipMultiplyMatrix(&brush
->transform
, matrix
, order
);
2162 GpStatus WINGDIPAPI
GdipTranslateLineTransform(GpLineGradient
*brush
,
2163 REAL dx
, REAL dy
, GpMatrixOrder order
)
2165 TRACE("(%p,%f,%f,%d)\n", brush
, dx
, dy
, order
);
2168 return InvalidParameter
;
2170 return GdipTranslateMatrix(&brush
->transform
, dx
, dy
, order
);
2173 /******************************************************************************
2174 * GdipTranslateTextureTransform [GDIPLUS.@]
2176 GpStatus WINGDIPAPI
GdipTranslateTextureTransform(GpTexture
* brush
, REAL dx
, REAL dy
,
2177 GpMatrixOrder order
)
2179 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, dx
, dy
, order
);
2182 return InvalidParameter
;
2184 return GdipTranslateMatrix(&brush
->transform
, dx
, dy
, order
);
2187 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
2189 TRACE("(%p, %p)\n", brush
, rect
);
2191 if(!brush
|| !rect
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
2192 return InvalidParameter
;
2194 *rect
= brush
->rect
;
2199 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
2204 TRACE("(%p, %p)\n", brush
, rect
);
2207 return InvalidParameter
;
2209 ret
= GdipGetLineRect(brush
, &rectF
);
2212 rect
->X
= gdip_round(rectF
.X
);
2213 rect
->Y
= gdip_round(rectF
.Y
);
2214 rect
->Width
= gdip_round(rectF
.Width
);
2215 rect
->Height
= gdip_round(rectF
.Height
);
2221 GpStatus WINGDIPAPI
GdipRotateLineTransform(GpLineGradient
* brush
,
2222 REAL angle
, GpMatrixOrder order
)
2226 TRACE("(%p,%0.2f,%u)\n", brush
, angle
, order
);
2228 if(!brush
|| brush
->brush
.bt
!= BrushTypeLinearGradient
)
2229 return InvalidParameter
;
2232 FIXME("(%p, %.2f, %d) stub\n", brush
, angle
, order
);
2234 return NotImplemented
;