2 * Copyright (C) 2007 Google (Evan Stade)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "gdiplus_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus
);
37 /******************************************************************************
38 * GdipCloneBrush [GDIPLUS.@]
40 GpStatus WINGDIPAPI
GdipCloneBrush(GpBrush
*brush
, GpBrush
**clone
)
42 TRACE("(%p, %p)\n", brush
, clone
);
45 return InvalidParameter
;
48 case BrushTypeSolidColor
:
51 *clone
= GdipAlloc(sizeof(GpSolidFill
));
52 if (!*clone
) return OutOfMemory
;
54 fill
= (GpSolidFill
*)*clone
;
56 memcpy(*clone
, brush
, sizeof(GpSolidFill
));
58 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
59 fill
->bmp
= ARGB2BMP(fill
->color
);
62 case BrushTypeHatchFill
:
64 GpHatch
*hatch
= (GpHatch
*)brush
;
66 return GdipCreateHatchBrush(hatch
->hatchstyle
, hatch
->forecol
, hatch
->backcol
, (GpHatch
**)clone
);
68 case BrushTypePathGradient
:{
69 GpPathGradient
*src
, *dest
;
72 *clone
= GdipAlloc(sizeof(GpPathGradient
));
73 if (!*clone
) return OutOfMemory
;
75 src
= (GpPathGradient
*) brush
,
76 dest
= (GpPathGradient
*) *clone
;
77 count
= src
->pathdata
.Count
;
79 memcpy(dest
, src
, sizeof(GpPathGradient
));
81 dest
->pathdata
.Count
= count
;
82 dest
->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
83 dest
->pathdata
.Types
= GdipAlloc(count
);
85 if(!dest
->pathdata
.Points
|| !dest
->pathdata
.Types
){
86 GdipFree(dest
->pathdata
.Points
);
87 GdipFree(dest
->pathdata
.Types
);
92 memcpy(dest
->pathdata
.Points
, src
->pathdata
.Points
, count
* sizeof(PointF
));
93 memcpy(dest
->pathdata
.Types
, src
->pathdata
.Types
, count
);
96 count
= src
->blendcount
;
97 dest
->blendcount
= count
;
98 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
99 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
101 if(!dest
->blendfac
|| !dest
->blendpos
){
102 GdipFree(dest
->pathdata
.Points
);
103 GdipFree(dest
->pathdata
.Types
);
104 GdipFree(dest
->blendfac
);
105 GdipFree(dest
->blendpos
);
110 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
111 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
115 case BrushTypeLinearGradient
:{
116 GpLineGradient
*dest
, *src
;
119 dest
= GdipAlloc(sizeof(GpLineGradient
));
120 if(!dest
) return OutOfMemory
;
122 src
= (GpLineGradient
*)brush
;
124 memcpy(dest
, src
, sizeof(GpLineGradient
));
126 dest
->brush
.gdibrush
= CreateSolidBrush(dest
->brush
.lb
.lbColor
);
128 count
= dest
->blendcount
;
129 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
130 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
131 pcount
= dest
->pblendcount
;
134 dest
->pblendcolor
= GdipAlloc(pcount
* sizeof(ARGB
));
135 dest
->pblendpos
= GdipAlloc(pcount
* sizeof(REAL
));
138 if (!dest
->blendfac
|| !dest
->blendpos
||
139 (pcount
&& (!dest
->pblendcolor
|| !dest
->pblendpos
)))
141 GdipFree(dest
->blendfac
);
142 GdipFree(dest
->blendpos
);
143 GdipFree(dest
->pblendcolor
);
144 GdipFree(dest
->pblendpos
);
145 DeleteObject(dest
->brush
.gdibrush
);
150 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
151 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
155 memcpy(dest
->pblendcolor
, src
->pblendcolor
, pcount
* sizeof(ARGB
));
156 memcpy(dest
->pblendpos
, src
->pblendpos
, pcount
* sizeof(REAL
));
159 *clone
= &dest
->brush
;
162 case BrushTypeTextureFill
:
165 GpTexture
*texture
= (GpTexture
*)brush
;
166 GpTexture
*new_texture
;
169 stat
= GdipGetImageWidth(texture
->image
, &width
);
170 if (stat
!= Ok
) return stat
;
171 stat
= GdipGetImageHeight(texture
->image
, &height
);
172 if (stat
!= Ok
) return stat
;
174 stat
= GdipCreateTextureIA(texture
->image
, texture
->imageattributes
, 0, 0, width
, height
, &new_texture
);
178 memcpy(new_texture
->transform
, texture
->transform
, sizeof(GpMatrix
));
179 *clone
= (GpBrush
*)new_texture
;
187 ERR("not implemented for brush type %d\n", brush
->bt
);
188 return NotImplemented
;
191 TRACE("<-- %p\n", *clone
);
195 static const char HatchBrushes
[][8] = {
196 { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HatchStyleHorizontal */
197 { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleVertical */
198 { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HatchStyleForwardDiagonal */
199 { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleBackwardDiagonal */
200 { 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleCross */
201 { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleDiagonalCross */
202 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80 }, /* HatchStyle05Percent */
203 { 0x00, 0x02, 0x00, 0x88, 0x00, 0x20, 0x00, 0x88 }, /* HatchStyle10Percent */
204 { 0x00, 0x22, 0x00, 0xcc, 0x00, 0x22, 0x00, 0xcc }, /* HatchStyle20Percent */
205 { 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc }, /* HatchStyle25Percent */
206 { 0x00, 0xcc, 0x04, 0xcc, 0x00, 0xcc, 0x40, 0xcc }, /* HatchStyle30Percent */
207 { 0x44, 0xcc, 0x22, 0xcc, 0x44, 0xcc, 0x22, 0xcc }, /* HatchStyle40Percent */
208 { 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc }, /* HatchStyle50Percent */
209 { 0x55, 0xcd, 0x55, 0xee, 0x55, 0xdc, 0x55, 0xee }, /* HatchStyle60Percent */
210 { 0x55, 0xdd, 0x55, 0xff, 0x55, 0xdd, 0x55, 0xff }, /* HatchStyle70Percent */
211 { 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff }, /* HatchStyle75Percent */
212 { 0x55, 0xff, 0x59, 0xff, 0x55, 0xff, 0x99, 0xff }, /* HatchStyle80Percent */
213 { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xfd, 0xff }, /* HatchStyle90Percent */
214 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, /* HatchStyleLightDownwardDiagonal */
215 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, /* HatchStyleLightUpwardDiagonal */
216 { 0x99, 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc }, /* HatchStyleDarkDownwardDiagonal */
217 { 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 }, /* HatchStyleDarkUpwardDiagonal */
218 { 0xc1, 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0 }, /* HatchStyleWideDownwardDiagonal */
219 { 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83, 0xc1 }, /* HatchStyleWideUpwardDiagonal */
220 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, /* HatchStyleLightVertical */
221 { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleLightHorizontal */
222 { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, /* HatchStyleNarrowVertical */
223 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, /* HatchStyleNarrowHorizontal */
224 { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, /* HatchStyleDarkVertical */
225 { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
228 GpStatus
get_hatch_data(HatchStyle hatchstyle
, const char **result
)
230 if (hatchstyle
< sizeof(HatchBrushes
) / sizeof(HatchBrushes
[0]))
232 *result
= HatchBrushes
[hatchstyle
];
236 return NotImplemented
;
239 /******************************************************************************
240 * GdipCreateHatchBrush [GDIPLUS.@]
242 GpStatus WINGDIPAPI
GdipCreateHatchBrush(HatchStyle hatchstyle
, ARGB forecol
, ARGB backcol
, GpHatch
**brush
)
244 COLORREF fgcol
= ARGB2COLORREF(forecol
);
247 TRACE("(%d, %d, %d, %p)\n", hatchstyle
, forecol
, backcol
, brush
);
249 if(!brush
) return InvalidParameter
;
251 *brush
= GdipAlloc(sizeof(GpHatch
));
252 if (!*brush
) return OutOfMemory
;
254 if (hatchstyle
< sizeof(HatchBrushes
) / sizeof(HatchBrushes
[0]))
258 BITMAPINFOHEADER bmih
;
262 hdc
= CreateCompatibleDC(0);
266 bmih
.biSize
= sizeof(bmih
);
270 bmih
.biBitCount
= 32;
271 bmih
.biCompression
= BI_RGB
;
272 bmih
.biSizeImage
= 0;
274 hbmp
= CreateDIBSection(hdc
, (BITMAPINFO
*)&bmih
, DIB_RGB_COLORS
, (void**)&bits
, NULL
, 0);
280 if ((HatchBrushes
[hatchstyle
][y
] & (0x80 >> x
)) != 0)
281 bits
[y
*8+x
] = forecol
;
283 bits
[y
*8+x
] = backcol
;
295 (*brush
)->brush
.lb
.lbStyle
= BS_PATTERN
;
296 (*brush
)->brush
.lb
.lbColor
= 0;
297 (*brush
)->brush
.lb
.lbHatch
= (ULONG_PTR
)hbmp
;
298 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
305 FIXME("Unimplemented hatch style %d\n", hatchstyle
);
307 (*brush
)->brush
.lb
.lbStyle
= BS_SOLID
;
308 (*brush
)->brush
.lb
.lbColor
= fgcol
;
309 (*brush
)->brush
.lb
.lbHatch
= 0;
310 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
315 (*brush
)->brush
.bt
= BrushTypeHatchFill
;
316 (*brush
)->forecol
= forecol
;
317 (*brush
)->backcol
= backcol
;
318 (*brush
)->hatchstyle
= hatchstyle
;
319 TRACE("<-- %p\n", *brush
);
330 /******************************************************************************
331 * GdipCreateLineBrush [GDIPLUS.@]
333 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
334 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
335 GpWrapMode wrap
, GpLineGradient
**line
)
337 COLORREF col
= ARGB2COLORREF(startcolor
);
339 TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint
),
340 debugstr_pointf(endpoint
), startcolor
, endcolor
, wrap
, line
);
342 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
343 return InvalidParameter
;
345 if (startpoint
->X
== endpoint
->X
&& startpoint
->Y
== endpoint
->Y
)
348 *line
= GdipAlloc(sizeof(GpLineGradient
));
349 if(!*line
) return OutOfMemory
;
351 (*line
)->brush
.lb
.lbStyle
= BS_SOLID
;
352 (*line
)->brush
.lb
.lbColor
= col
;
353 (*line
)->brush
.lb
.lbHatch
= 0;
354 (*line
)->brush
.gdibrush
= CreateSolidBrush(col
);
355 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
357 (*line
)->startpoint
.X
= startpoint
->X
;
358 (*line
)->startpoint
.Y
= startpoint
->Y
;
359 (*line
)->endpoint
.X
= endpoint
->X
;
360 (*line
)->endpoint
.Y
= endpoint
->Y
;
361 (*line
)->startcolor
= startcolor
;
362 (*line
)->endcolor
= endcolor
;
363 (*line
)->wrap
= wrap
;
364 (*line
)->gamma
= FALSE
;
366 (*line
)->rect
.X
= (startpoint
->X
< endpoint
->X
? startpoint
->X
: endpoint
->X
);
367 (*line
)->rect
.Y
= (startpoint
->Y
< endpoint
->Y
? startpoint
->Y
: endpoint
->Y
);
368 (*line
)->rect
.Width
= fabs(startpoint
->X
- endpoint
->X
);
369 (*line
)->rect
.Height
= fabs(startpoint
->Y
- endpoint
->Y
);
371 if ((*line
)->rect
.Width
== 0)
373 (*line
)->rect
.X
-= (*line
)->rect
.Height
/ 2.0f
;
374 (*line
)->rect
.Width
= (*line
)->rect
.Height
;
376 else if ((*line
)->rect
.Height
== 0)
378 (*line
)->rect
.Y
-= (*line
)->rect
.Width
/ 2.0f
;
379 (*line
)->rect
.Height
= (*line
)->rect
.Width
;
382 (*line
)->blendcount
= 1;
383 (*line
)->blendfac
= GdipAlloc(sizeof(REAL
));
384 (*line
)->blendpos
= GdipAlloc(sizeof(REAL
));
386 if (!(*line
)->blendfac
|| !(*line
)->blendpos
)
388 GdipFree((*line
)->blendfac
);
389 GdipFree((*line
)->blendpos
);
390 DeleteObject((*line
)->brush
.gdibrush
);
396 (*line
)->blendfac
[0] = 1.0f
;
397 (*line
)->blendpos
[0] = 1.0f
;
399 (*line
)->pblendcolor
= NULL
;
400 (*line
)->pblendpos
= NULL
;
401 (*line
)->pblendcount
= 0;
403 TRACE("<-- %p\n", *line
);
408 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
409 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
410 GpWrapMode wrap
, GpLineGradient
**line
)
415 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
416 startcolor
, endcolor
, wrap
, line
);
418 if(!startpoint
|| !endpoint
)
419 return InvalidParameter
;
421 stF
.X
= (REAL
)startpoint
->X
;
422 stF
.Y
= (REAL
)startpoint
->Y
;
423 endF
.X
= (REAL
)endpoint
->X
;
424 endF
.Y
= (REAL
)endpoint
->Y
;
426 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
429 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
430 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
431 GpLineGradient
**line
)
436 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
440 return InvalidParameter
;
444 case LinearGradientModeHorizontal
:
447 end
.X
= rect
->X
+ rect
->Width
;
450 case LinearGradientModeVertical
:
454 end
.Y
= rect
->Y
+ rect
->Height
;
456 case LinearGradientModeForwardDiagonal
:
459 end
.X
= rect
->X
+ rect
->Width
;
460 end
.Y
= rect
->Y
+ rect
->Height
;
462 case LinearGradientModeBackwardDiagonal
:
463 start
.X
= rect
->X
+ rect
->Width
;
466 end
.Y
= rect
->Y
+ rect
->Height
;
469 return InvalidParameter
;
472 stat
= GdipCreateLineBrush(&start
, &end
, startcolor
, endcolor
, wrap
, line
);
475 (*line
)->rect
= *rect
;
480 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
481 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
482 GpLineGradient
**line
)
486 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
489 rectF
.X
= (REAL
) rect
->X
;
490 rectF
.Y
= (REAL
) rect
->Y
;
491 rectF
.Width
= (REAL
) rect
->Width
;
492 rectF
.Height
= (REAL
) rect
->Height
;
494 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
497 /******************************************************************************
498 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
500 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF
* rect
,
501 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
502 GpLineGradient
**line
)
505 LinearGradientMode mode
;
506 REAL width
, height
, exofs
, eyofs
;
507 REAL sin_angle
, cos_angle
, sin_cos_angle
;
509 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
512 sin_angle
= sinf(deg2rad(angle
));
513 cos_angle
= cosf(deg2rad(angle
));
514 sin_cos_angle
= sin_angle
* cos_angle
;
518 width
= height
= 1.0;
523 height
= rect
->Height
;
526 if (sin_cos_angle
>= 0)
527 mode
= LinearGradientModeForwardDiagonal
;
529 mode
= LinearGradientModeBackwardDiagonal
;
531 stat
= GdipCreateLineBrushFromRect(rect
, startcolor
, endcolor
, mode
, wrap
, line
);
535 if (sin_cos_angle
>= 0)
537 exofs
= width
* sin_cos_angle
+ height
* cos_angle
* cos_angle
;
538 eyofs
= width
* sin_angle
* sin_angle
+ height
* sin_cos_angle
;
542 exofs
= width
* sin_angle
* sin_angle
+ height
* sin_cos_angle
;
543 eyofs
= -width
* sin_cos_angle
+ height
* sin_angle
* sin_angle
;
548 exofs
= exofs
* rect
->Width
;
549 eyofs
= eyofs
* rect
->Height
;
554 (*line
)->endpoint
.X
= rect
->X
+ exofs
;
555 (*line
)->endpoint
.Y
= rect
->Y
+ eyofs
;
559 (*line
)->endpoint
.X
= (*line
)->startpoint
.X
;
560 (*line
)->endpoint
.Y
= (*line
)->startpoint
.Y
;
561 (*line
)->startpoint
.X
= rect
->X
+ exofs
;
562 (*line
)->startpoint
.Y
= rect
->Y
+ eyofs
;
569 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect
* rect
,
570 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
571 GpLineGradient
**line
)
573 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
576 return GdipCreateLineBrushFromRectI(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
580 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
581 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
583 COLORREF col
= ARGB2COLORREF(0xffffffff);
585 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
588 return InvalidParameter
;
593 *grad
= GdipAlloc(sizeof(GpPathGradient
));
594 if (!*grad
) return OutOfMemory
;
596 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
597 (*grad
)->blendpos
= GdipAlloc(sizeof(REAL
));
598 if(!(*grad
)->blendfac
|| !(*grad
)->blendpos
){
599 GdipFree((*grad
)->blendfac
);
600 GdipFree((*grad
)->blendpos
);
605 (*grad
)->blendfac
[0] = 1.0;
606 (*grad
)->blendpos
[0] = 1.0;
607 (*grad
)->blendcount
= 1;
609 (*grad
)->pathdata
.Count
= count
;
610 (*grad
)->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
611 (*grad
)->pathdata
.Types
= GdipAlloc(count
);
613 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
614 GdipFree((*grad
)->pathdata
.Points
);
615 GdipFree((*grad
)->pathdata
.Types
);
620 memcpy((*grad
)->pathdata
.Points
, points
, count
* sizeof(PointF
));
621 memset((*grad
)->pathdata
.Types
, PathPointTypeLine
, count
);
623 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
624 (*grad
)->brush
.lb
.lbColor
= col
;
625 (*grad
)->brush
.lb
.lbHatch
= 0;
627 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
628 (*grad
)->brush
.bt
= BrushTypePathGradient
;
629 (*grad
)->centercolor
= 0xffffffff;
630 (*grad
)->wrap
= wrap
;
631 (*grad
)->gamma
= FALSE
;
632 (*grad
)->center
.X
= 0.0;
633 (*grad
)->center
.Y
= 0.0;
634 (*grad
)->focus
.X
= 0.0;
635 (*grad
)->focus
.Y
= 0.0;
637 TRACE("<-- %p\n", *grad
);
642 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
643 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
649 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
652 return InvalidParameter
;
657 pointsF
= GdipAlloc(sizeof(GpPointF
) * count
);
661 for(i
= 0; i
< count
; i
++){
662 pointsF
[i
].X
= (REAL
)points
[i
].X
;
663 pointsF
[i
].Y
= (REAL
)points
[i
].Y
;
666 ret
= GdipCreatePathGradient(pointsF
, count
, wrap
, grad
);
672 /******************************************************************************
673 * GdipCreatePathGradientFromPath [GDIPLUS.@]
675 * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
677 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
678 GpPathGradient
**grad
)
680 COLORREF col
= ARGB2COLORREF(0xffffffff);
682 TRACE("(%p, %p)\n", path
, grad
);
685 return InvalidParameter
;
687 *grad
= GdipAlloc(sizeof(GpPathGradient
));
688 if (!*grad
) return OutOfMemory
;
690 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
691 (*grad
)->blendpos
= GdipAlloc(sizeof(REAL
));
692 if(!(*grad
)->blendfac
|| !(*grad
)->blendpos
){
693 GdipFree((*grad
)->blendfac
);
694 GdipFree((*grad
)->blendpos
);
699 (*grad
)->blendfac
[0] = 1.0;
700 (*grad
)->blendpos
[0] = 1.0;
701 (*grad
)->blendcount
= 1;
703 (*grad
)->pathdata
.Count
= path
->pathdata
.Count
;
704 (*grad
)->pathdata
.Points
= GdipAlloc(path
->pathdata
.Count
* sizeof(PointF
));
705 (*grad
)->pathdata
.Types
= GdipAlloc(path
->pathdata
.Count
);
707 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
708 GdipFree((*grad
)->pathdata
.Points
);
709 GdipFree((*grad
)->pathdata
.Types
);
714 memcpy((*grad
)->pathdata
.Points
, path
->pathdata
.Points
,
715 path
->pathdata
.Count
* sizeof(PointF
));
716 memcpy((*grad
)->pathdata
.Types
, path
->pathdata
.Types
, path
->pathdata
.Count
);
718 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
719 (*grad
)->brush
.lb
.lbColor
= col
;
720 (*grad
)->brush
.lb
.lbHatch
= 0;
722 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
723 (*grad
)->brush
.bt
= BrushTypePathGradient
;
724 (*grad
)->centercolor
= 0xffffffff;
725 (*grad
)->wrap
= WrapModeClamp
;
726 (*grad
)->gamma
= FALSE
;
727 /* FIXME: this should be set to the "centroid" of the path by default */
728 (*grad
)->center
.X
= 0.0;
729 (*grad
)->center
.Y
= 0.0;
730 (*grad
)->focus
.X
= 0.0;
731 (*grad
)->focus
.Y
= 0.0;
733 TRACE("<-- %p\n", *grad
);
738 /******************************************************************************
739 * GdipCreateSolidFill [GDIPLUS.@]
741 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
743 COLORREF col
= ARGB2COLORREF(color
);
745 TRACE("(%x, %p)\n", color
, sf
);
747 if(!sf
) return InvalidParameter
;
749 *sf
= GdipAlloc(sizeof(GpSolidFill
));
750 if (!*sf
) return OutOfMemory
;
752 (*sf
)->brush
.lb
.lbStyle
= BS_SOLID
;
753 (*sf
)->brush
.lb
.lbColor
= col
;
754 (*sf
)->brush
.lb
.lbHatch
= 0;
756 (*sf
)->brush
.gdibrush
= CreateSolidBrush(col
);
757 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
758 (*sf
)->color
= color
;
759 (*sf
)->bmp
= ARGB2BMP(color
);
761 TRACE("<-- %p\n", *sf
);
766 /******************************************************************************
767 * GdipCreateTexture [GDIPLUS.@]
770 * image [I] image to use
771 * wrapmode [I] optional
772 * texture [O] pointer to the resulting texturebrush
776 * FAILURE: element of GpStatus
778 GpStatus WINGDIPAPI
GdipCreateTexture(GpImage
*image
, GpWrapMode wrapmode
,
782 GpImageAttributes
*attributes
;
785 TRACE("%p, %d %p\n", image
, wrapmode
, texture
);
787 if (!(image
&& texture
))
788 return InvalidParameter
;
790 stat
= GdipGetImageWidth(image
, &width
);
791 if (stat
!= Ok
) return stat
;
792 stat
= GdipGetImageHeight(image
, &height
);
793 if (stat
!= Ok
) return stat
;
795 stat
= GdipCreateImageAttributes(&attributes
);
799 attributes
->wrap
= wrapmode
;
801 stat
= GdipCreateTextureIA(image
, attributes
, 0, 0, width
, height
,
804 GdipDisposeImageAttributes(attributes
);
810 /******************************************************************************
811 * GdipCreateTexture2 [GDIPLUS.@]
813 GpStatus WINGDIPAPI
GdipCreateTexture2(GpImage
*image
, GpWrapMode wrapmode
,
814 REAL x
, REAL y
, REAL width
, REAL height
, GpTexture
**texture
)
816 GpImageAttributes
*attributes
;
819 TRACE("%p %d %f %f %f %f %p\n", image
, wrapmode
,
820 x
, y
, width
, height
, texture
);
822 stat
= GdipCreateImageAttributes(&attributes
);
826 attributes
->wrap
= wrapmode
;
828 stat
= GdipCreateTextureIA(image
, attributes
, x
, y
, width
, height
,
831 GdipDisposeImageAttributes(attributes
);
837 /******************************************************************************
838 * GdipCreateTextureIA [GDIPLUS.@]
840 * FIXME: imageattr ignored
842 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
843 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
844 REAL height
, GpTexture
**texture
)
848 GpImage
*new_image
=NULL
;
850 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image
, imageattr
, x
, y
, width
, height
,
853 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
854 return InvalidParameter
;
858 if(image
->type
!= ImageTypeBitmap
){
859 FIXME("not implemented for image type %d\n", image
->type
);
860 return NotImplemented
;
863 status
= GdipCloneBitmapArea(x
, y
, width
, height
, PixelFormatDontCare
, (GpBitmap
*)image
, (GpBitmap
**)&new_image
);
867 status
= GdipCreateHBITMAPFromBitmap((GpBitmap
*)new_image
, &hbm
, 0);
870 status
= GenericError
;
874 *texture
= GdipAlloc(sizeof(GpTexture
));
876 status
= OutOfMemory
;
880 if((status
= GdipCreateMatrix(&(*texture
)->transform
)) != Ok
){
886 status
= GdipCloneImageAttributes(imageattr
, &(*texture
)->imageattributes
);
890 status
= GdipCreateImageAttributes(&(*texture
)->imageattributes
);
892 (*texture
)->imageattributes
->wrap
= WrapModeTile
;
897 (*texture
)->brush
.lb
.lbStyle
= BS_PATTERN
;
898 (*texture
)->brush
.lb
.lbColor
= 0;
899 (*texture
)->brush
.lb
.lbHatch
= (ULONG_PTR
)hbm
;
901 (*texture
)->brush
.gdibrush
= CreateBrushIndirect(&(*texture
)->brush
.lb
);
902 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
903 (*texture
)->image
= new_image
;
908 TRACE("<-- %p\n", *texture
);
914 GdipDeleteMatrix((*texture
)->transform
);
915 GdipDisposeImageAttributes((*texture
)->imageattributes
);
919 GdipDisposeImage(new_image
);
920 TRACE("<-- error %u\n", status
);
928 /******************************************************************************
929 * GdipCreateTextureIAI [GDIPLUS.@]
931 GpStatus WINGDIPAPI
GdipCreateTextureIAI(GpImage
*image
, GDIPCONST GpImageAttributes
*imageattr
,
932 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
934 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image
, imageattr
, x
, y
, width
, height
,
937 return GdipCreateTextureIA(image
,imageattr
,(REAL
)x
,(REAL
)y
,(REAL
)width
,(REAL
)height
,texture
);
940 GpStatus WINGDIPAPI
GdipCreateTexture2I(GpImage
*image
, GpWrapMode wrapmode
,
941 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
943 GpImageAttributes
*imageattr
;
946 TRACE("%p %d %d %d %d %d %p\n", image
, wrapmode
, x
, y
, width
, height
,
949 stat
= GdipCreateImageAttributes(&imageattr
);
953 imageattr
->wrap
= wrapmode
;
955 stat
= GdipCreateTextureIA(image
, imageattr
, x
, y
, width
, height
, texture
);
961 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
963 TRACE("(%p, %p)\n", brush
, type
);
965 if(!brush
|| !type
) return InvalidParameter
;
972 GpStatus WINGDIPAPI
GdipGetHatchBackgroundColor(GpHatch
*brush
, ARGB
*backcol
)
974 TRACE("(%p, %p)\n", brush
, backcol
);
976 if(!brush
|| !backcol
) return InvalidParameter
;
978 *backcol
= brush
->backcol
;
983 GpStatus WINGDIPAPI
GdipGetHatchForegroundColor(GpHatch
*brush
, ARGB
*forecol
)
985 TRACE("(%p, %p)\n", brush
, forecol
);
987 if(!brush
|| !forecol
) return InvalidParameter
;
989 *forecol
= brush
->forecol
;
994 GpStatus WINGDIPAPI
GdipGetHatchStyle(GpHatch
*brush
, HatchStyle
*hatchstyle
)
996 TRACE("(%p, %p)\n", brush
, hatchstyle
);
998 if(!brush
|| !hatchstyle
) return InvalidParameter
;
1000 *hatchstyle
= brush
->hatchstyle
;
1005 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
1007 TRACE("(%p)\n", brush
);
1009 if(!brush
) return InvalidParameter
;
1013 case BrushTypePathGradient
:
1014 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Points
);
1015 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Types
);
1016 GdipFree(((GpPathGradient
*) brush
)->blendfac
);
1017 GdipFree(((GpPathGradient
*) brush
)->blendpos
);
1019 case BrushTypeSolidColor
:
1020 if (((GpSolidFill
*)brush
)->bmp
)
1021 DeleteObject(((GpSolidFill
*)brush
)->bmp
);
1023 case BrushTypeLinearGradient
:
1024 GdipFree(((GpLineGradient
*)brush
)->blendfac
);
1025 GdipFree(((GpLineGradient
*)brush
)->blendpos
);
1026 GdipFree(((GpLineGradient
*)brush
)->pblendcolor
);
1027 GdipFree(((GpLineGradient
*)brush
)->pblendpos
);
1029 case BrushTypeTextureFill
:
1030 GdipDeleteMatrix(((GpTexture
*)brush
)->transform
);
1031 GdipDisposeImage(((GpTexture
*)brush
)->image
);
1032 GdipDisposeImageAttributes(((GpTexture
*)brush
)->imageattributes
);
1033 GdipFree(((GpTexture
*)brush
)->bitmap_bits
);
1039 DeleteObject(brush
->gdibrush
);
1045 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
1048 TRACE("(%p, %p)\n", line
, usinggamma
);
1050 if(!line
|| !usinggamma
)
1051 return InvalidParameter
;
1053 *usinggamma
= line
->gamma
;
1058 GpStatus WINGDIPAPI
GdipGetLineWrapMode(GpLineGradient
*brush
, GpWrapMode
*wrapmode
)
1060 TRACE("(%p, %p)\n", brush
, wrapmode
);
1062 if(!brush
|| !wrapmode
)
1063 return InvalidParameter
;
1065 *wrapmode
= brush
->wrap
;
1070 GpStatus WINGDIPAPI
GdipGetPathGradientBlend(GpPathGradient
*brush
, REAL
*blend
,
1071 REAL
*positions
, INT count
)
1073 TRACE("(%p, %p, %p, %d)\n", brush
, blend
, positions
, count
);
1075 if(!brush
|| !blend
|| !positions
|| count
<= 0)
1076 return InvalidParameter
;
1078 if(count
< brush
->blendcount
)
1079 return InsufficientBuffer
;
1081 memcpy(blend
, brush
->blendfac
, count
*sizeof(REAL
));
1082 if(brush
->blendcount
> 1){
1083 memcpy(positions
, brush
->blendpos
, count
*sizeof(REAL
));
1089 GpStatus WINGDIPAPI
GdipGetPathGradientBlendCount(GpPathGradient
*brush
, INT
*count
)
1091 TRACE("(%p, %p)\n", brush
, count
);
1093 if(!brush
|| !count
)
1094 return InvalidParameter
;
1096 *count
= brush
->blendcount
;
1101 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
1104 TRACE("(%p, %p)\n", grad
, point
);
1107 return InvalidParameter
;
1109 point
->X
= grad
->center
.X
;
1110 point
->Y
= grad
->center
.Y
;
1115 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
1121 TRACE("(%p, %p)\n", grad
, point
);
1124 return InvalidParameter
;
1126 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
1129 point
->X
= roundr(ptf
.X
);
1130 point
->Y
= roundr(ptf
.Y
);
1136 GpStatus WINGDIPAPI
GdipGetPathGradientCenterColor(GpPathGradient
*grad
,
1141 TRACE("(%p,%p)\n", grad
, colors
);
1144 FIXME("not implemented\n");
1146 return NotImplemented
;
1149 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
1152 TRACE("(%p, %p, %p)\n", grad
, x
, y
);
1154 if(!grad
|| !x
|| !y
)
1155 return InvalidParameter
;
1163 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
1166 TRACE("(%p, %p)\n", grad
, gamma
);
1169 return InvalidParameter
;
1171 *gamma
= grad
->gamma
;
1176 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
1179 TRACE("(%p, %p)\n", grad
, count
);
1182 return InvalidParameter
;
1184 *count
= grad
->pathdata
.Count
;
1189 GpStatus WINGDIPAPI
GdipGetPathGradientRect(GpPathGradient
*brush
, GpRectF
*rect
)
1195 TRACE("(%p, %p)\n", brush
, rect
);
1198 return InvalidParameter
;
1200 stat
= GdipCreatePath2(brush
->pathdata
.Points
, brush
->pathdata
.Types
,
1201 brush
->pathdata
.Count
, FillModeAlternate
, &path
);
1202 if(stat
!= Ok
) return stat
;
1204 stat
= GdipGetPathWorldBounds(path
, &r
, NULL
, NULL
);
1206 GdipDeletePath(path
);
1210 memcpy(rect
, &r
, sizeof(GpRectF
));
1212 GdipDeletePath(path
);
1217 GpStatus WINGDIPAPI
GdipGetPathGradientRectI(GpPathGradient
*brush
, GpRect
*rect
)
1222 TRACE("(%p, %p)\n", brush
, rect
);
1225 return InvalidParameter
;
1227 stat
= GdipGetPathGradientRect(brush
, &rectf
);
1228 if(stat
!= Ok
) return stat
;
1230 rect
->X
= roundr(rectf
.X
);
1231 rect
->Y
= roundr(rectf
.Y
);
1232 rect
->Width
= roundr(rectf
.Width
);
1233 rect
->Height
= roundr(rectf
.Height
);
1238 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1239 *grad
, ARGB
*argb
, INT
*count
)
1243 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1245 if(!grad
|| !argb
|| !count
|| (*count
< grad
->pathdata
.Count
))
1246 return InvalidParameter
;
1249 FIXME("not implemented\n");
1251 return NotImplemented
;
1254 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorCount(GpPathGradient
*brush
, INT
*count
)
1258 TRACE("(%p, %p)\n", brush
, count
);
1260 if (!brush
|| !count
)
1261 return InvalidParameter
;
1264 FIXME("not implemented\n");
1266 return NotImplemented
;
1269 GpStatus WINGDIPAPI
GdipGetPathGradientWrapMode(GpPathGradient
*brush
,
1270 GpWrapMode
*wrapmode
)
1272 TRACE("(%p, %p)\n", brush
, wrapmode
);
1274 if(!brush
|| !wrapmode
)
1275 return InvalidParameter
;
1277 *wrapmode
= brush
->wrap
;
1282 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
1284 TRACE("(%p, %p)\n", sf
, argb
);
1287 return InvalidParameter
;
1294 /******************************************************************************
1295 * GdipGetTextureImage [GDIPLUS.@]
1297 GpStatus WINGDIPAPI
GdipGetTextureImage(GpTexture
*brush
, GpImage
**image
)
1299 TRACE("(%p, %p)\n", brush
, image
);
1301 if(!brush
|| !image
)
1302 return InvalidParameter
;
1304 return GdipCloneImage(brush
->image
, image
);
1307 /******************************************************************************
1308 * GdipGetTextureTransform [GDIPLUS.@]
1310 GpStatus WINGDIPAPI
GdipGetTextureTransform(GpTexture
*brush
, GpMatrix
*matrix
)
1312 TRACE("(%p, %p)\n", brush
, matrix
);
1314 if(!brush
|| !matrix
)
1315 return InvalidParameter
;
1317 memcpy(matrix
, brush
->transform
, sizeof(GpMatrix
));
1322 /******************************************************************************
1323 * GdipGetTextureWrapMode [GDIPLUS.@]
1325 GpStatus WINGDIPAPI
GdipGetTextureWrapMode(GpTexture
*brush
, GpWrapMode
*wrapmode
)
1327 TRACE("(%p, %p)\n", brush
, wrapmode
);
1329 if(!brush
|| !wrapmode
)
1330 return InvalidParameter
;
1332 *wrapmode
= brush
->imageattributes
->wrap
;
1337 /******************************************************************************
1338 * GdipMultiplyTextureTransform [GDIPLUS.@]
1340 GpStatus WINGDIPAPI
GdipMultiplyTextureTransform(GpTexture
* brush
,
1341 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1343 TRACE("(%p, %p, %d)\n", brush
, matrix
, order
);
1345 if(!brush
|| !matrix
)
1346 return InvalidParameter
;
1348 return GdipMultiplyMatrix(brush
->transform
, matrix
, order
);
1351 /******************************************************************************
1352 * GdipResetTextureTransform [GDIPLUS.@]
1354 GpStatus WINGDIPAPI
GdipResetTextureTransform(GpTexture
* brush
)
1356 TRACE("(%p)\n", brush
);
1359 return InvalidParameter
;
1361 return GdipSetMatrixElements(brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1364 /******************************************************************************
1365 * GdipScaleTextureTransform [GDIPLUS.@]
1367 GpStatus WINGDIPAPI
GdipScaleTextureTransform(GpTexture
* brush
,
1368 REAL sx
, REAL sy
, GpMatrixOrder order
)
1370 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, sx
, sy
, order
);
1373 return InvalidParameter
;
1375 return GdipScaleMatrix(brush
->transform
, sx
, sy
, order
);
1378 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
1379 GDIPCONST REAL
*factors
, GDIPCONST REAL
* positions
, INT count
)
1381 REAL
*new_blendfac
, *new_blendpos
;
1383 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1385 if(!brush
|| !factors
|| !positions
|| count
<= 0 ||
1386 (count
>= 2 && (positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)))
1387 return InvalidParameter
;
1389 new_blendfac
= GdipAlloc(count
* sizeof(REAL
));
1390 new_blendpos
= GdipAlloc(count
* sizeof(REAL
));
1392 if (!new_blendfac
|| !new_blendpos
)
1394 GdipFree(new_blendfac
);
1395 GdipFree(new_blendpos
);
1399 memcpy(new_blendfac
, factors
, count
* sizeof(REAL
));
1400 memcpy(new_blendpos
, positions
, count
* sizeof(REAL
));
1402 GdipFree(brush
->blendfac
);
1403 GdipFree(brush
->blendpos
);
1405 brush
->blendcount
= count
;
1406 brush
->blendfac
= new_blendfac
;
1407 brush
->blendpos
= new_blendpos
;
1412 GpStatus WINGDIPAPI
GdipGetLineBlend(GpLineGradient
*brush
, REAL
*factors
,
1413 REAL
*positions
, INT count
)
1415 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1417 if (!brush
|| !factors
|| !positions
|| count
<= 0)
1418 return InvalidParameter
;
1420 if (count
< brush
->blendcount
)
1421 return InsufficientBuffer
;
1423 memcpy(factors
, brush
->blendfac
, brush
->blendcount
* sizeof(REAL
));
1424 memcpy(positions
, brush
->blendpos
, brush
->blendcount
* sizeof(REAL
));
1429 GpStatus WINGDIPAPI
GdipGetLineBlendCount(GpLineGradient
*brush
, INT
*count
)
1431 TRACE("(%p, %p)\n", brush
, count
);
1433 if (!brush
|| !count
)
1434 return InvalidParameter
;
1436 *count
= brush
->blendcount
;
1441 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
1444 TRACE("(%p, %d)\n", line
, usegamma
);
1447 return InvalidParameter
;
1449 line
->gamma
= usegamma
;
1454 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
1461 const int precision
= 16;
1462 REAL erf_range
; /* we use values erf(-erf_range) through erf(+erf_range) */
1466 TRACE("(%p, %0.2f, %0.2f)\n", line
, focus
, scale
);
1468 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1469 return InvalidParameter
;
1471 /* we want 2 standard deviations */
1472 erf_range
= 2.0 / sqrt(2);
1474 /* calculate the constants we need to normalize the error function to be
1475 between 0.0 and scale over the range we need */
1476 min_erf
= erf(-erf_range
);
1477 scale_erf
= scale
/ (-2.0 * min_erf
);
1483 for (i
=1; i
<precision
; i
++)
1485 positions
[i
] = focus
* i
/ precision
;
1486 factors
[i
] = scale_erf
* (erf(2 * erf_range
* i
/ precision
- erf_range
) - min_erf
);
1488 num_points
+= precision
;
1491 positions
[num_points
] = focus
;
1492 factors
[num_points
] = scale
;
1497 for (i
=1; i
<precision
; i
++)
1499 positions
[i
+num_points
-1] = (focus
+ ((1.0-focus
) * i
/ precision
));
1500 factors
[i
+num_points
-1] = scale_erf
* (erf(erf_range
- 2 * erf_range
* i
/ precision
) - min_erf
);
1502 num_points
+= precision
;
1503 positions
[num_points
-1] = 1.0;
1504 factors
[num_points
-1] = 0.0;
1507 return GdipSetLineBlend(line
, factors
, positions
, num_points
);
1510 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
1513 TRACE("(%p, %d)\n", line
, wrap
);
1515 if(!line
|| wrap
== WrapModeClamp
)
1516 return InvalidParameter
;
1523 GpStatus WINGDIPAPI
GdipSetPathGradientBlend(GpPathGradient
*brush
, GDIPCONST REAL
*blend
,
1524 GDIPCONST REAL
*pos
, INT count
)
1528 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, pos
, count
);
1531 FIXME("not implemented\n");
1533 return NotImplemented
;
1536 GpStatus WINGDIPAPI
GdipSetPathGradientLinearBlend(GpPathGradient
*brush
,
1537 REAL focus
, REAL scale
)
1541 TRACE("(%p,%0.2f,%0.2f)\n", brush
, focus
, scale
);
1544 FIXME("not implemented\n");
1546 return NotImplemented
;
1549 GpStatus WINGDIPAPI
GdipSetPathGradientPresetBlend(GpPathGradient
*brush
,
1550 GDIPCONST ARGB
*blend
, GDIPCONST REAL
*pos
, INT count
)
1552 FIXME("(%p,%p,%p,%i): stub\n", brush
, blend
, pos
, count
);
1553 return NotImplemented
;
1556 GpStatus WINGDIPAPI
GdipGetPathGradientPresetBlend(GpPathGradient
*brush
,
1557 ARGB
*blend
, REAL
*pos
, INT count
)
1559 FIXME("(%p,%p,%p,%i): stub\n", brush
, blend
, pos
, count
);
1560 return NotImplemented
;
1563 GpStatus WINGDIPAPI
GdipGetPathGradientPresetBlendCount(GpPathGradient
*brush
,
1566 FIXME("(%p,%p): stub\n", brush
, count
);
1567 return NotImplemented
;
1570 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
1573 TRACE("(%p, %x)\n", grad
, argb
);
1576 return InvalidParameter
;
1578 grad
->centercolor
= argb
;
1579 grad
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1581 DeleteObject(grad
->brush
.gdibrush
);
1582 grad
->brush
.gdibrush
= CreateSolidBrush(grad
->brush
.lb
.lbColor
);
1587 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
1590 TRACE("(%p, %s)\n", grad
, debugstr_pointf(point
));
1593 return InvalidParameter
;
1595 grad
->center
.X
= point
->X
;
1596 grad
->center
.Y
= point
->Y
;
1601 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
1606 TRACE("(%p, %p)\n", grad
, point
);
1609 return InvalidParameter
;
1611 ptf
.X
= (REAL
)point
->X
;
1612 ptf
.Y
= (REAL
)point
->Y
;
1614 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
1617 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
1620 TRACE("(%p, %.2f, %.2f)\n", grad
, x
, y
);
1623 return InvalidParameter
;
1631 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
1634 TRACE("(%p, %d)\n", grad
, gamma
);
1637 return InvalidParameter
;
1639 grad
->gamma
= gamma
;
1644 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
1645 REAL focus
, REAL scale
)
1649 TRACE("(%p,%0.2f,%0.2f)\n", grad
, focus
, scale
);
1651 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1652 return InvalidParameter
;
1655 FIXME("not implemented\n");
1657 return NotImplemented
;
1660 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1661 *grad
, GDIPCONST ARGB
*argb
, INT
*count
)
1665 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1667 if(!grad
|| !argb
|| !count
|| (*count
<= 0) ||
1668 (*count
> grad
->pathdata
.Count
))
1669 return InvalidParameter
;
1672 FIXME("not implemented\n");
1674 return NotImplemented
;
1677 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
1680 TRACE("(%p, %d)\n", grad
, wrap
);
1683 return InvalidParameter
;
1690 GpStatus WINGDIPAPI
GdipSetPathGradientTransform(GpPathGradient
*grad
,
1695 TRACE("(%p,%p)\n", grad
, matrix
);
1698 FIXME("not implemented\n");
1700 return NotImplemented
;
1703 GpStatus WINGDIPAPI
GdipGetPathGradientTransform(GpPathGradient
*grad
,
1708 TRACE("(%p,%p)\n", grad
, matrix
);
1711 FIXME("not implemented\n");
1713 return NotImplemented
;
1716 GpStatus WINGDIPAPI
GdipMultiplyPathGradientTransform(GpPathGradient
*grad
,
1717 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1721 TRACE("(%p,%p,%i)\n", grad
, matrix
, order
);
1724 FIXME("not implemented\n");
1726 return NotImplemented
;
1729 GpStatus WINGDIPAPI
GdipRotatePathGradientTransform(GpPathGradient
*grad
,
1730 REAL angle
, GpMatrixOrder order
)
1734 TRACE("(%p,%0.2f,%i)\n", grad
, angle
, order
);
1737 FIXME("not implemented\n");
1739 return NotImplemented
;
1742 GpStatus WINGDIPAPI
GdipScalePathGradientTransform(GpPathGradient
*grad
,
1743 REAL sx
, REAL sy
, GpMatrixOrder order
)
1747 TRACE("(%p,%0.2f,%0.2f,%i)\n", grad
, sx
, sy
, order
);
1750 FIXME("not implemented\n");
1752 return NotImplemented
;
1755 GpStatus WINGDIPAPI
GdipTranslatePathGradientTransform(GpPathGradient
*grad
,
1756 REAL dx
, REAL dy
, GpMatrixOrder order
)
1760 TRACE("(%p,%0.2f,%0.2f,%i)\n", grad
, dx
, dy
, order
);
1763 FIXME("not implemented\n");
1765 return NotImplemented
;
1768 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
1770 TRACE("(%p, %x)\n", sf
, argb
);
1773 return InvalidParameter
;
1776 sf
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1778 DeleteObject(sf
->brush
.gdibrush
);
1779 sf
->brush
.gdibrush
= CreateSolidBrush(sf
->brush
.lb
.lbColor
);
1784 /******************************************************************************
1785 * GdipSetTextureTransform [GDIPLUS.@]
1787 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
1788 GDIPCONST GpMatrix
*matrix
)
1790 TRACE("(%p, %p)\n", texture
, matrix
);
1792 if(!texture
|| !matrix
)
1793 return InvalidParameter
;
1795 memcpy(texture
->transform
, matrix
, sizeof(GpMatrix
));
1800 /******************************************************************************
1801 * GdipSetTextureWrapMode [GDIPLUS.@]
1803 * WrapMode not used, only stored
1805 GpStatus WINGDIPAPI
GdipSetTextureWrapMode(GpTexture
*brush
, GpWrapMode wrapmode
)
1807 TRACE("(%p, %d)\n", brush
, wrapmode
);
1810 return InvalidParameter
;
1812 brush
->imageattributes
->wrap
= wrapmode
;
1817 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
1820 TRACE("(%p, %x, %x)\n", brush
, color1
, color2
);
1823 return InvalidParameter
;
1825 brush
->startcolor
= color1
;
1826 brush
->endcolor
= color2
;
1831 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
1833 TRACE("(%p, %p)\n", brush
, colors
);
1835 if(!brush
|| !colors
)
1836 return InvalidParameter
;
1838 colors
[0] = brush
->startcolor
;
1839 colors
[1] = brush
->endcolor
;
1844 /******************************************************************************
1845 * GdipRotateTextureTransform [GDIPLUS.@]
1847 GpStatus WINGDIPAPI
GdipRotateTextureTransform(GpTexture
* brush
, REAL angle
,
1848 GpMatrixOrder order
)
1850 TRACE("(%p, %.2f, %d)\n", brush
, angle
, order
);
1853 return InvalidParameter
;
1855 return GdipRotateMatrix(brush
->transform
, angle
, order
);
1858 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
1865 TRACE("(%p,%.2f,%.2f)\n", brush
, focus
, scale
);
1867 if (!brush
) return InvalidParameter
;
1871 factors
[num_points
] = 0.0;
1872 positions
[num_points
] = 0.0;
1876 factors
[num_points
] = scale
;
1877 positions
[num_points
] = focus
;
1882 factors
[num_points
] = 0.0;
1883 positions
[num_points
] = 1.0;
1887 return GdipSetLineBlend(brush
, factors
, positions
, num_points
);
1890 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
1891 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
1895 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, positions
, count
);
1897 if (!brush
|| !blend
|| !positions
|| count
< 2 ||
1898 positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)
1900 return InvalidParameter
;
1903 new_color
= GdipAlloc(count
* sizeof(ARGB
));
1904 new_pos
= GdipAlloc(count
* sizeof(REAL
));
1905 if (!new_color
|| !new_pos
)
1907 GdipFree(new_color
);
1912 memcpy(new_color
, blend
, sizeof(ARGB
) * count
);
1913 memcpy(new_pos
, positions
, sizeof(REAL
) * count
);
1915 GdipFree(brush
->pblendcolor
);
1916 GdipFree(brush
->pblendpos
);
1918 brush
->pblendcolor
= new_color
;
1919 brush
->pblendpos
= new_pos
;
1920 brush
->pblendcount
= count
;
1925 GpStatus WINGDIPAPI
GdipGetLinePresetBlend(GpLineGradient
*brush
,
1926 ARGB
*blend
, REAL
* positions
, INT count
)
1928 if (!brush
|| !blend
|| !positions
|| count
< 2)
1929 return InvalidParameter
;
1931 if (brush
->pblendcount
== 0)
1932 return GenericError
;
1934 if (count
< brush
->pblendcount
)
1935 return InsufficientBuffer
;
1937 memcpy(blend
, brush
->pblendcolor
, sizeof(ARGB
) * brush
->pblendcount
);
1938 memcpy(positions
, brush
->pblendpos
, sizeof(REAL
) * brush
->pblendcount
);
1943 GpStatus WINGDIPAPI
GdipGetLinePresetBlendCount(GpLineGradient
*brush
,
1946 if (!brush
|| !count
)
1947 return InvalidParameter
;
1949 *count
= brush
->pblendcount
;
1954 GpStatus WINGDIPAPI
GdipResetLineTransform(GpLineGradient
*brush
)
1958 TRACE("(%p)\n", brush
);
1961 FIXME("not implemented\n");
1963 return NotImplemented
;
1966 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
1967 GDIPCONST GpMatrix
*matrix
)
1971 TRACE("(%p,%p)\n", brush
, matrix
);
1974 FIXME("not implemented\n");
1976 return NotImplemented
;
1979 GpStatus WINGDIPAPI
GdipGetLineTransform(GpLineGradient
*brush
, GpMatrix
*matrix
)
1983 TRACE("(%p,%p)\n", brush
, matrix
);
1986 FIXME("not implemented\n");
1988 return NotImplemented
;
1991 GpStatus WINGDIPAPI
GdipScaleLineTransform(GpLineGradient
*brush
, REAL sx
, REAL sy
,
1992 GpMatrixOrder order
)
1996 TRACE("(%p,%0.2f,%0.2f,%u)\n", brush
, sx
, sy
, order
);
1999 FIXME("not implemented\n");
2001 return NotImplemented
;
2004 GpStatus WINGDIPAPI
GdipMultiplyLineTransform(GpLineGradient
*brush
,
2005 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
2009 TRACE("(%p,%p,%u)\n", brush
, matrix
, order
);
2012 FIXME("not implemented\n");
2014 return NotImplemented
;
2017 GpStatus WINGDIPAPI
GdipTranslateLineTransform(GpLineGradient
* brush
,
2018 REAL dx
, REAL dy
, GpMatrixOrder order
)
2020 FIXME("stub: %p %f %f %d\n", brush
, dx
, dy
, order
);
2022 return NotImplemented
;
2025 /******************************************************************************
2026 * GdipTranslateTextureTransform [GDIPLUS.@]
2028 GpStatus WINGDIPAPI
GdipTranslateTextureTransform(GpTexture
* brush
, REAL dx
, REAL dy
,
2029 GpMatrixOrder order
)
2031 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, dx
, dy
, order
);
2034 return InvalidParameter
;
2036 return GdipTranslateMatrix(brush
->transform
, dx
, dy
, order
);
2039 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
2041 TRACE("(%p, %p)\n", brush
, rect
);
2044 return InvalidParameter
;
2046 *rect
= brush
->rect
;
2051 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
2056 TRACE("(%p, %p)\n", brush
, rect
);
2059 return InvalidParameter
;
2061 ret
= GdipGetLineRect(brush
, &rectF
);
2064 rect
->X
= roundr(rectF
.X
);
2065 rect
->Y
= roundr(rectF
.Y
);
2066 rect
->Width
= roundr(rectF
.Width
);
2067 rect
->Height
= roundr(rectF
.Height
);
2073 GpStatus WINGDIPAPI
GdipRotateLineTransform(GpLineGradient
* brush
,
2074 REAL angle
, GpMatrixOrder order
)
2078 TRACE("(%p,%0.2f,%u)\n", brush
, angle
, order
);
2081 return InvalidParameter
;
2084 FIXME("(%p, %.2f, %d) stub\n", brush
, angle
, order
);
2086 return NotImplemented
;