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
:
49 *clone
= GdipAlloc(sizeof(GpSolidFill
));
50 if (!*clone
) return OutOfMemory
;
52 memcpy(*clone
, brush
, sizeof(GpSolidFill
));
54 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
56 case BrushTypeHatchFill
:
57 *clone
= GdipAlloc(sizeof(GpHatch
));
58 if (!*clone
) return OutOfMemory
;
60 memcpy(*clone
, brush
, sizeof(GpHatch
));
62 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
64 case BrushTypePathGradient
:{
65 GpPathGradient
*src
, *dest
;
68 *clone
= GdipAlloc(sizeof(GpPathGradient
));
69 if (!*clone
) return OutOfMemory
;
71 src
= (GpPathGradient
*) brush
,
72 dest
= (GpPathGradient
*) *clone
;
73 count
= src
->pathdata
.Count
;
75 memcpy(dest
, src
, sizeof(GpPathGradient
));
77 dest
->pathdata
.Count
= count
;
78 dest
->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
79 dest
->pathdata
.Types
= GdipAlloc(count
);
81 if(!dest
->pathdata
.Points
|| !dest
->pathdata
.Types
){
82 GdipFree(dest
->pathdata
.Points
);
83 GdipFree(dest
->pathdata
.Types
);
88 memcpy(dest
->pathdata
.Points
, src
->pathdata
.Points
, count
* sizeof(PointF
));
89 memcpy(dest
->pathdata
.Types
, src
->pathdata
.Types
, count
);
92 count
= src
->blendcount
;
93 dest
->blendcount
= count
;
94 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
95 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
97 if(!dest
->blendfac
|| !dest
->blendpos
){
98 GdipFree(dest
->pathdata
.Points
);
99 GdipFree(dest
->pathdata
.Types
);
100 GdipFree(dest
->blendfac
);
101 GdipFree(dest
->blendpos
);
106 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
107 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
111 case BrushTypeLinearGradient
:
112 *clone
= GdipAlloc(sizeof(GpLineGradient
));
113 if(!*clone
) return OutOfMemory
;
115 memcpy(*clone
, brush
, sizeof(GpLineGradient
));
117 (*clone
)->gdibrush
= CreateSolidBrush((*clone
)->lb
.lbColor
);
119 case BrushTypeTextureFill
:
120 *clone
= GdipAlloc(sizeof(GpTexture
));
121 if(!*clone
) return OutOfMemory
;
123 memcpy(*clone
, brush
, sizeof(GpTexture
));
125 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
128 ERR("not implemented for brush type %d\n", brush
->bt
);
129 return NotImplemented
;
135 static LONG
HatchStyleToHatch(HatchStyle hatchstyle
)
139 case HatchStyleHorizontal
: return HS_HORIZONTAL
;
140 case HatchStyleVertical
: return HS_VERTICAL
;
141 case HatchStyleForwardDiagonal
: return HS_FDIAGONAL
;
142 case HatchStyleBackwardDiagonal
: return HS_BDIAGONAL
;
143 case HatchStyleCross
: return HS_CROSS
;
144 case HatchStyleDiagonalCross
: return HS_DIAGCROSS
;
149 /******************************************************************************
150 * GdipCreateHatchBrush [GDIPLUS.@]
152 GpStatus WINGDIPAPI
GdipCreateHatchBrush(HatchStyle hatchstyle
, ARGB forecol
, ARGB backcol
, GpHatch
**brush
)
154 COLORREF fgcol
= ARGB2COLORREF(forecol
);
156 TRACE("(%d, %d, %d, %p)\n", hatchstyle
, forecol
, backcol
, brush
);
158 if(!brush
) return InvalidParameter
;
160 *brush
= GdipAlloc(sizeof(GpHatch
));
161 if (!*brush
) return OutOfMemory
;
165 case HatchStyleHorizontal
:
166 case HatchStyleVertical
:
167 case HatchStyleForwardDiagonal
:
168 case HatchStyleBackwardDiagonal
:
169 case HatchStyleCross
:
170 case HatchStyleDiagonalCross
:
171 /* Brushes that map to BS_HATCHED */
172 (*brush
)->brush
.lb
.lbStyle
= BS_HATCHED
;
173 (*brush
)->brush
.lb
.lbColor
= fgcol
;
174 (*brush
)->brush
.lb
.lbHatch
= HatchStyleToHatch(hatchstyle
);
178 FIXME("Unimplemented hatch style %d\n", hatchstyle
);
180 (*brush
)->brush
.lb
.lbStyle
= BS_SOLID
;
181 (*brush
)->brush
.lb
.lbColor
= fgcol
;
182 (*brush
)->brush
.lb
.lbHatch
= 0;
187 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
188 (*brush
)->brush
.bt
= BrushTypeHatchFill
;
189 (*brush
)->forecol
= forecol
;
190 (*brush
)->backcol
= backcol
;
191 (*brush
)->hatchstyle
= hatchstyle
;
196 /******************************************************************************
197 * GdipCreateLineBrush [GDIPLUS.@]
199 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
200 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
201 GpWrapMode wrap
, GpLineGradient
**line
)
203 COLORREF col
= ARGB2COLORREF(startcolor
);
205 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
206 startcolor
, endcolor
, wrap
, line
);
208 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
209 return InvalidParameter
;
211 *line
= GdipAlloc(sizeof(GpLineGradient
));
212 if(!*line
) return OutOfMemory
;
214 (*line
)->brush
.lb
.lbStyle
= BS_SOLID
;
215 (*line
)->brush
.lb
.lbColor
= col
;
216 (*line
)->brush
.lb
.lbHatch
= 0;
217 (*line
)->brush
.gdibrush
= CreateSolidBrush(col
);
218 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
220 (*line
)->startpoint
.X
= startpoint
->X
;
221 (*line
)->startpoint
.Y
= startpoint
->Y
;
222 (*line
)->endpoint
.X
= endpoint
->X
;
223 (*line
)->endpoint
.Y
= endpoint
->Y
;
224 (*line
)->startcolor
= startcolor
;
225 (*line
)->endcolor
= endcolor
;
226 (*line
)->wrap
= wrap
;
227 (*line
)->gamma
= FALSE
;
232 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
233 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
234 GpWrapMode wrap
, GpLineGradient
**line
)
239 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
240 startcolor
, endcolor
, wrap
, line
);
242 if(!startpoint
|| !endpoint
)
243 return InvalidParameter
;
245 stF
.X
= (REAL
)startpoint
->X
;
246 stF
.Y
= (REAL
)startpoint
->Y
;
247 endF
.X
= (REAL
)endpoint
->X
;
248 endF
.X
= (REAL
)endpoint
->Y
;
250 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
253 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
254 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
255 GpLineGradient
**line
)
259 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
263 return InvalidParameter
;
267 end
.X
= rect
->X
+ rect
->Width
;
268 end
.Y
= rect
->Y
+ rect
->Height
;
270 return GdipCreateLineBrush(&start
, &end
, startcolor
, endcolor
, wrap
, line
);
273 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
274 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
275 GpLineGradient
**line
)
279 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
282 rectF
.X
= (REAL
) rect
->X
;
283 rectF
.Y
= (REAL
) rect
->Y
;
284 rectF
.Width
= (REAL
) rect
->Width
;
285 rectF
.Height
= (REAL
) rect
->Height
;
287 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
290 /******************************************************************************
291 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
293 * FIXME: angle value completely ignored. Don't know how to use it since native
294 * always set Brush rectangle to rect (independetly of this angle).
295 * Maybe it's used only on drawing.
297 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF
* rect
,
298 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
299 GpLineGradient
**line
)
301 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
304 return GdipCreateLineBrushFromRect(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
308 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect
* rect
,
309 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
310 GpLineGradient
**line
)
312 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
315 return GdipCreateLineBrushFromRectI(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
319 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
320 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
322 COLORREF col
= ARGB2COLORREF(0xffffffff);
324 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
327 return InvalidParameter
;
332 *grad
= GdipAlloc(sizeof(GpPathGradient
));
333 if (!*grad
) return OutOfMemory
;
335 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
336 if(!(*grad
)->blendfac
){
340 (*grad
)->blendfac
[0] = 1.0;
341 (*grad
)->blendpos
= NULL
;
342 (*grad
)->blendcount
= 1;
344 (*grad
)->pathdata
.Count
= count
;
345 (*grad
)->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
346 (*grad
)->pathdata
.Types
= GdipAlloc(count
);
348 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
349 GdipFree((*grad
)->pathdata
.Points
);
350 GdipFree((*grad
)->pathdata
.Types
);
355 memcpy((*grad
)->pathdata
.Points
, points
, count
* sizeof(PointF
));
356 memset((*grad
)->pathdata
.Types
, PathPointTypeLine
, count
);
358 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
359 (*grad
)->brush
.lb
.lbColor
= col
;
360 (*grad
)->brush
.lb
.lbHatch
= 0;
362 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
363 (*grad
)->brush
.bt
= BrushTypePathGradient
;
364 (*grad
)->centercolor
= 0xffffffff;
365 (*grad
)->wrap
= wrap
;
366 (*grad
)->gamma
= FALSE
;
367 (*grad
)->center
.X
= 0.0;
368 (*grad
)->center
.Y
= 0.0;
369 (*grad
)->focus
.X
= 0.0;
370 (*grad
)->focus
.Y
= 0.0;
375 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
376 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
382 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
385 return InvalidParameter
;
390 pointsF
= GdipAlloc(sizeof(GpPointF
) * count
);
394 for(i
= 0; i
< count
; i
++){
395 pointsF
[i
].X
= (REAL
)points
[i
].X
;
396 pointsF
[i
].Y
= (REAL
)points
[i
].Y
;
399 ret
= GdipCreatePathGradient(pointsF
, count
, wrap
, grad
);
405 /******************************************************************************
406 * GdipCreatePathGradientFromPath [GDIPLUS.@]
408 * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
410 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
411 GpPathGradient
**grad
)
413 COLORREF col
= ARGB2COLORREF(0xffffffff);
415 TRACE("(%p, %p)\n", path
, grad
);
418 return InvalidParameter
;
420 *grad
= GdipAlloc(sizeof(GpPathGradient
));
421 if (!*grad
) return OutOfMemory
;
423 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
424 if(!(*grad
)->blendfac
){
428 (*grad
)->blendfac
[0] = 1.0;
429 (*grad
)->blendpos
= NULL
;
430 (*grad
)->blendcount
= 1;
432 (*grad
)->pathdata
.Count
= path
->pathdata
.Count
;
433 (*grad
)->pathdata
.Points
= GdipAlloc(path
->pathdata
.Count
* sizeof(PointF
));
434 (*grad
)->pathdata
.Types
= GdipAlloc(path
->pathdata
.Count
);
436 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
437 GdipFree((*grad
)->pathdata
.Points
);
438 GdipFree((*grad
)->pathdata
.Types
);
443 memcpy((*grad
)->pathdata
.Points
, path
->pathdata
.Points
,
444 path
->pathdata
.Count
* sizeof(PointF
));
445 memcpy((*grad
)->pathdata
.Types
, path
->pathdata
.Types
, path
->pathdata
.Count
);
447 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
448 (*grad
)->brush
.lb
.lbColor
= col
;
449 (*grad
)->brush
.lb
.lbHatch
= 0;
451 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
452 (*grad
)->brush
.bt
= BrushTypePathGradient
;
453 (*grad
)->centercolor
= 0xffffffff;
454 (*grad
)->wrap
= WrapModeClamp
;
455 (*grad
)->gamma
= FALSE
;
456 /* FIXME: this should be set to the "centroid" of the path by default */
457 (*grad
)->center
.X
= 0.0;
458 (*grad
)->center
.Y
= 0.0;
459 (*grad
)->focus
.X
= 0.0;
460 (*grad
)->focus
.Y
= 0.0;
465 /******************************************************************************
466 * GdipCreateSolidFill [GDIPLUS.@]
468 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
470 COLORREF col
= ARGB2COLORREF(color
);
472 TRACE("(%x, %p)\n", color
, sf
);
474 if(!sf
) return InvalidParameter
;
476 *sf
= GdipAlloc(sizeof(GpSolidFill
));
477 if (!*sf
) return OutOfMemory
;
479 (*sf
)->brush
.lb
.lbStyle
= BS_SOLID
;
480 (*sf
)->brush
.lb
.lbColor
= col
;
481 (*sf
)->brush
.lb
.lbHatch
= 0;
483 (*sf
)->brush
.gdibrush
= CreateSolidBrush(col
);
484 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
485 (*sf
)->color
= color
;
490 /******************************************************************************
491 * GdipCreateTexture [GDIPLUS.@]
494 * image [I] image to use
495 * wrapmode [I] optional
496 * texture [O] pointer to the resulting texturebrush
500 * FAILURE: element of GpStatus
502 GpStatus WINGDIPAPI
GdipCreateTexture(GpImage
*image
, GpWrapMode wrapmode
,
506 GpImageAttributes attributes
;
509 TRACE("%p, %d %p\n", image
, wrapmode
, texture
);
511 if (!(image
&& texture
))
512 return InvalidParameter
;
514 stat
= GdipGetImageWidth(image
, &width
);
515 if (stat
!= Ok
) return stat
;
516 stat
= GdipGetImageHeight(image
, &height
);
517 if (stat
!= Ok
) return stat
;
518 attributes
.wrap
= wrapmode
;
520 return GdipCreateTextureIA(image
, &attributes
, 0, 0, width
, height
,
524 /******************************************************************************
525 * GdipCreateTexture2 [GDIPLUS.@]
527 GpStatus WINGDIPAPI
GdipCreateTexture2(GpImage
*image
, GpWrapMode wrapmode
,
528 REAL x
, REAL y
, REAL width
, REAL height
, GpTexture
**texture
)
530 GpImageAttributes attributes
;
532 TRACE("%p %d %f %f %f %f %p\n", image
, wrapmode
,
533 x
, y
, width
, height
, texture
);
535 attributes
.wrap
= wrapmode
;
536 return GdipCreateTextureIA(image
, &attributes
, x
, y
, width
, height
,
540 /******************************************************************************
541 * GdipCreateTextureIA [GDIPLUS.@]
543 * FIXME: imageattr ignored
545 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
546 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
547 REAL height
, GpTexture
**texture
)
550 HBITMAP hbm
, old
= NULL
;
552 BITMAPINFOHEADER
*bmih
;
553 INT n_x
, n_y
, n_width
, n_height
, abs_height
, stride
, image_stride
, i
, bytespp
;
555 BYTE
*dibits
, *buff
, *textbits
;
558 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image
, imageattr
, x
, y
, width
, height
,
561 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
562 return InvalidParameter
;
564 if(image
->type
!= ImageTypeBitmap
){
565 FIXME("not implemented for image type %d\n", image
->type
);
566 return NotImplemented
;
571 n_width
= roundr(width
);
572 n_height
= roundr(height
);
574 if(n_x
+ n_width
> ((GpBitmap
*)image
)->width
||
575 n_y
+ n_height
> ((GpBitmap
*)image
)->height
)
576 return InvalidParameter
;
578 IPicture_get_Handle(image
->picture
, (OLE_HANDLE
*)&hbm
);
579 if(!hbm
) return GenericError
;
580 IPicture_get_CurDC(image
->picture
, &hdc
);
581 bm_is_selected
= (hdc
!= 0);
583 pbmi
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
586 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
587 pbmi
->bmiHeader
.biBitCount
= 0;
590 hdc
= CreateCompatibleDC(0);
591 old
= SelectObject(hdc
, hbm
);
595 GetDIBits(hdc
, hbm
, 0, 0, NULL
, pbmi
, DIB_RGB_COLORS
);
597 bytespp
= pbmi
->bmiHeader
.biBitCount
/ 8;
598 abs_height
= abs(pbmi
->bmiHeader
.biHeight
);
600 if(n_x
> pbmi
->bmiHeader
.biWidth
|| n_x
+ n_width
> pbmi
->bmiHeader
.biWidth
||
601 n_y
> abs_height
|| n_y
+ n_height
> abs_height
){
603 return InvalidParameter
;
606 dibits
= GdipAlloc(pbmi
->bmiHeader
.biSizeImage
);
608 if(dibits
) /* this is not a good place to error out */
609 GetDIBits(hdc
, hbm
, 0, abs_height
, dibits
, pbmi
, DIB_RGB_COLORS
);
612 SelectObject(hdc
, old
);
621 image_stride
= (pbmi
->bmiHeader
.biWidth
* bytespp
+ 3) & ~3;
622 stride
= (n_width
* bytespp
+ 3) & ~3;
623 buff
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + stride
* n_height
);
630 bmih
= (BITMAPINFOHEADER
*)buff
;
631 textbits
= (BYTE
*) (bmih
+ 1);
632 bmih
->biSize
= sizeof(BITMAPINFOHEADER
);
633 bmih
->biWidth
= n_width
;
634 bmih
->biHeight
= n_height
;
635 bmih
->biCompression
= BI_RGB
;
636 bmih
->biSizeImage
= stride
* n_height
;
637 bmih
->biBitCount
= pbmi
->bmiHeader
.biBitCount
;
641 /* image is flipped */
642 if(pbmi
->bmiHeader
.biHeight
> 0){
643 dibits
+= pbmi
->bmiHeader
.biSizeImage
;
645 textbits
+= stride
* (n_height
- 1);
651 for(i
= 0; i
< n_height
; i
++)
652 memcpy(&textbits
[i
* stride
],
653 &dibits
[n_x
* bytespp
+ (n_y
+ i
) * image_stride
],
656 *texture
= GdipAlloc(sizeof(GpTexture
));
663 if((status
= GdipCreateMatrix(&(*texture
)->transform
)) != Ok
){
670 (*texture
)->brush
.lb
.lbStyle
= BS_DIBPATTERNPT
;
671 (*texture
)->brush
.lb
.lbColor
= DIB_RGB_COLORS
;
672 (*texture
)->brush
.lb
.lbHatch
= (ULONG_PTR
)buff
;
674 (*texture
)->brush
.gdibrush
= CreateBrushIndirect(&(*texture
)->brush
.lb
);
675 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
676 (*texture
)->wrap
= imageattr
->wrap
;
684 /******************************************************************************
685 * GdipCreateTextureIAI [GDIPLUS.@]
687 GpStatus WINGDIPAPI
GdipCreateTextureIAI(GpImage
*image
, GDIPCONST GpImageAttributes
*imageattr
,
688 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
690 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image
, imageattr
, x
, y
, width
, height
,
693 return GdipCreateTextureIA(image
,imageattr
,(REAL
)x
,(REAL
)y
,(REAL
)width
,(REAL
)height
,texture
);
696 GpStatus WINGDIPAPI
GdipCreateTexture2I(GpImage
*image
, GpWrapMode wrapmode
,
697 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
699 GpImageAttributes imageattr
;
701 TRACE("%p %d %d %d %d %d %p\n", image
, wrapmode
, x
, y
, width
, height
,
704 imageattr
.wrap
= wrapmode
;
706 return GdipCreateTextureIA(image
, &imageattr
, x
, y
, width
, height
, texture
);
709 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
711 TRACE("(%p, %p)\n", brush
, type
);
713 if(!brush
|| !type
) return InvalidParameter
;
720 GpStatus WINGDIPAPI
GdipGetHatchBackgroundColor(GpHatch
*brush
, ARGB
*backcol
)
722 TRACE("(%p, %p)\n", brush
, backcol
);
724 if(!brush
|| !backcol
) return InvalidParameter
;
726 *backcol
= brush
->backcol
;
731 GpStatus WINGDIPAPI
GdipGetHatchForegroundColor(GpHatch
*brush
, ARGB
*forecol
)
733 TRACE("(%p, %p)\n", brush
, forecol
);
735 if(!brush
|| !forecol
) return InvalidParameter
;
737 *forecol
= brush
->forecol
;
742 GpStatus WINGDIPAPI
GdipGetHatchStyle(GpHatch
*brush
, HatchStyle
*hatchstyle
)
744 TRACE("(%p, %p)\n", brush
, hatchstyle
);
746 if(!brush
|| !hatchstyle
) return InvalidParameter
;
748 *hatchstyle
= brush
->hatchstyle
;
753 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
755 TRACE("(%p)\n", brush
);
757 if(!brush
) return InvalidParameter
;
761 case BrushTypePathGradient
:
762 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Points
);
763 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Types
);
764 GdipFree(((GpPathGradient
*) brush
)->blendfac
);
765 GdipFree(((GpPathGradient
*) brush
)->blendpos
);
767 case BrushTypeSolidColor
:
768 case BrushTypeLinearGradient
:
770 case BrushTypeTextureFill
:
771 GdipDeleteMatrix(((GpTexture
*)brush
)->transform
);
777 DeleteObject(brush
->gdibrush
);
783 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
786 TRACE("(%p, %p)\n", line
, usinggamma
);
788 if(!line
|| !usinggamma
)
789 return InvalidParameter
;
791 *usinggamma
= line
->gamma
;
796 GpStatus WINGDIPAPI
GdipGetLineWrapMode(GpLineGradient
*brush
, GpWrapMode
*wrapmode
)
798 TRACE("(%p, %p)\n", brush
, wrapmode
);
800 if(!brush
|| !wrapmode
)
801 return InvalidParameter
;
803 *wrapmode
= brush
->wrap
;
808 GpStatus WINGDIPAPI
GdipGetPathGradientBlend(GpPathGradient
*brush
, REAL
*blend
,
809 REAL
*positions
, INT count
)
811 TRACE("(%p, %p, %p, %d)\n", brush
, blend
, positions
, count
);
813 if(!brush
|| !blend
|| !positions
|| count
<= 0)
814 return InvalidParameter
;
816 if(count
< brush
->blendcount
)
817 return InsufficientBuffer
;
819 memcpy(blend
, brush
->blendfac
, count
*sizeof(REAL
));
820 if(brush
->blendcount
> 1){
821 memcpy(positions
, brush
->blendpos
, count
*sizeof(REAL
));
827 GpStatus WINGDIPAPI
GdipGetPathGradientBlendCount(GpPathGradient
*brush
, INT
*count
)
829 TRACE("(%p, %p)\n", brush
, count
);
832 return InvalidParameter
;
834 *count
= brush
->blendcount
;
839 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
842 TRACE("(%p, %p)\n", grad
, point
);
845 return InvalidParameter
;
847 point
->X
= grad
->center
.X
;
848 point
->Y
= grad
->center
.Y
;
853 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
859 TRACE("(%p, %p)\n", grad
, point
);
862 return InvalidParameter
;
864 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
867 point
->X
= roundr(ptf
.X
);
868 point
->Y
= roundr(ptf
.Y
);
874 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
877 TRACE("(%p, %p, %p)\n", grad
, x
, y
);
879 if(!grad
|| !x
|| !y
)
880 return InvalidParameter
;
888 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
891 TRACE("(%p, %p)\n", grad
, gamma
);
894 return InvalidParameter
;
896 *gamma
= grad
->gamma
;
901 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
904 TRACE("(%p, %p)\n", grad
, count
);
907 return InvalidParameter
;
909 *count
= grad
->pathdata
.Count
;
914 GpStatus WINGDIPAPI
GdipGetPathGradientRect(GpPathGradient
*brush
, GpRectF
*rect
)
920 TRACE("(%p, %p)\n", brush
, rect
);
923 return InvalidParameter
;
925 stat
= GdipCreatePath2(brush
->pathdata
.Points
, brush
->pathdata
.Types
,
926 brush
->pathdata
.Count
, FillModeAlternate
, &path
);
927 if(stat
!= Ok
) return stat
;
929 stat
= GdipGetPathWorldBounds(path
, &r
, NULL
, NULL
);
931 GdipDeletePath(path
);
935 memcpy(rect
, &r
, sizeof(GpRectF
));
937 GdipDeletePath(path
);
942 GpStatus WINGDIPAPI
GdipGetPathGradientRectI(GpPathGradient
*brush
, GpRect
*rect
)
947 TRACE("(%p, %p)\n", brush
, rect
);
950 return InvalidParameter
;
952 stat
= GdipGetPathGradientRect(brush
, &rectf
);
953 if(stat
!= Ok
) return stat
;
955 rect
->X
= roundr(rectf
.X
);
956 rect
->Y
= roundr(rectf
.Y
);
957 rect
->Width
= roundr(rectf
.Width
);
958 rect
->Height
= roundr(rectf
.Height
);
963 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
964 *grad
, ARGB
*argb
, INT
*count
)
968 if(!grad
|| !argb
|| !count
|| (*count
< grad
->pathdata
.Count
))
969 return InvalidParameter
;
972 FIXME("not implemented\n");
974 return NotImplemented
;
977 GpStatus WINGDIPAPI
GdipGetPathGradientWrapMode(GpPathGradient
*brush
,
978 GpWrapMode
*wrapmode
)
980 TRACE("(%p, %p)\n", brush
, wrapmode
);
982 if(!brush
|| !wrapmode
)
983 return InvalidParameter
;
985 *wrapmode
= brush
->wrap
;
990 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
992 TRACE("(%p, %p)\n", sf
, argb
);
995 return InvalidParameter
;
1002 /******************************************************************************
1003 * GdipGetTextureTransform [GDIPLUS.@]
1005 GpStatus WINGDIPAPI
GdipGetTextureTransform(GpTexture
*brush
, GpMatrix
*matrix
)
1007 TRACE("(%p, %p)\n", brush
, matrix
);
1009 if(!brush
|| !matrix
)
1010 return InvalidParameter
;
1012 memcpy(matrix
, brush
->transform
, sizeof(GpMatrix
));
1017 /******************************************************************************
1018 * GdipGetTextureWrapMode [GDIPLUS.@]
1020 GpStatus WINGDIPAPI
GdipGetTextureWrapMode(GpTexture
*brush
, GpWrapMode
*wrapmode
)
1022 TRACE("(%p, %p)\n", brush
, wrapmode
);
1024 if(!brush
|| !wrapmode
)
1025 return InvalidParameter
;
1027 *wrapmode
= brush
->wrap
;
1032 /******************************************************************************
1033 * GdipMultiplyTextureTransform [GDIPLUS.@]
1035 GpStatus WINGDIPAPI
GdipMultiplyTextureTransform(GpTexture
* brush
,
1036 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1038 TRACE("(%p, %p, %d)\n", brush
, matrix
, order
);
1040 if(!brush
|| !matrix
)
1041 return InvalidParameter
;
1043 return GdipMultiplyMatrix(brush
->transform
, matrix
, order
);
1046 /******************************************************************************
1047 * GdipResetTextureTransform [GDIPLUS.@]
1049 GpStatus WINGDIPAPI
GdipResetTextureTransform(GpTexture
* brush
)
1051 TRACE("(%p)\n", brush
);
1054 return InvalidParameter
;
1056 return GdipSetMatrixElements(brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1059 /******************************************************************************
1060 * GdipScaleTextureTransform [GDIPLUS.@]
1062 GpStatus WINGDIPAPI
GdipScaleTextureTransform(GpTexture
* brush
,
1063 REAL sx
, REAL sy
, GpMatrixOrder order
)
1065 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, sx
, sy
, order
);
1068 return InvalidParameter
;
1070 return GdipScaleMatrix(brush
->transform
, sx
, sy
, order
);
1073 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
1074 GDIPCONST REAL
*blend
, GDIPCONST REAL
* positions
, INT count
)
1078 if(!brush
|| !blend
|| !positions
|| count
<= 0)
1079 return InvalidParameter
;
1082 FIXME("not implemented\n");
1087 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
1090 TRACE("(%p, %d)\n", line
, usegamma
);
1093 return InvalidParameter
;
1095 line
->gamma
= usegamma
;
1100 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
1105 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1106 return InvalidParameter
;
1109 FIXME("not implemented\n");
1111 return NotImplemented
;
1114 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
1117 TRACE("(%p, %d)\n", line
, wrap
);
1119 if(!line
|| wrap
== WrapModeClamp
)
1120 return InvalidParameter
;
1127 GpStatus WINGDIPAPI
GdipSetPathGradientBlend(GpPathGradient
*brush
, GDIPCONST REAL
*blend
,
1128 GDIPCONST REAL
*pos
, INT count
)
1133 FIXME("not implemented\n");
1135 return NotImplemented
;
1138 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
1141 TRACE("(%p, %x)\n", grad
, argb
);
1144 return InvalidParameter
;
1146 grad
->centercolor
= argb
;
1147 grad
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1149 DeleteObject(grad
->brush
.gdibrush
);
1150 grad
->brush
.gdibrush
= CreateSolidBrush(grad
->brush
.lb
.lbColor
);
1155 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
1158 TRACE("(%p, %p)\n", grad
, point
);
1161 return InvalidParameter
;
1163 grad
->center
.X
= point
->X
;
1164 grad
->center
.Y
= point
->Y
;
1169 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
1174 TRACE("(%p, %p)\n", grad
, point
);
1177 return InvalidParameter
;
1179 ptf
.X
= (REAL
)point
->X
;
1180 ptf
.Y
= (REAL
)point
->Y
;
1182 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
1185 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
1188 TRACE("(%p, %.2f, %.2f)\n", grad
, x
, y
);
1191 return InvalidParameter
;
1199 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
1202 TRACE("(%p, %d)\n", grad
, gamma
);
1205 return InvalidParameter
;
1207 grad
->gamma
= gamma
;
1212 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
1213 REAL focus
, REAL scale
)
1217 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1218 return InvalidParameter
;
1221 FIXME("not implemented\n");
1223 return NotImplemented
;
1226 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1227 *grad
, ARGB
*argb
, INT
*count
)
1231 if(!grad
|| !argb
|| !count
|| (*count
<= 0) ||
1232 (*count
> grad
->pathdata
.Count
))
1233 return InvalidParameter
;
1236 FIXME("not implemented\n");
1238 return NotImplemented
;
1241 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
1244 TRACE("(%p, %d)\n", grad
, wrap
);
1247 return InvalidParameter
;
1254 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
1256 TRACE("(%p, %x)\n", sf
, argb
);
1259 return InvalidParameter
;
1262 sf
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1264 DeleteObject(sf
->brush
.gdibrush
);
1265 sf
->brush
.gdibrush
= CreateSolidBrush(sf
->brush
.lb
.lbColor
);
1270 /******************************************************************************
1271 * GdipSetTextureTransform [GDIPLUS.@]
1273 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
1274 GDIPCONST GpMatrix
*matrix
)
1276 TRACE("(%p, %p)\n", texture
, matrix
);
1278 if(!texture
|| !matrix
)
1279 return InvalidParameter
;
1281 memcpy(texture
->transform
, matrix
, sizeof(GpMatrix
));
1286 /******************************************************************************
1287 * GdipSetTextureWrapMode [GDIPLUS.@]
1289 * WrapMode not used, only stored
1291 GpStatus WINGDIPAPI
GdipSetTextureWrapMode(GpTexture
*brush
, GpWrapMode wrapmode
)
1293 TRACE("(%p, %d)\n", brush
, wrapmode
);
1296 return InvalidParameter
;
1298 brush
->wrap
= wrapmode
;
1303 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
1306 TRACE("(%p, %x, %x)\n", brush
, color1
, color2
);
1309 return InvalidParameter
;
1311 brush
->startcolor
= color1
;
1312 brush
->endcolor
= color2
;
1317 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
1319 TRACE("(%p, %p)\n", brush
, colors
);
1321 if(!brush
|| !colors
)
1322 return InvalidParameter
;
1324 colors
[0] = brush
->startcolor
;
1325 colors
[1] = brush
->endcolor
;
1330 /******************************************************************************
1331 * GdipRotateTextureTransform [GDIPLUS.@]
1333 GpStatus WINGDIPAPI
GdipRotateTextureTransform(GpTexture
* brush
, REAL angle
,
1334 GpMatrixOrder order
)
1336 TRACE("(%p, %.2f, %d)\n", brush
, angle
, order
);
1339 return InvalidParameter
;
1341 return GdipRotateMatrix(brush
->transform
, angle
, order
);
1344 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
1350 FIXME("not implemented\n");
1352 return NotImplemented
;
1355 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
1356 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
1361 FIXME("not implemented\n");
1363 return NotImplemented
;
1366 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
1367 GDIPCONST GpMatrix
*matrix
)
1372 FIXME("not implemented\n");
1374 return NotImplemented
;
1377 GpStatus WINGDIPAPI
GdipTranslateLineTransform(GpLineGradient
* brush
,
1378 REAL dx
, REAL dy
, GpMatrixOrder order
)
1380 FIXME("stub: %p %f %f %d\n", brush
, dx
, dy
, order
);
1382 return NotImplemented
;
1385 /******************************************************************************
1386 * GdipTranslateTextureTransform [GDIPLUS.@]
1388 GpStatus WINGDIPAPI
GdipTranslateTextureTransform(GpTexture
* brush
, REAL dx
, REAL dy
,
1389 GpMatrixOrder order
)
1391 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, dx
, dy
, order
);
1394 return InvalidParameter
;
1396 return GdipTranslateMatrix(brush
->transform
, dx
, dy
, order
);
1399 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
1401 TRACE("(%p, %p)\n", brush
, rect
);
1404 return InvalidParameter
;
1406 rect
->X
= (brush
->startpoint
.X
< brush
->endpoint
.X
? brush
->startpoint
.X
: brush
->endpoint
.X
);
1407 rect
->Y
= (brush
->startpoint
.Y
< brush
->endpoint
.Y
? brush
->startpoint
.Y
: brush
->endpoint
.Y
);
1409 rect
->Width
= fabs(brush
->startpoint
.X
- brush
->endpoint
.X
);
1410 rect
->Height
= fabs(brush
->startpoint
.Y
- brush
->endpoint
.Y
);
1415 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
1420 TRACE("(%p, %p)\n", brush
, rect
);
1423 return InvalidParameter
;
1425 ret
= GdipGetLineRect(brush
, &rectF
);
1428 rect
->X
= roundr(rectF
.X
);
1429 rect
->Y
= roundr(rectF
.Y
);
1430 rect
->Width
= roundr(rectF
.Width
);
1431 rect
->Height
= roundr(rectF
.Height
);
1437 GpStatus WINGDIPAPI
GdipRotateLineTransform(GpLineGradient
* brush
,
1438 REAL angle
, GpMatrixOrder order
)
1443 return InvalidParameter
;
1446 FIXME("(%p, %.2f, %d) stub\n", brush
, angle
, order
);
1448 return NotImplemented
;