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
:
63 *clone
= GdipAlloc(sizeof(GpHatch
));
64 if (!*clone
) return OutOfMemory
;
66 memcpy(*clone
, brush
, sizeof(GpHatch
));
68 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
70 case BrushTypePathGradient
:{
71 GpPathGradient
*src
, *dest
;
74 *clone
= GdipAlloc(sizeof(GpPathGradient
));
75 if (!*clone
) return OutOfMemory
;
77 src
= (GpPathGradient
*) brush
,
78 dest
= (GpPathGradient
*) *clone
;
79 count
= src
->pathdata
.Count
;
81 memcpy(dest
, src
, sizeof(GpPathGradient
));
83 dest
->pathdata
.Count
= count
;
84 dest
->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
85 dest
->pathdata
.Types
= GdipAlloc(count
);
87 if(!dest
->pathdata
.Points
|| !dest
->pathdata
.Types
){
88 GdipFree(dest
->pathdata
.Points
);
89 GdipFree(dest
->pathdata
.Types
);
94 memcpy(dest
->pathdata
.Points
, src
->pathdata
.Points
, count
* sizeof(PointF
));
95 memcpy(dest
->pathdata
.Types
, src
->pathdata
.Types
, count
);
98 count
= src
->blendcount
;
99 dest
->blendcount
= count
;
100 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
101 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
103 if(!dest
->blendfac
|| !dest
->blendpos
){
104 GdipFree(dest
->pathdata
.Points
);
105 GdipFree(dest
->pathdata
.Types
);
106 GdipFree(dest
->blendfac
);
107 GdipFree(dest
->blendpos
);
112 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
113 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
117 case BrushTypeLinearGradient
:{
118 GpLineGradient
*dest
, *src
;
121 dest
= GdipAlloc(sizeof(GpLineGradient
));
122 if(!dest
) return OutOfMemory
;
124 src
= (GpLineGradient
*)brush
;
126 memcpy(dest
, src
, sizeof(GpLineGradient
));
128 dest
->brush
.gdibrush
= CreateSolidBrush(dest
->brush
.lb
.lbColor
);
130 count
= dest
->blendcount
;
131 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
132 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
133 pcount
= dest
->pblendcount
;
136 dest
->pblendcolor
= GdipAlloc(pcount
* sizeof(ARGB
));
137 dest
->pblendpos
= GdipAlloc(pcount
* sizeof(REAL
));
140 if (!dest
->blendfac
|| !dest
->blendpos
||
141 (pcount
&& (!dest
->pblendcolor
|| !dest
->pblendpos
)))
143 GdipFree(dest
->blendfac
);
144 GdipFree(dest
->blendpos
);
145 GdipFree(dest
->pblendcolor
);
146 GdipFree(dest
->pblendpos
);
147 DeleteObject(dest
->brush
.gdibrush
);
152 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
153 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
157 memcpy(dest
->pblendcolor
, src
->pblendcolor
, pcount
* sizeof(ARGB
));
158 memcpy(dest
->pblendpos
, src
->pblendpos
, pcount
* sizeof(REAL
));
161 *clone
= &dest
->brush
;
164 case BrushTypeTextureFill
:
165 *clone
= GdipAlloc(sizeof(GpTexture
));
166 if(!*clone
) return OutOfMemory
;
168 memcpy(*clone
, brush
, sizeof(GpTexture
));
170 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
173 ERR("not implemented for brush type %d\n", brush
->bt
);
174 return NotImplemented
;
177 TRACE("<-- %p\n", *clone
);
181 static const char HatchBrushes
[][8] = {
182 { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HatchStyleHorizontal */
183 { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleVertical */
184 { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HatchStyleForwardDiagonal */
185 { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleBackwardDiagonal */
186 { 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleCross */
187 { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleDiagonalCross */
188 { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80 }, /* HatchStyle05Percent */
189 { 0x00, 0x02, 0x00, 0x88, 0x00, 0x20, 0x00, 0x88 }, /* HatchStyle10Percent */
190 { 0x00, 0x22, 0x00, 0xcc, 0x00, 0x22, 0x00, 0xcc }, /* HatchStyle20Percent */
191 { 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc }, /* HatchStyle25Percent */
192 { 0x00, 0xcc, 0x04, 0xcc, 0x00, 0xcc, 0x40, 0xcc }, /* HatchStyle30Percent */
193 { 0x44, 0xcc, 0x22, 0xcc, 0x44, 0xcc, 0x22, 0xcc }, /* HatchStyle40Percent */
194 { 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc }, /* HatchStyle50Percent */
195 { 0x55, 0xcd, 0x55, 0xee, 0x55, 0xdc, 0x55, 0xee }, /* HatchStyle60Percent */
196 { 0x55, 0xdd, 0x55, 0xff, 0x55, 0xdd, 0x55, 0xff }, /* HatchStyle70Percent */
197 { 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff }, /* HatchStyle75Percent */
198 { 0x55, 0xff, 0x59, 0xff, 0x55, 0xff, 0x99, 0xff }, /* HatchStyle80Percent */
199 { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xfd, 0xff }, /* HatchStyle90Percent */
200 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, /* HatchStyleLightDownwardDiagonal */
201 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, /* HatchStyleLightUpwardDiagonal */
202 { 0x99, 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc }, /* HatchStyleDarkDownwardDiagonal */
203 { 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 }, /* HatchStyleDarkUpwardDiagonal */
204 { 0xc1, 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0 }, /* HatchStyleWideDownwardDiagonal */
205 { 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83, 0xc1 }, /* HatchStyleWideUpwardDiagonal */
206 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, /* HatchStyleLightVertical */
207 { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleLightHorizontal */
208 { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, /* HatchStyleNarrowVertical */
209 { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, /* HatchStyleNarrowHorizontal */
210 { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, /* HatchStyleDarkVertical */
211 { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
214 /******************************************************************************
215 * GdipCreateHatchBrush [GDIPLUS.@]
217 GpStatus WINGDIPAPI
GdipCreateHatchBrush(HatchStyle hatchstyle
, ARGB forecol
, ARGB backcol
, GpHatch
**brush
)
219 COLORREF fgcol
= ARGB2COLORREF(forecol
);
222 TRACE("(%d, %d, %d, %p)\n", hatchstyle
, forecol
, backcol
, brush
);
224 if(!brush
) return InvalidParameter
;
226 *brush
= GdipAlloc(sizeof(GpHatch
));
227 if (!*brush
) return OutOfMemory
;
229 if (hatchstyle
< sizeof(HatchBrushes
) / sizeof(HatchBrushes
[0]))
233 BITMAPINFOHEADER bmih
;
237 hdc
= CreateCompatibleDC(0);
241 bmih
.biSize
= sizeof(bmih
);
245 bmih
.biBitCount
= 32;
246 bmih
.biCompression
= BI_RGB
;
247 bmih
.biSizeImage
= 0;
249 hbmp
= CreateDIBSection(hdc
, (BITMAPINFO
*)&bmih
, DIB_RGB_COLORS
, (void**)&bits
, NULL
, 0);
255 if ((HatchBrushes
[hatchstyle
][y
] & (0x80 >> x
)) != 0)
256 bits
[y
*8+x
] = forecol
;
258 bits
[y
*8+x
] = backcol
;
270 (*brush
)->brush
.lb
.lbStyle
= BS_PATTERN
;
271 (*brush
)->brush
.lb
.lbColor
= 0;
272 (*brush
)->brush
.lb
.lbHatch
= (ULONG_PTR
)hbmp
;
273 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
280 FIXME("Unimplemented hatch style %d\n", hatchstyle
);
282 (*brush
)->brush
.lb
.lbStyle
= BS_SOLID
;
283 (*brush
)->brush
.lb
.lbColor
= fgcol
;
284 (*brush
)->brush
.lb
.lbHatch
= 0;
285 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
290 (*brush
)->brush
.bt
= BrushTypeHatchFill
;
291 (*brush
)->forecol
= forecol
;
292 (*brush
)->backcol
= backcol
;
293 (*brush
)->hatchstyle
= hatchstyle
;
294 TRACE("<-- %p\n", *brush
);
305 /******************************************************************************
306 * GdipCreateLineBrush [GDIPLUS.@]
308 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
309 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
310 GpWrapMode wrap
, GpLineGradient
**line
)
312 COLORREF col
= ARGB2COLORREF(startcolor
);
314 TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint
),
315 debugstr_pointf(endpoint
), startcolor
, endcolor
, wrap
, line
);
317 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
318 return InvalidParameter
;
320 *line
= GdipAlloc(sizeof(GpLineGradient
));
321 if(!*line
) return OutOfMemory
;
323 (*line
)->brush
.lb
.lbStyle
= BS_SOLID
;
324 (*line
)->brush
.lb
.lbColor
= col
;
325 (*line
)->brush
.lb
.lbHatch
= 0;
326 (*line
)->brush
.gdibrush
= CreateSolidBrush(col
);
327 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
329 (*line
)->startpoint
.X
= startpoint
->X
;
330 (*line
)->startpoint
.Y
= startpoint
->Y
;
331 (*line
)->endpoint
.X
= endpoint
->X
;
332 (*line
)->endpoint
.Y
= endpoint
->Y
;
333 (*line
)->startcolor
= startcolor
;
334 (*line
)->endcolor
= endcolor
;
335 (*line
)->wrap
= wrap
;
336 (*line
)->gamma
= FALSE
;
338 (*line
)->rect
.X
= (startpoint
->X
< endpoint
->X
? startpoint
->X
: endpoint
->X
);
339 (*line
)->rect
.Y
= (startpoint
->Y
< endpoint
->Y
? startpoint
->Y
: endpoint
->Y
);
340 (*line
)->rect
.Width
= fabs(startpoint
->X
- endpoint
->X
);
341 (*line
)->rect
.Height
= fabs(startpoint
->Y
- endpoint
->Y
);
343 if ((*line
)->rect
.Width
== 0)
345 (*line
)->rect
.X
-= (*line
)->rect
.Height
/ 2.0f
;
346 (*line
)->rect
.Width
= (*line
)->rect
.Height
;
348 else if ((*line
)->rect
.Height
== 0)
350 (*line
)->rect
.Y
-= (*line
)->rect
.Width
/ 2.0f
;
351 (*line
)->rect
.Height
= (*line
)->rect
.Width
;
354 (*line
)->blendcount
= 1;
355 (*line
)->blendfac
= GdipAlloc(sizeof(REAL
));
356 (*line
)->blendpos
= GdipAlloc(sizeof(REAL
));
358 if (!(*line
)->blendfac
|| !(*line
)->blendpos
)
360 GdipFree((*line
)->blendfac
);
361 GdipFree((*line
)->blendpos
);
362 DeleteObject((*line
)->brush
.gdibrush
);
368 (*line
)->blendfac
[0] = 1.0f
;
369 (*line
)->blendpos
[0] = 1.0f
;
371 (*line
)->pblendcolor
= NULL
;
372 (*line
)->pblendpos
= NULL
;
373 (*line
)->pblendcount
= 0;
375 TRACE("<-- %p\n", *line
);
380 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
381 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
382 GpWrapMode wrap
, GpLineGradient
**line
)
387 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
388 startcolor
, endcolor
, wrap
, line
);
390 if(!startpoint
|| !endpoint
)
391 return InvalidParameter
;
393 stF
.X
= (REAL
)startpoint
->X
;
394 stF
.Y
= (REAL
)startpoint
->Y
;
395 endF
.X
= (REAL
)endpoint
->X
;
396 endF
.X
= (REAL
)endpoint
->Y
;
398 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
401 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
402 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
403 GpLineGradient
**line
)
408 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
412 return InvalidParameter
;
416 case LinearGradientModeHorizontal
:
419 end
.X
= rect
->X
+ rect
->Width
;
422 case LinearGradientModeVertical
:
426 end
.Y
= rect
->Y
+ rect
->Height
;
428 case LinearGradientModeForwardDiagonal
:
431 end
.X
= rect
->X
+ rect
->Width
;
432 end
.Y
= rect
->Y
+ rect
->Height
;
434 case LinearGradientModeBackwardDiagonal
:
435 start
.X
= rect
->X
+ rect
->Width
;
438 end
.Y
= rect
->Y
+ rect
->Height
;
441 return InvalidParameter
;
444 stat
= GdipCreateLineBrush(&start
, &end
, startcolor
, endcolor
, wrap
, line
);
447 (*line
)->rect
= *rect
;
452 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
453 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
454 GpLineGradient
**line
)
458 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
461 rectF
.X
= (REAL
) rect
->X
;
462 rectF
.Y
= (REAL
) rect
->Y
;
463 rectF
.Width
= (REAL
) rect
->Width
;
464 rectF
.Height
= (REAL
) rect
->Height
;
466 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
469 /******************************************************************************
470 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
472 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF
* rect
,
473 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
474 GpLineGradient
**line
)
477 LinearGradientMode mode
;
478 REAL width
, height
, exofs
, eyofs
;
479 REAL sin_angle
, cos_angle
, sin_cos_angle
;
481 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
484 sin_angle
= sinf(deg2rad(angle
));
485 cos_angle
= cosf(deg2rad(angle
));
486 sin_cos_angle
= sin_angle
* cos_angle
;
490 width
= height
= 1.0;
495 height
= rect
->Height
;
498 if (sin_cos_angle
>= 0)
499 mode
= LinearGradientModeForwardDiagonal
;
501 mode
= LinearGradientModeBackwardDiagonal
;
503 stat
= GdipCreateLineBrushFromRect(rect
, startcolor
, endcolor
, mode
, wrap
, line
);
507 if (sin_cos_angle
>= 0)
509 exofs
= width
* sin_cos_angle
+ height
* cos_angle
* cos_angle
;
510 eyofs
= width
* sin_angle
* sin_angle
+ height
* sin_cos_angle
;
514 exofs
= width
* sin_angle
* sin_angle
+ height
* sin_cos_angle
;
515 eyofs
= -width
* sin_cos_angle
+ height
* sin_angle
* sin_angle
;
520 exofs
= exofs
* rect
->Width
;
521 eyofs
= eyofs
* rect
->Height
;
526 (*line
)->endpoint
.X
= rect
->X
+ exofs
;
527 (*line
)->endpoint
.Y
= rect
->Y
+ eyofs
;
531 (*line
)->endpoint
.X
= (*line
)->startpoint
.X
;
532 (*line
)->endpoint
.Y
= (*line
)->startpoint
.Y
;
533 (*line
)->startpoint
.X
= rect
->X
+ exofs
;
534 (*line
)->startpoint
.Y
= rect
->Y
+ eyofs
;
541 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect
* rect
,
542 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
543 GpLineGradient
**line
)
545 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
548 return GdipCreateLineBrushFromRectI(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
552 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
553 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
555 COLORREF col
= ARGB2COLORREF(0xffffffff);
557 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
560 return InvalidParameter
;
565 *grad
= GdipAlloc(sizeof(GpPathGradient
));
566 if (!*grad
) return OutOfMemory
;
568 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
569 if(!(*grad
)->blendfac
){
573 (*grad
)->blendfac
[0] = 1.0;
574 (*grad
)->blendpos
= NULL
;
575 (*grad
)->blendcount
= 1;
577 (*grad
)->pathdata
.Count
= count
;
578 (*grad
)->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
579 (*grad
)->pathdata
.Types
= GdipAlloc(count
);
581 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
582 GdipFree((*grad
)->pathdata
.Points
);
583 GdipFree((*grad
)->pathdata
.Types
);
588 memcpy((*grad
)->pathdata
.Points
, points
, count
* sizeof(PointF
));
589 memset((*grad
)->pathdata
.Types
, PathPointTypeLine
, count
);
591 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
592 (*grad
)->brush
.lb
.lbColor
= col
;
593 (*grad
)->brush
.lb
.lbHatch
= 0;
595 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
596 (*grad
)->brush
.bt
= BrushTypePathGradient
;
597 (*grad
)->centercolor
= 0xffffffff;
598 (*grad
)->wrap
= wrap
;
599 (*grad
)->gamma
= FALSE
;
600 (*grad
)->center
.X
= 0.0;
601 (*grad
)->center
.Y
= 0.0;
602 (*grad
)->focus
.X
= 0.0;
603 (*grad
)->focus
.Y
= 0.0;
605 TRACE("<-- %p\n", *grad
);
610 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
611 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
617 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
620 return InvalidParameter
;
625 pointsF
= GdipAlloc(sizeof(GpPointF
) * count
);
629 for(i
= 0; i
< count
; i
++){
630 pointsF
[i
].X
= (REAL
)points
[i
].X
;
631 pointsF
[i
].Y
= (REAL
)points
[i
].Y
;
634 ret
= GdipCreatePathGradient(pointsF
, count
, wrap
, grad
);
640 /******************************************************************************
641 * GdipCreatePathGradientFromPath [GDIPLUS.@]
643 * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
645 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
646 GpPathGradient
**grad
)
648 COLORREF col
= ARGB2COLORREF(0xffffffff);
650 TRACE("(%p, %p)\n", path
, grad
);
653 return InvalidParameter
;
655 *grad
= GdipAlloc(sizeof(GpPathGradient
));
656 if (!*grad
) return OutOfMemory
;
658 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
659 if(!(*grad
)->blendfac
){
663 (*grad
)->blendfac
[0] = 1.0;
664 (*grad
)->blendpos
= NULL
;
665 (*grad
)->blendcount
= 1;
667 (*grad
)->pathdata
.Count
= path
->pathdata
.Count
;
668 (*grad
)->pathdata
.Points
= GdipAlloc(path
->pathdata
.Count
* sizeof(PointF
));
669 (*grad
)->pathdata
.Types
= GdipAlloc(path
->pathdata
.Count
);
671 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
672 GdipFree((*grad
)->pathdata
.Points
);
673 GdipFree((*grad
)->pathdata
.Types
);
678 memcpy((*grad
)->pathdata
.Points
, path
->pathdata
.Points
,
679 path
->pathdata
.Count
* sizeof(PointF
));
680 memcpy((*grad
)->pathdata
.Types
, path
->pathdata
.Types
, path
->pathdata
.Count
);
682 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
683 (*grad
)->brush
.lb
.lbColor
= col
;
684 (*grad
)->brush
.lb
.lbHatch
= 0;
686 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
687 (*grad
)->brush
.bt
= BrushTypePathGradient
;
688 (*grad
)->centercolor
= 0xffffffff;
689 (*grad
)->wrap
= WrapModeClamp
;
690 (*grad
)->gamma
= FALSE
;
691 /* FIXME: this should be set to the "centroid" of the path by default */
692 (*grad
)->center
.X
= 0.0;
693 (*grad
)->center
.Y
= 0.0;
694 (*grad
)->focus
.X
= 0.0;
695 (*grad
)->focus
.Y
= 0.0;
697 TRACE("<-- %p\n", *grad
);
702 /******************************************************************************
703 * GdipCreateSolidFill [GDIPLUS.@]
705 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
707 COLORREF col
= ARGB2COLORREF(color
);
709 TRACE("(%x, %p)\n", color
, sf
);
711 if(!sf
) return InvalidParameter
;
713 *sf
= GdipAlloc(sizeof(GpSolidFill
));
714 if (!*sf
) return OutOfMemory
;
716 (*sf
)->brush
.lb
.lbStyle
= BS_SOLID
;
717 (*sf
)->brush
.lb
.lbColor
= col
;
718 (*sf
)->brush
.lb
.lbHatch
= 0;
720 (*sf
)->brush
.gdibrush
= CreateSolidBrush(col
);
721 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
722 (*sf
)->color
= color
;
723 (*sf
)->bmp
= ARGB2BMP(color
);
725 TRACE("<-- %p\n", *sf
);
730 /******************************************************************************
731 * GdipCreateTexture [GDIPLUS.@]
734 * image [I] image to use
735 * wrapmode [I] optional
736 * texture [O] pointer to the resulting texturebrush
740 * FAILURE: element of GpStatus
742 GpStatus WINGDIPAPI
GdipCreateTexture(GpImage
*image
, GpWrapMode wrapmode
,
746 GpImageAttributes attributes
;
749 TRACE("%p, %d %p\n", image
, wrapmode
, texture
);
751 if (!(image
&& texture
))
752 return InvalidParameter
;
754 stat
= GdipGetImageWidth(image
, &width
);
755 if (stat
!= Ok
) return stat
;
756 stat
= GdipGetImageHeight(image
, &height
);
757 if (stat
!= Ok
) return stat
;
758 attributes
.wrap
= wrapmode
;
760 return GdipCreateTextureIA(image
, &attributes
, 0, 0, width
, height
,
764 /******************************************************************************
765 * GdipCreateTexture2 [GDIPLUS.@]
767 GpStatus WINGDIPAPI
GdipCreateTexture2(GpImage
*image
, GpWrapMode wrapmode
,
768 REAL x
, REAL y
, REAL width
, REAL height
, GpTexture
**texture
)
770 GpImageAttributes attributes
;
772 TRACE("%p %d %f %f %f %f %p\n", image
, wrapmode
,
773 x
, y
, width
, height
, texture
);
775 attributes
.wrap
= wrapmode
;
776 return GdipCreateTextureIA(image
, &attributes
, x
, y
, width
, height
,
780 /******************************************************************************
781 * GdipCreateTextureIA [GDIPLUS.@]
783 * FIXME: imageattr ignored
785 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
786 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
787 REAL height
, GpTexture
**texture
)
790 HBITMAP hbm
, old
= NULL
;
792 BITMAPINFOHEADER
*bmih
;
793 INT n_x
, n_y
, n_width
, n_height
, abs_height
, stride
, image_stride
, i
, bytespp
;
795 BYTE
*dibits
, *buff
, *textbits
;
798 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image
, imageattr
, x
, y
, width
, height
,
801 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
802 return InvalidParameter
;
804 if(image
->type
!= ImageTypeBitmap
){
805 FIXME("not implemented for image type %d\n", image
->type
);
806 return NotImplemented
;
811 n_width
= roundr(width
);
812 n_height
= roundr(height
);
814 if(n_x
+ n_width
> ((GpBitmap
*)image
)->width
||
815 n_y
+ n_height
> ((GpBitmap
*)image
)->height
)
816 return InvalidParameter
;
818 hbm
= ((GpBitmap
*)image
)->hbitmap
;
819 if(!hbm
) return GenericError
;
820 hdc
= ((GpBitmap
*)image
)->hdc
;
821 bm_is_selected
= (hdc
!= 0);
823 pbmi
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
826 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
827 pbmi
->bmiHeader
.biBitCount
= 0;
830 hdc
= CreateCompatibleDC(0);
831 old
= SelectObject(hdc
, hbm
);
835 GetDIBits(hdc
, hbm
, 0, 0, NULL
, pbmi
, DIB_RGB_COLORS
);
837 bytespp
= pbmi
->bmiHeader
.biBitCount
/ 8;
838 abs_height
= abs(pbmi
->bmiHeader
.biHeight
);
840 if(n_x
> pbmi
->bmiHeader
.biWidth
|| n_x
+ n_width
> pbmi
->bmiHeader
.biWidth
||
841 n_y
> abs_height
|| n_y
+ n_height
> abs_height
){
843 return InvalidParameter
;
846 dibits
= GdipAlloc(pbmi
->bmiHeader
.biSizeImage
);
848 if(dibits
) /* this is not a good place to error out */
849 GetDIBits(hdc
, hbm
, 0, abs_height
, dibits
, pbmi
, DIB_RGB_COLORS
);
852 SelectObject(hdc
, old
);
861 image_stride
= (pbmi
->bmiHeader
.biWidth
* bytespp
+ 3) & ~3;
862 stride
= (n_width
* bytespp
+ 3) & ~3;
863 buff
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + stride
* n_height
);
870 bmih
= (BITMAPINFOHEADER
*)buff
;
871 textbits
= (BYTE
*) (bmih
+ 1);
872 bmih
->biSize
= sizeof(BITMAPINFOHEADER
);
873 bmih
->biWidth
= n_width
;
874 bmih
->biHeight
= n_height
;
875 bmih
->biCompression
= BI_RGB
;
876 bmih
->biSizeImage
= stride
* n_height
;
877 bmih
->biBitCount
= pbmi
->bmiHeader
.biBitCount
;
881 /* image is flipped */
882 if(pbmi
->bmiHeader
.biHeight
> 0){
883 dibits
+= image_stride
* (pbmi
->bmiHeader
.biHeight
- 1);
885 textbits
+= stride
* (n_height
- 1);
891 for(i
= 0; i
< n_height
; i
++)
892 memcpy(&textbits
[i
* stride
],
893 &dibits
[n_x
* bytespp
+ (n_y
+ i
) * image_stride
],
896 *texture
= GdipAlloc(sizeof(GpTexture
));
903 if((status
= GdipCreateMatrix(&(*texture
)->transform
)) != Ok
){
910 (*texture
)->brush
.lb
.lbStyle
= BS_DIBPATTERNPT
;
911 (*texture
)->brush
.lb
.lbColor
= DIB_RGB_COLORS
;
912 (*texture
)->brush
.lb
.lbHatch
= (ULONG_PTR
)buff
;
914 (*texture
)->brush
.gdibrush
= CreateBrushIndirect(&(*texture
)->brush
.lb
);
915 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
916 (*texture
)->wrap
= imageattr
->wrap
;
921 TRACE("<-- %p\n", *texture
);
926 /******************************************************************************
927 * GdipCreateTextureIAI [GDIPLUS.@]
929 GpStatus WINGDIPAPI
GdipCreateTextureIAI(GpImage
*image
, GDIPCONST GpImageAttributes
*imageattr
,
930 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
932 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image
, imageattr
, x
, y
, width
, height
,
935 return GdipCreateTextureIA(image
,imageattr
,(REAL
)x
,(REAL
)y
,(REAL
)width
,(REAL
)height
,texture
);
938 GpStatus WINGDIPAPI
GdipCreateTexture2I(GpImage
*image
, GpWrapMode wrapmode
,
939 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
941 GpImageAttributes imageattr
;
943 TRACE("%p %d %d %d %d %d %p\n", image
, wrapmode
, x
, y
, width
, height
,
946 imageattr
.wrap
= wrapmode
;
948 return GdipCreateTextureIA(image
, &imageattr
, x
, y
, width
, height
, texture
);
951 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
953 TRACE("(%p, %p)\n", brush
, type
);
955 if(!brush
|| !type
) return InvalidParameter
;
962 GpStatus WINGDIPAPI
GdipGetHatchBackgroundColor(GpHatch
*brush
, ARGB
*backcol
)
964 TRACE("(%p, %p)\n", brush
, backcol
);
966 if(!brush
|| !backcol
) return InvalidParameter
;
968 *backcol
= brush
->backcol
;
973 GpStatus WINGDIPAPI
GdipGetHatchForegroundColor(GpHatch
*brush
, ARGB
*forecol
)
975 TRACE("(%p, %p)\n", brush
, forecol
);
977 if(!brush
|| !forecol
) return InvalidParameter
;
979 *forecol
= brush
->forecol
;
984 GpStatus WINGDIPAPI
GdipGetHatchStyle(GpHatch
*brush
, HatchStyle
*hatchstyle
)
986 TRACE("(%p, %p)\n", brush
, hatchstyle
);
988 if(!brush
|| !hatchstyle
) return InvalidParameter
;
990 *hatchstyle
= brush
->hatchstyle
;
995 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
997 TRACE("(%p)\n", brush
);
999 if(!brush
) return InvalidParameter
;
1003 case BrushTypePathGradient
:
1004 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Points
);
1005 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Types
);
1006 GdipFree(((GpPathGradient
*) brush
)->blendfac
);
1007 GdipFree(((GpPathGradient
*) brush
)->blendpos
);
1009 case BrushTypeSolidColor
:
1010 if (((GpSolidFill
*)brush
)->bmp
)
1011 DeleteObject(((GpSolidFill
*)brush
)->bmp
);
1013 case BrushTypeLinearGradient
:
1014 GdipFree(((GpLineGradient
*)brush
)->blendfac
);
1015 GdipFree(((GpLineGradient
*)brush
)->blendpos
);
1016 GdipFree(((GpLineGradient
*)brush
)->pblendcolor
);
1017 GdipFree(((GpLineGradient
*)brush
)->pblendpos
);
1019 case BrushTypeTextureFill
:
1020 GdipDeleteMatrix(((GpTexture
*)brush
)->transform
);
1026 DeleteObject(brush
->gdibrush
);
1032 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
1035 TRACE("(%p, %p)\n", line
, usinggamma
);
1037 if(!line
|| !usinggamma
)
1038 return InvalidParameter
;
1040 *usinggamma
= line
->gamma
;
1045 GpStatus WINGDIPAPI
GdipGetLineWrapMode(GpLineGradient
*brush
, GpWrapMode
*wrapmode
)
1047 TRACE("(%p, %p)\n", brush
, wrapmode
);
1049 if(!brush
|| !wrapmode
)
1050 return InvalidParameter
;
1052 *wrapmode
= brush
->wrap
;
1057 GpStatus WINGDIPAPI
GdipGetPathGradientBlend(GpPathGradient
*brush
, REAL
*blend
,
1058 REAL
*positions
, INT count
)
1060 TRACE("(%p, %p, %p, %d)\n", brush
, blend
, positions
, count
);
1062 if(!brush
|| !blend
|| !positions
|| count
<= 0)
1063 return InvalidParameter
;
1065 if(count
< brush
->blendcount
)
1066 return InsufficientBuffer
;
1068 memcpy(blend
, brush
->blendfac
, count
*sizeof(REAL
));
1069 if(brush
->blendcount
> 1){
1070 memcpy(positions
, brush
->blendpos
, count
*sizeof(REAL
));
1076 GpStatus WINGDIPAPI
GdipGetPathGradientBlendCount(GpPathGradient
*brush
, INT
*count
)
1078 TRACE("(%p, %p)\n", brush
, count
);
1080 if(!brush
|| !count
)
1081 return InvalidParameter
;
1083 *count
= brush
->blendcount
;
1088 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
1091 TRACE("(%p, %p)\n", grad
, point
);
1094 return InvalidParameter
;
1096 point
->X
= grad
->center
.X
;
1097 point
->Y
= grad
->center
.Y
;
1102 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
1108 TRACE("(%p, %p)\n", grad
, point
);
1111 return InvalidParameter
;
1113 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
1116 point
->X
= roundr(ptf
.X
);
1117 point
->Y
= roundr(ptf
.Y
);
1123 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
1126 TRACE("(%p, %p, %p)\n", grad
, x
, y
);
1128 if(!grad
|| !x
|| !y
)
1129 return InvalidParameter
;
1137 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
1140 TRACE("(%p, %p)\n", grad
, gamma
);
1143 return InvalidParameter
;
1145 *gamma
= grad
->gamma
;
1150 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
1153 TRACE("(%p, %p)\n", grad
, count
);
1156 return InvalidParameter
;
1158 *count
= grad
->pathdata
.Count
;
1163 GpStatus WINGDIPAPI
GdipGetPathGradientRect(GpPathGradient
*brush
, GpRectF
*rect
)
1169 TRACE("(%p, %p)\n", brush
, rect
);
1172 return InvalidParameter
;
1174 stat
= GdipCreatePath2(brush
->pathdata
.Points
, brush
->pathdata
.Types
,
1175 brush
->pathdata
.Count
, FillModeAlternate
, &path
);
1176 if(stat
!= Ok
) return stat
;
1178 stat
= GdipGetPathWorldBounds(path
, &r
, NULL
, NULL
);
1180 GdipDeletePath(path
);
1184 memcpy(rect
, &r
, sizeof(GpRectF
));
1186 GdipDeletePath(path
);
1191 GpStatus WINGDIPAPI
GdipGetPathGradientRectI(GpPathGradient
*brush
, GpRect
*rect
)
1196 TRACE("(%p, %p)\n", brush
, rect
);
1199 return InvalidParameter
;
1201 stat
= GdipGetPathGradientRect(brush
, &rectf
);
1202 if(stat
!= Ok
) return stat
;
1204 rect
->X
= roundr(rectf
.X
);
1205 rect
->Y
= roundr(rectf
.Y
);
1206 rect
->Width
= roundr(rectf
.Width
);
1207 rect
->Height
= roundr(rectf
.Height
);
1212 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1213 *grad
, ARGB
*argb
, INT
*count
)
1217 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1219 if(!grad
|| !argb
|| !count
|| (*count
< grad
->pathdata
.Count
))
1220 return InvalidParameter
;
1223 FIXME("not implemented\n");
1225 return NotImplemented
;
1228 GpStatus WINGDIPAPI
GdipGetPathGradientWrapMode(GpPathGradient
*brush
,
1229 GpWrapMode
*wrapmode
)
1231 TRACE("(%p, %p)\n", brush
, wrapmode
);
1233 if(!brush
|| !wrapmode
)
1234 return InvalidParameter
;
1236 *wrapmode
= brush
->wrap
;
1241 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
1243 TRACE("(%p, %p)\n", sf
, argb
);
1246 return InvalidParameter
;
1253 /******************************************************************************
1254 * GdipGetTextureTransform [GDIPLUS.@]
1256 GpStatus WINGDIPAPI
GdipGetTextureTransform(GpTexture
*brush
, GpMatrix
*matrix
)
1258 TRACE("(%p, %p)\n", brush
, matrix
);
1260 if(!brush
|| !matrix
)
1261 return InvalidParameter
;
1263 memcpy(matrix
, brush
->transform
, sizeof(GpMatrix
));
1268 /******************************************************************************
1269 * GdipGetTextureWrapMode [GDIPLUS.@]
1271 GpStatus WINGDIPAPI
GdipGetTextureWrapMode(GpTexture
*brush
, GpWrapMode
*wrapmode
)
1273 TRACE("(%p, %p)\n", brush
, wrapmode
);
1275 if(!brush
|| !wrapmode
)
1276 return InvalidParameter
;
1278 *wrapmode
= brush
->wrap
;
1283 /******************************************************************************
1284 * GdipMultiplyTextureTransform [GDIPLUS.@]
1286 GpStatus WINGDIPAPI
GdipMultiplyTextureTransform(GpTexture
* brush
,
1287 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1289 TRACE("(%p, %p, %d)\n", brush
, matrix
, order
);
1291 if(!brush
|| !matrix
)
1292 return InvalidParameter
;
1294 return GdipMultiplyMatrix(brush
->transform
, matrix
, order
);
1297 /******************************************************************************
1298 * GdipResetTextureTransform [GDIPLUS.@]
1300 GpStatus WINGDIPAPI
GdipResetTextureTransform(GpTexture
* brush
)
1302 TRACE("(%p)\n", brush
);
1305 return InvalidParameter
;
1307 return GdipSetMatrixElements(brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1310 /******************************************************************************
1311 * GdipScaleTextureTransform [GDIPLUS.@]
1313 GpStatus WINGDIPAPI
GdipScaleTextureTransform(GpTexture
* brush
,
1314 REAL sx
, REAL sy
, GpMatrixOrder order
)
1316 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, sx
, sy
, order
);
1319 return InvalidParameter
;
1321 return GdipScaleMatrix(brush
->transform
, sx
, sy
, order
);
1324 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
1325 GDIPCONST REAL
*factors
, GDIPCONST REAL
* positions
, INT count
)
1327 REAL
*new_blendfac
, *new_blendpos
;
1329 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1331 if(!brush
|| !factors
|| !positions
|| count
<= 0 ||
1332 (count
>= 2 && (positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)))
1333 return InvalidParameter
;
1335 new_blendfac
= GdipAlloc(count
* sizeof(REAL
));
1336 new_blendpos
= GdipAlloc(count
* sizeof(REAL
));
1338 if (!new_blendfac
|| !new_blendpos
)
1340 GdipFree(new_blendfac
);
1341 GdipFree(new_blendpos
);
1345 memcpy(new_blendfac
, factors
, count
* sizeof(REAL
));
1346 memcpy(new_blendpos
, positions
, count
* sizeof(REAL
));
1348 GdipFree(brush
->blendfac
);
1349 GdipFree(brush
->blendpos
);
1351 brush
->blendcount
= count
;
1352 brush
->blendfac
= new_blendfac
;
1353 brush
->blendpos
= new_blendpos
;
1358 GpStatus WINGDIPAPI
GdipGetLineBlend(GpLineGradient
*brush
, REAL
*factors
,
1359 REAL
*positions
, INT count
)
1361 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1363 if (!brush
|| !factors
|| !positions
|| count
<= 0)
1364 return InvalidParameter
;
1366 if (count
< brush
->blendcount
)
1367 return InsufficientBuffer
;
1369 memcpy(factors
, brush
->blendfac
, brush
->blendcount
* sizeof(REAL
));
1370 memcpy(positions
, brush
->blendpos
, brush
->blendcount
* sizeof(REAL
));
1375 GpStatus WINGDIPAPI
GdipGetLineBlendCount(GpLineGradient
*brush
, INT
*count
)
1377 TRACE("(%p, %p)\n", brush
, count
);
1379 if (!brush
|| !count
)
1380 return InvalidParameter
;
1382 *count
= brush
->blendcount
;
1387 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
1390 TRACE("(%p, %d)\n", line
, usegamma
);
1393 return InvalidParameter
;
1395 line
->gamma
= usegamma
;
1400 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
1407 const int precision
= 16;
1408 REAL erf_range
; /* we use values erf(-erf_range) through erf(+erf_range) */
1412 TRACE("(%p, %0.2f, %0.2f)\n", line
, focus
, scale
);
1414 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1415 return InvalidParameter
;
1417 /* we want 2 standard deviations */
1418 erf_range
= 2.0 / sqrt(2);
1420 /* calculate the constants we need to normalize the error function to be
1421 between 0.0 and scale over the range we need */
1422 min_erf
= erf(-erf_range
);
1423 scale_erf
= scale
/ (-2.0 * min_erf
);
1429 for (i
=1; i
<precision
; i
++)
1431 positions
[i
] = focus
* i
/ precision
;
1432 factors
[i
] = scale_erf
* (erf(2 * erf_range
* i
/ precision
- erf_range
) - min_erf
);
1434 num_points
+= precision
;
1437 positions
[num_points
] = focus
;
1438 factors
[num_points
] = scale
;
1443 for (i
=1; i
<precision
; i
++)
1445 positions
[i
+num_points
-1] = (focus
+ ((1.0-focus
) * i
/ precision
));
1446 factors
[i
+num_points
-1] = scale_erf
* (erf(erf_range
- 2 * erf_range
* i
/ precision
) - min_erf
);
1448 num_points
+= precision
;
1449 positions
[num_points
-1] = 1.0;
1450 factors
[num_points
-1] = 0.0;
1453 return GdipSetLineBlend(line
, factors
, positions
, num_points
);
1456 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
1459 TRACE("(%p, %d)\n", line
, wrap
);
1461 if(!line
|| wrap
== WrapModeClamp
)
1462 return InvalidParameter
;
1469 GpStatus WINGDIPAPI
GdipSetPathGradientBlend(GpPathGradient
*brush
, GDIPCONST REAL
*blend
,
1470 GDIPCONST REAL
*pos
, INT count
)
1474 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, pos
, count
);
1477 FIXME("not implemented\n");
1479 return NotImplemented
;
1482 GpStatus WINGDIPAPI
GdipSetPathGradientPresetBlend(GpPathGradient
*brush
,
1483 GDIPCONST ARGB
*blend
, GDIPCONST REAL
*pos
, INT count
)
1485 FIXME("(%p,%p,%p,%i): stub\n", brush
, blend
, pos
, count
);
1486 return NotImplemented
;
1489 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
1492 TRACE("(%p, %x)\n", grad
, argb
);
1495 return InvalidParameter
;
1497 grad
->centercolor
= argb
;
1498 grad
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1500 DeleteObject(grad
->brush
.gdibrush
);
1501 grad
->brush
.gdibrush
= CreateSolidBrush(grad
->brush
.lb
.lbColor
);
1506 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
1509 TRACE("(%p, %s)\n", grad
, debugstr_pointf(point
));
1512 return InvalidParameter
;
1514 grad
->center
.X
= point
->X
;
1515 grad
->center
.Y
= point
->Y
;
1520 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
1525 TRACE("(%p, %p)\n", grad
, point
);
1528 return InvalidParameter
;
1530 ptf
.X
= (REAL
)point
->X
;
1531 ptf
.Y
= (REAL
)point
->Y
;
1533 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
1536 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
1539 TRACE("(%p, %.2f, %.2f)\n", grad
, x
, y
);
1542 return InvalidParameter
;
1550 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
1553 TRACE("(%p, %d)\n", grad
, gamma
);
1556 return InvalidParameter
;
1558 grad
->gamma
= gamma
;
1563 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
1564 REAL focus
, REAL scale
)
1568 TRACE("(%p,%0.2f,%0.2f)\n", grad
, focus
, scale
);
1570 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1571 return InvalidParameter
;
1574 FIXME("not implemented\n");
1576 return NotImplemented
;
1579 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1580 *grad
, ARGB
*argb
, INT
*count
)
1584 TRACE("(%p,%p,%p)\n", grad
, argb
, count
);
1586 if(!grad
|| !argb
|| !count
|| (*count
<= 0) ||
1587 (*count
> grad
->pathdata
.Count
))
1588 return InvalidParameter
;
1591 FIXME("not implemented\n");
1593 return NotImplemented
;
1596 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
1599 TRACE("(%p, %d)\n", grad
, wrap
);
1602 return InvalidParameter
;
1609 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
1611 TRACE("(%p, %x)\n", sf
, argb
);
1614 return InvalidParameter
;
1617 sf
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1619 DeleteObject(sf
->brush
.gdibrush
);
1620 sf
->brush
.gdibrush
= CreateSolidBrush(sf
->brush
.lb
.lbColor
);
1625 /******************************************************************************
1626 * GdipSetTextureTransform [GDIPLUS.@]
1628 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
1629 GDIPCONST GpMatrix
*matrix
)
1631 TRACE("(%p, %p)\n", texture
, matrix
);
1633 if(!texture
|| !matrix
)
1634 return InvalidParameter
;
1636 memcpy(texture
->transform
, matrix
, sizeof(GpMatrix
));
1641 /******************************************************************************
1642 * GdipSetTextureWrapMode [GDIPLUS.@]
1644 * WrapMode not used, only stored
1646 GpStatus WINGDIPAPI
GdipSetTextureWrapMode(GpTexture
*brush
, GpWrapMode wrapmode
)
1648 TRACE("(%p, %d)\n", brush
, wrapmode
);
1651 return InvalidParameter
;
1653 brush
->wrap
= wrapmode
;
1658 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
1661 TRACE("(%p, %x, %x)\n", brush
, color1
, color2
);
1664 return InvalidParameter
;
1666 brush
->startcolor
= color1
;
1667 brush
->endcolor
= color2
;
1672 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
1674 TRACE("(%p, %p)\n", brush
, colors
);
1676 if(!brush
|| !colors
)
1677 return InvalidParameter
;
1679 colors
[0] = brush
->startcolor
;
1680 colors
[1] = brush
->endcolor
;
1685 /******************************************************************************
1686 * GdipRotateTextureTransform [GDIPLUS.@]
1688 GpStatus WINGDIPAPI
GdipRotateTextureTransform(GpTexture
* brush
, REAL angle
,
1689 GpMatrixOrder order
)
1691 TRACE("(%p, %.2f, %d)\n", brush
, angle
, order
);
1694 return InvalidParameter
;
1696 return GdipRotateMatrix(brush
->transform
, angle
, order
);
1699 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
1706 TRACE("(%p,%.2f,%.2f)\n", brush
, focus
, scale
);
1708 if (!brush
) return InvalidParameter
;
1712 factors
[num_points
] = 0.0;
1713 positions
[num_points
] = 0.0;
1717 factors
[num_points
] = scale
;
1718 positions
[num_points
] = focus
;
1723 factors
[num_points
] = 0.0;
1724 positions
[num_points
] = 1.0;
1728 return GdipSetLineBlend(brush
, factors
, positions
, num_points
);
1731 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
1732 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
1736 TRACE("(%p,%p,%p,%i)\n", brush
, blend
, positions
, count
);
1738 if (!brush
|| !blend
|| !positions
|| count
< 2 ||
1739 positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)
1741 return InvalidParameter
;
1744 new_color
= GdipAlloc(count
* sizeof(ARGB
));
1745 new_pos
= GdipAlloc(count
* sizeof(REAL
));
1746 if (!new_color
|| !new_pos
)
1748 GdipFree(new_color
);
1753 memcpy(new_color
, blend
, sizeof(ARGB
) * count
);
1754 memcpy(new_pos
, positions
, sizeof(REAL
) * count
);
1756 GdipFree(brush
->pblendcolor
);
1757 GdipFree(brush
->pblendpos
);
1759 brush
->pblendcolor
= new_color
;
1760 brush
->pblendpos
= new_pos
;
1761 brush
->pblendcount
= count
;
1766 GpStatus WINGDIPAPI
GdipGetLinePresetBlend(GpLineGradient
*brush
,
1767 ARGB
*blend
, REAL
* positions
, INT count
)
1769 if (!brush
|| !blend
|| !positions
|| count
< 2)
1770 return InvalidParameter
;
1772 if (brush
->pblendcount
== 0)
1773 return GenericError
;
1775 if (count
< brush
->pblendcount
)
1776 return InsufficientBuffer
;
1778 memcpy(blend
, brush
->pblendcolor
, sizeof(ARGB
) * brush
->pblendcount
);
1779 memcpy(positions
, brush
->pblendpos
, sizeof(REAL
) * brush
->pblendcount
);
1784 GpStatus WINGDIPAPI
GdipGetLinePresetBlendCount(GpLineGradient
*brush
,
1787 if (!brush
|| !count
)
1788 return InvalidParameter
;
1790 *count
= brush
->pblendcount
;
1795 GpStatus WINGDIPAPI
GdipResetLineTransform(GpLineGradient
*brush
)
1799 TRACE("(%p)\n", brush
);
1802 FIXME("not implemented\n");
1804 return NotImplemented
;
1807 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
1808 GDIPCONST GpMatrix
*matrix
)
1812 TRACE("(%p,%p)\n", brush
, matrix
);
1815 FIXME("not implemented\n");
1817 return NotImplemented
;
1820 GpStatus WINGDIPAPI
GdipScaleLineTransform(GpLineGradient
*brush
, REAL sx
, REAL sy
,
1821 GpMatrixOrder order
)
1825 TRACE("(%p,%0.2f,%0.2f,%u)\n", brush
, sx
, sy
, order
);
1828 FIXME("not implemented\n");
1830 return NotImplemented
;
1833 GpStatus WINGDIPAPI
GdipTranslateLineTransform(GpLineGradient
* brush
,
1834 REAL dx
, REAL dy
, GpMatrixOrder order
)
1836 FIXME("stub: %p %f %f %d\n", brush
, dx
, dy
, order
);
1838 return NotImplemented
;
1841 /******************************************************************************
1842 * GdipTranslateTextureTransform [GDIPLUS.@]
1844 GpStatus WINGDIPAPI
GdipTranslateTextureTransform(GpTexture
* brush
, REAL dx
, REAL dy
,
1845 GpMatrixOrder order
)
1847 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, dx
, dy
, order
);
1850 return InvalidParameter
;
1852 return GdipTranslateMatrix(brush
->transform
, dx
, dy
, order
);
1855 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
1857 TRACE("(%p, %p)\n", brush
, rect
);
1860 return InvalidParameter
;
1862 *rect
= brush
->rect
;
1867 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
1872 TRACE("(%p, %p)\n", brush
, rect
);
1875 return InvalidParameter
;
1877 ret
= GdipGetLineRect(brush
, &rectF
);
1880 rect
->X
= roundr(rectF
.X
);
1881 rect
->Y
= roundr(rectF
.Y
);
1882 rect
->Width
= roundr(rectF
.Width
);
1883 rect
->Height
= roundr(rectF
.Height
);
1889 GpStatus WINGDIPAPI
GdipRotateLineTransform(GpLineGradient
* brush
,
1890 REAL angle
, GpMatrixOrder order
)
1894 TRACE("(%p,%0.2f,%u)\n", brush
, angle
, order
);
1897 return InvalidParameter
;
1900 FIXME("(%p, %.2f, %d) stub\n", brush
, angle
, order
);
1902 return NotImplemented
;