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 GpLineGradient
*dest
, *src
;
115 dest
= GdipAlloc(sizeof(GpLineGradient
));
116 if(!dest
) return OutOfMemory
;
118 src
= (GpLineGradient
*)brush
;
120 memcpy(dest
, src
, sizeof(GpLineGradient
));
122 dest
->brush
.gdibrush
= CreateSolidBrush(dest
->brush
.lb
.lbColor
);
124 count
= dest
->blendcount
;
125 dest
->blendfac
= GdipAlloc(count
* sizeof(REAL
));
126 dest
->blendpos
= GdipAlloc(count
* sizeof(REAL
));
128 if (!dest
->blendfac
|| !dest
->blendpos
)
130 GdipFree(dest
->blendfac
);
131 GdipFree(dest
->blendpos
);
132 DeleteObject(dest
->brush
.gdibrush
);
137 memcpy(dest
->blendfac
, src
->blendfac
, count
* sizeof(REAL
));
138 memcpy(dest
->blendpos
, src
->blendpos
, count
* sizeof(REAL
));
140 *clone
= &dest
->brush
;
143 case BrushTypeTextureFill
:
144 *clone
= GdipAlloc(sizeof(GpTexture
));
145 if(!*clone
) return OutOfMemory
;
147 memcpy(*clone
, brush
, sizeof(GpTexture
));
149 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
152 ERR("not implemented for brush type %d\n", brush
->bt
);
153 return NotImplemented
;
159 static LONG
HatchStyleToHatch(HatchStyle hatchstyle
)
163 case HatchStyleHorizontal
: return HS_HORIZONTAL
;
164 case HatchStyleVertical
: return HS_VERTICAL
;
165 case HatchStyleForwardDiagonal
: return HS_FDIAGONAL
;
166 case HatchStyleBackwardDiagonal
: return HS_BDIAGONAL
;
167 case HatchStyleCross
: return HS_CROSS
;
168 case HatchStyleDiagonalCross
: return HS_DIAGCROSS
;
173 /******************************************************************************
174 * GdipCreateHatchBrush [GDIPLUS.@]
176 GpStatus WINGDIPAPI
GdipCreateHatchBrush(HatchStyle hatchstyle
, ARGB forecol
, ARGB backcol
, GpHatch
**brush
)
178 COLORREF fgcol
= ARGB2COLORREF(forecol
);
180 TRACE("(%d, %d, %d, %p)\n", hatchstyle
, forecol
, backcol
, brush
);
182 if(!brush
) return InvalidParameter
;
184 *brush
= GdipAlloc(sizeof(GpHatch
));
185 if (!*brush
) return OutOfMemory
;
189 case HatchStyleHorizontal
:
190 case HatchStyleVertical
:
191 case HatchStyleForwardDiagonal
:
192 case HatchStyleBackwardDiagonal
:
193 case HatchStyleCross
:
194 case HatchStyleDiagonalCross
:
195 /* Brushes that map to BS_HATCHED */
196 (*brush
)->brush
.lb
.lbStyle
= BS_HATCHED
;
197 (*brush
)->brush
.lb
.lbColor
= fgcol
;
198 (*brush
)->brush
.lb
.lbHatch
= HatchStyleToHatch(hatchstyle
);
202 FIXME("Unimplemented hatch style %d\n", hatchstyle
);
204 (*brush
)->brush
.lb
.lbStyle
= BS_SOLID
;
205 (*brush
)->brush
.lb
.lbColor
= fgcol
;
206 (*brush
)->brush
.lb
.lbHatch
= 0;
211 (*brush
)->brush
.gdibrush
= CreateBrushIndirect(&(*brush
)->brush
.lb
);
212 (*brush
)->brush
.bt
= BrushTypeHatchFill
;
213 (*brush
)->forecol
= forecol
;
214 (*brush
)->backcol
= backcol
;
215 (*brush
)->hatchstyle
= hatchstyle
;
220 /******************************************************************************
221 * GdipCreateLineBrush [GDIPLUS.@]
223 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
224 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
225 GpWrapMode wrap
, GpLineGradient
**line
)
227 COLORREF col
= ARGB2COLORREF(startcolor
);
229 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
230 startcolor
, endcolor
, wrap
, line
);
232 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
233 return InvalidParameter
;
235 *line
= GdipAlloc(sizeof(GpLineGradient
));
236 if(!*line
) return OutOfMemory
;
238 (*line
)->brush
.lb
.lbStyle
= BS_SOLID
;
239 (*line
)->brush
.lb
.lbColor
= col
;
240 (*line
)->brush
.lb
.lbHatch
= 0;
241 (*line
)->brush
.gdibrush
= CreateSolidBrush(col
);
242 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
244 (*line
)->startpoint
.X
= startpoint
->X
;
245 (*line
)->startpoint
.Y
= startpoint
->Y
;
246 (*line
)->endpoint
.X
= endpoint
->X
;
247 (*line
)->endpoint
.Y
= endpoint
->Y
;
248 (*line
)->startcolor
= startcolor
;
249 (*line
)->endcolor
= endcolor
;
250 (*line
)->wrap
= wrap
;
251 (*line
)->gamma
= FALSE
;
253 (*line
)->blendcount
= 1;
254 (*line
)->blendfac
= GdipAlloc(sizeof(REAL
));
255 (*line
)->blendpos
= GdipAlloc(sizeof(REAL
));
257 if (!(*line
)->blendfac
|| !(*line
)->blendpos
)
259 GdipFree((*line
)->blendfac
);
260 GdipFree((*line
)->blendpos
);
261 DeleteObject((*line
)->brush
.gdibrush
);
267 (*line
)->blendfac
[0] = 1.0f
;
268 (*line
)->blendpos
[0] = 1.0f
;
273 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
274 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
275 GpWrapMode wrap
, GpLineGradient
**line
)
280 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint
, endpoint
,
281 startcolor
, endcolor
, wrap
, line
);
283 if(!startpoint
|| !endpoint
)
284 return InvalidParameter
;
286 stF
.X
= (REAL
)startpoint
->X
;
287 stF
.Y
= (REAL
)startpoint
->Y
;
288 endF
.X
= (REAL
)endpoint
->X
;
289 endF
.X
= (REAL
)endpoint
->Y
;
291 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
294 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
295 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
296 GpLineGradient
**line
)
300 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
304 return InvalidParameter
;
308 end
.X
= rect
->X
+ rect
->Width
;
309 end
.Y
= rect
->Y
+ rect
->Height
;
311 return GdipCreateLineBrush(&start
, &end
, startcolor
, endcolor
, wrap
, line
);
314 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
315 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
316 GpLineGradient
**line
)
320 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect
, startcolor
, endcolor
, mode
,
323 rectF
.X
= (REAL
) rect
->X
;
324 rectF
.Y
= (REAL
) rect
->Y
;
325 rectF
.Width
= (REAL
) rect
->Width
;
326 rectF
.Height
= (REAL
) rect
->Height
;
328 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
331 /******************************************************************************
332 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
334 * FIXME: angle value completely ignored. Don't know how to use it since native
335 * always set Brush rectangle to rect (independetly of this angle).
336 * Maybe it's used only on drawing.
338 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF
* rect
,
339 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
340 GpLineGradient
**line
)
342 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
345 return GdipCreateLineBrushFromRect(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
349 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect
* rect
,
350 ARGB startcolor
, ARGB endcolor
, REAL angle
, BOOL isAngleScalable
, GpWrapMode wrap
,
351 GpLineGradient
**line
)
353 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect
, startcolor
, endcolor
, angle
, isAngleScalable
,
356 return GdipCreateLineBrushFromRectI(rect
, startcolor
, endcolor
, LinearGradientModeForwardDiagonal
,
360 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
361 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
363 COLORREF col
= ARGB2COLORREF(0xffffffff);
365 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
368 return InvalidParameter
;
373 *grad
= GdipAlloc(sizeof(GpPathGradient
));
374 if (!*grad
) return OutOfMemory
;
376 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
377 if(!(*grad
)->blendfac
){
381 (*grad
)->blendfac
[0] = 1.0;
382 (*grad
)->blendpos
= NULL
;
383 (*grad
)->blendcount
= 1;
385 (*grad
)->pathdata
.Count
= count
;
386 (*grad
)->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
387 (*grad
)->pathdata
.Types
= GdipAlloc(count
);
389 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
390 GdipFree((*grad
)->pathdata
.Points
);
391 GdipFree((*grad
)->pathdata
.Types
);
396 memcpy((*grad
)->pathdata
.Points
, points
, count
* sizeof(PointF
));
397 memset((*grad
)->pathdata
.Types
, PathPointTypeLine
, count
);
399 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
400 (*grad
)->brush
.lb
.lbColor
= col
;
401 (*grad
)->brush
.lb
.lbHatch
= 0;
403 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
404 (*grad
)->brush
.bt
= BrushTypePathGradient
;
405 (*grad
)->centercolor
= 0xffffffff;
406 (*grad
)->wrap
= wrap
;
407 (*grad
)->gamma
= FALSE
;
408 (*grad
)->center
.X
= 0.0;
409 (*grad
)->center
.Y
= 0.0;
410 (*grad
)->focus
.X
= 0.0;
411 (*grad
)->focus
.Y
= 0.0;
416 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
417 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
423 TRACE("(%p, %d, %d, %p)\n", points
, count
, wrap
, grad
);
426 return InvalidParameter
;
431 pointsF
= GdipAlloc(sizeof(GpPointF
) * count
);
435 for(i
= 0; i
< count
; i
++){
436 pointsF
[i
].X
= (REAL
)points
[i
].X
;
437 pointsF
[i
].Y
= (REAL
)points
[i
].Y
;
440 ret
= GdipCreatePathGradient(pointsF
, count
, wrap
, grad
);
446 /******************************************************************************
447 * GdipCreatePathGradientFromPath [GDIPLUS.@]
449 * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
451 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
452 GpPathGradient
**grad
)
454 COLORREF col
= ARGB2COLORREF(0xffffffff);
456 TRACE("(%p, %p)\n", path
, grad
);
459 return InvalidParameter
;
461 *grad
= GdipAlloc(sizeof(GpPathGradient
));
462 if (!*grad
) return OutOfMemory
;
464 (*grad
)->blendfac
= GdipAlloc(sizeof(REAL
));
465 if(!(*grad
)->blendfac
){
469 (*grad
)->blendfac
[0] = 1.0;
470 (*grad
)->blendpos
= NULL
;
471 (*grad
)->blendcount
= 1;
473 (*grad
)->pathdata
.Count
= path
->pathdata
.Count
;
474 (*grad
)->pathdata
.Points
= GdipAlloc(path
->pathdata
.Count
* sizeof(PointF
));
475 (*grad
)->pathdata
.Types
= GdipAlloc(path
->pathdata
.Count
);
477 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
478 GdipFree((*grad
)->pathdata
.Points
);
479 GdipFree((*grad
)->pathdata
.Types
);
484 memcpy((*grad
)->pathdata
.Points
, path
->pathdata
.Points
,
485 path
->pathdata
.Count
* sizeof(PointF
));
486 memcpy((*grad
)->pathdata
.Types
, path
->pathdata
.Types
, path
->pathdata
.Count
);
488 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
489 (*grad
)->brush
.lb
.lbColor
= col
;
490 (*grad
)->brush
.lb
.lbHatch
= 0;
492 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
493 (*grad
)->brush
.bt
= BrushTypePathGradient
;
494 (*grad
)->centercolor
= 0xffffffff;
495 (*grad
)->wrap
= WrapModeClamp
;
496 (*grad
)->gamma
= FALSE
;
497 /* FIXME: this should be set to the "centroid" of the path by default */
498 (*grad
)->center
.X
= 0.0;
499 (*grad
)->center
.Y
= 0.0;
500 (*grad
)->focus
.X
= 0.0;
501 (*grad
)->focus
.Y
= 0.0;
506 /******************************************************************************
507 * GdipCreateSolidFill [GDIPLUS.@]
509 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
511 COLORREF col
= ARGB2COLORREF(color
);
513 TRACE("(%x, %p)\n", color
, sf
);
515 if(!sf
) return InvalidParameter
;
517 *sf
= GdipAlloc(sizeof(GpSolidFill
));
518 if (!*sf
) return OutOfMemory
;
520 (*sf
)->brush
.lb
.lbStyle
= BS_SOLID
;
521 (*sf
)->brush
.lb
.lbColor
= col
;
522 (*sf
)->brush
.lb
.lbHatch
= 0;
524 (*sf
)->brush
.gdibrush
= CreateSolidBrush(col
);
525 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
526 (*sf
)->color
= color
;
531 /******************************************************************************
532 * GdipCreateTexture [GDIPLUS.@]
535 * image [I] image to use
536 * wrapmode [I] optional
537 * texture [O] pointer to the resulting texturebrush
541 * FAILURE: element of GpStatus
543 GpStatus WINGDIPAPI
GdipCreateTexture(GpImage
*image
, GpWrapMode wrapmode
,
547 GpImageAttributes attributes
;
550 TRACE("%p, %d %p\n", image
, wrapmode
, texture
);
552 if (!(image
&& texture
))
553 return InvalidParameter
;
555 stat
= GdipGetImageWidth(image
, &width
);
556 if (stat
!= Ok
) return stat
;
557 stat
= GdipGetImageHeight(image
, &height
);
558 if (stat
!= Ok
) return stat
;
559 attributes
.wrap
= wrapmode
;
561 return GdipCreateTextureIA(image
, &attributes
, 0, 0, width
, height
,
565 /******************************************************************************
566 * GdipCreateTexture2 [GDIPLUS.@]
568 GpStatus WINGDIPAPI
GdipCreateTexture2(GpImage
*image
, GpWrapMode wrapmode
,
569 REAL x
, REAL y
, REAL width
, REAL height
, GpTexture
**texture
)
571 GpImageAttributes attributes
;
573 TRACE("%p %d %f %f %f %f %p\n", image
, wrapmode
,
574 x
, y
, width
, height
, texture
);
576 attributes
.wrap
= wrapmode
;
577 return GdipCreateTextureIA(image
, &attributes
, x
, y
, width
, height
,
581 /******************************************************************************
582 * GdipCreateTextureIA [GDIPLUS.@]
584 * FIXME: imageattr ignored
586 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
587 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
588 REAL height
, GpTexture
**texture
)
591 HBITMAP hbm
, old
= NULL
;
593 BITMAPINFOHEADER
*bmih
;
594 INT n_x
, n_y
, n_width
, n_height
, abs_height
, stride
, image_stride
, i
, bytespp
;
596 BYTE
*dibits
, *buff
, *textbits
;
599 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image
, imageattr
, x
, y
, width
, height
,
602 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
603 return InvalidParameter
;
605 if(image
->type
!= ImageTypeBitmap
){
606 FIXME("not implemented for image type %d\n", image
->type
);
607 return NotImplemented
;
612 n_width
= roundr(width
);
613 n_height
= roundr(height
);
615 if(n_x
+ n_width
> ((GpBitmap
*)image
)->width
||
616 n_y
+ n_height
> ((GpBitmap
*)image
)->height
)
617 return InvalidParameter
;
619 IPicture_get_Handle(image
->picture
, (OLE_HANDLE
*)&hbm
);
620 if(!hbm
) return GenericError
;
621 IPicture_get_CurDC(image
->picture
, &hdc
);
622 bm_is_selected
= (hdc
!= 0);
624 pbmi
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
627 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
628 pbmi
->bmiHeader
.biBitCount
= 0;
631 hdc
= CreateCompatibleDC(0);
632 old
= SelectObject(hdc
, hbm
);
636 GetDIBits(hdc
, hbm
, 0, 0, NULL
, pbmi
, DIB_RGB_COLORS
);
638 bytespp
= pbmi
->bmiHeader
.biBitCount
/ 8;
639 abs_height
= abs(pbmi
->bmiHeader
.biHeight
);
641 if(n_x
> pbmi
->bmiHeader
.biWidth
|| n_x
+ n_width
> pbmi
->bmiHeader
.biWidth
||
642 n_y
> abs_height
|| n_y
+ n_height
> abs_height
){
644 return InvalidParameter
;
647 dibits
= GdipAlloc(pbmi
->bmiHeader
.biSizeImage
);
649 if(dibits
) /* this is not a good place to error out */
650 GetDIBits(hdc
, hbm
, 0, abs_height
, dibits
, pbmi
, DIB_RGB_COLORS
);
653 SelectObject(hdc
, old
);
662 image_stride
= (pbmi
->bmiHeader
.biWidth
* bytespp
+ 3) & ~3;
663 stride
= (n_width
* bytespp
+ 3) & ~3;
664 buff
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + stride
* n_height
);
671 bmih
= (BITMAPINFOHEADER
*)buff
;
672 textbits
= (BYTE
*) (bmih
+ 1);
673 bmih
->biSize
= sizeof(BITMAPINFOHEADER
);
674 bmih
->biWidth
= n_width
;
675 bmih
->biHeight
= n_height
;
676 bmih
->biCompression
= BI_RGB
;
677 bmih
->biSizeImage
= stride
* n_height
;
678 bmih
->biBitCount
= pbmi
->bmiHeader
.biBitCount
;
682 /* image is flipped */
683 if(pbmi
->bmiHeader
.biHeight
> 0){
684 dibits
+= pbmi
->bmiHeader
.biSizeImage
;
686 textbits
+= stride
* (n_height
- 1);
692 for(i
= 0; i
< n_height
; i
++)
693 memcpy(&textbits
[i
* stride
],
694 &dibits
[n_x
* bytespp
+ (n_y
+ i
) * image_stride
],
697 *texture
= GdipAlloc(sizeof(GpTexture
));
704 if((status
= GdipCreateMatrix(&(*texture
)->transform
)) != Ok
){
711 (*texture
)->brush
.lb
.lbStyle
= BS_DIBPATTERNPT
;
712 (*texture
)->brush
.lb
.lbColor
= DIB_RGB_COLORS
;
713 (*texture
)->brush
.lb
.lbHatch
= (ULONG_PTR
)buff
;
715 (*texture
)->brush
.gdibrush
= CreateBrushIndirect(&(*texture
)->brush
.lb
);
716 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
717 (*texture
)->wrap
= imageattr
->wrap
;
725 /******************************************************************************
726 * GdipCreateTextureIAI [GDIPLUS.@]
728 GpStatus WINGDIPAPI
GdipCreateTextureIAI(GpImage
*image
, GDIPCONST GpImageAttributes
*imageattr
,
729 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
731 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image
, imageattr
, x
, y
, width
, height
,
734 return GdipCreateTextureIA(image
,imageattr
,(REAL
)x
,(REAL
)y
,(REAL
)width
,(REAL
)height
,texture
);
737 GpStatus WINGDIPAPI
GdipCreateTexture2I(GpImage
*image
, GpWrapMode wrapmode
,
738 INT x
, INT y
, INT width
, INT height
, GpTexture
**texture
)
740 GpImageAttributes imageattr
;
742 TRACE("%p %d %d %d %d %d %p\n", image
, wrapmode
, x
, y
, width
, height
,
745 imageattr
.wrap
= wrapmode
;
747 return GdipCreateTextureIA(image
, &imageattr
, x
, y
, width
, height
, texture
);
750 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
752 TRACE("(%p, %p)\n", brush
, type
);
754 if(!brush
|| !type
) return InvalidParameter
;
761 GpStatus WINGDIPAPI
GdipGetHatchBackgroundColor(GpHatch
*brush
, ARGB
*backcol
)
763 TRACE("(%p, %p)\n", brush
, backcol
);
765 if(!brush
|| !backcol
) return InvalidParameter
;
767 *backcol
= brush
->backcol
;
772 GpStatus WINGDIPAPI
GdipGetHatchForegroundColor(GpHatch
*brush
, ARGB
*forecol
)
774 TRACE("(%p, %p)\n", brush
, forecol
);
776 if(!brush
|| !forecol
) return InvalidParameter
;
778 *forecol
= brush
->forecol
;
783 GpStatus WINGDIPAPI
GdipGetHatchStyle(GpHatch
*brush
, HatchStyle
*hatchstyle
)
785 TRACE("(%p, %p)\n", brush
, hatchstyle
);
787 if(!brush
|| !hatchstyle
) return InvalidParameter
;
789 *hatchstyle
= brush
->hatchstyle
;
794 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
796 TRACE("(%p)\n", brush
);
798 if(!brush
) return InvalidParameter
;
802 case BrushTypePathGradient
:
803 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Points
);
804 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Types
);
805 GdipFree(((GpPathGradient
*) brush
)->blendfac
);
806 GdipFree(((GpPathGradient
*) brush
)->blendpos
);
808 case BrushTypeSolidColor
:
810 case BrushTypeLinearGradient
:
811 GdipFree(((GpLineGradient
*)brush
)->blendfac
);
812 GdipFree(((GpLineGradient
*)brush
)->blendpos
);
814 case BrushTypeTextureFill
:
815 GdipDeleteMatrix(((GpTexture
*)brush
)->transform
);
821 DeleteObject(brush
->gdibrush
);
827 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
830 TRACE("(%p, %p)\n", line
, usinggamma
);
832 if(!line
|| !usinggamma
)
833 return InvalidParameter
;
835 *usinggamma
= line
->gamma
;
840 GpStatus WINGDIPAPI
GdipGetLineWrapMode(GpLineGradient
*brush
, GpWrapMode
*wrapmode
)
842 TRACE("(%p, %p)\n", brush
, wrapmode
);
844 if(!brush
|| !wrapmode
)
845 return InvalidParameter
;
847 *wrapmode
= brush
->wrap
;
852 GpStatus WINGDIPAPI
GdipGetPathGradientBlend(GpPathGradient
*brush
, REAL
*blend
,
853 REAL
*positions
, INT count
)
855 TRACE("(%p, %p, %p, %d)\n", brush
, blend
, positions
, count
);
857 if(!brush
|| !blend
|| !positions
|| count
<= 0)
858 return InvalidParameter
;
860 if(count
< brush
->blendcount
)
861 return InsufficientBuffer
;
863 memcpy(blend
, brush
->blendfac
, count
*sizeof(REAL
));
864 if(brush
->blendcount
> 1){
865 memcpy(positions
, brush
->blendpos
, count
*sizeof(REAL
));
871 GpStatus WINGDIPAPI
GdipGetPathGradientBlendCount(GpPathGradient
*brush
, INT
*count
)
873 TRACE("(%p, %p)\n", brush
, count
);
876 return InvalidParameter
;
878 *count
= brush
->blendcount
;
883 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
886 TRACE("(%p, %p)\n", grad
, point
);
889 return InvalidParameter
;
891 point
->X
= grad
->center
.X
;
892 point
->Y
= grad
->center
.Y
;
897 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
903 TRACE("(%p, %p)\n", grad
, point
);
906 return InvalidParameter
;
908 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
911 point
->X
= roundr(ptf
.X
);
912 point
->Y
= roundr(ptf
.Y
);
918 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
921 TRACE("(%p, %p, %p)\n", grad
, x
, y
);
923 if(!grad
|| !x
|| !y
)
924 return InvalidParameter
;
932 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
935 TRACE("(%p, %p)\n", grad
, gamma
);
938 return InvalidParameter
;
940 *gamma
= grad
->gamma
;
945 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
948 TRACE("(%p, %p)\n", grad
, count
);
951 return InvalidParameter
;
953 *count
= grad
->pathdata
.Count
;
958 GpStatus WINGDIPAPI
GdipGetPathGradientRect(GpPathGradient
*brush
, GpRectF
*rect
)
964 TRACE("(%p, %p)\n", brush
, rect
);
967 return InvalidParameter
;
969 stat
= GdipCreatePath2(brush
->pathdata
.Points
, brush
->pathdata
.Types
,
970 brush
->pathdata
.Count
, FillModeAlternate
, &path
);
971 if(stat
!= Ok
) return stat
;
973 stat
= GdipGetPathWorldBounds(path
, &r
, NULL
, NULL
);
975 GdipDeletePath(path
);
979 memcpy(rect
, &r
, sizeof(GpRectF
));
981 GdipDeletePath(path
);
986 GpStatus WINGDIPAPI
GdipGetPathGradientRectI(GpPathGradient
*brush
, GpRect
*rect
)
991 TRACE("(%p, %p)\n", brush
, rect
);
994 return InvalidParameter
;
996 stat
= GdipGetPathGradientRect(brush
, &rectf
);
997 if(stat
!= Ok
) return stat
;
999 rect
->X
= roundr(rectf
.X
);
1000 rect
->Y
= roundr(rectf
.Y
);
1001 rect
->Width
= roundr(rectf
.Width
);
1002 rect
->Height
= roundr(rectf
.Height
);
1007 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1008 *grad
, ARGB
*argb
, INT
*count
)
1012 if(!grad
|| !argb
|| !count
|| (*count
< grad
->pathdata
.Count
))
1013 return InvalidParameter
;
1016 FIXME("not implemented\n");
1018 return NotImplemented
;
1021 GpStatus WINGDIPAPI
GdipGetPathGradientWrapMode(GpPathGradient
*brush
,
1022 GpWrapMode
*wrapmode
)
1024 TRACE("(%p, %p)\n", brush
, wrapmode
);
1026 if(!brush
|| !wrapmode
)
1027 return InvalidParameter
;
1029 *wrapmode
= brush
->wrap
;
1034 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
1036 TRACE("(%p, %p)\n", sf
, argb
);
1039 return InvalidParameter
;
1046 /******************************************************************************
1047 * GdipGetTextureTransform [GDIPLUS.@]
1049 GpStatus WINGDIPAPI
GdipGetTextureTransform(GpTexture
*brush
, GpMatrix
*matrix
)
1051 TRACE("(%p, %p)\n", brush
, matrix
);
1053 if(!brush
|| !matrix
)
1054 return InvalidParameter
;
1056 memcpy(matrix
, brush
->transform
, sizeof(GpMatrix
));
1061 /******************************************************************************
1062 * GdipGetTextureWrapMode [GDIPLUS.@]
1064 GpStatus WINGDIPAPI
GdipGetTextureWrapMode(GpTexture
*brush
, GpWrapMode
*wrapmode
)
1066 TRACE("(%p, %p)\n", brush
, wrapmode
);
1068 if(!brush
|| !wrapmode
)
1069 return InvalidParameter
;
1071 *wrapmode
= brush
->wrap
;
1076 /******************************************************************************
1077 * GdipMultiplyTextureTransform [GDIPLUS.@]
1079 GpStatus WINGDIPAPI
GdipMultiplyTextureTransform(GpTexture
* brush
,
1080 GDIPCONST GpMatrix
*matrix
, GpMatrixOrder order
)
1082 TRACE("(%p, %p, %d)\n", brush
, matrix
, order
);
1084 if(!brush
|| !matrix
)
1085 return InvalidParameter
;
1087 return GdipMultiplyMatrix(brush
->transform
, matrix
, order
);
1090 /******************************************************************************
1091 * GdipResetTextureTransform [GDIPLUS.@]
1093 GpStatus WINGDIPAPI
GdipResetTextureTransform(GpTexture
* brush
)
1095 TRACE("(%p)\n", brush
);
1098 return InvalidParameter
;
1100 return GdipSetMatrixElements(brush
->transform
, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1103 /******************************************************************************
1104 * GdipScaleTextureTransform [GDIPLUS.@]
1106 GpStatus WINGDIPAPI
GdipScaleTextureTransform(GpTexture
* brush
,
1107 REAL sx
, REAL sy
, GpMatrixOrder order
)
1109 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, sx
, sy
, order
);
1112 return InvalidParameter
;
1114 return GdipScaleMatrix(brush
->transform
, sx
, sy
, order
);
1117 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
1118 GDIPCONST REAL
*factors
, GDIPCONST REAL
* positions
, INT count
)
1120 REAL
*new_blendfac
, *new_blendpos
;
1122 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1124 if(!brush
|| !factors
|| !positions
|| count
<= 0 ||
1125 (count
>= 2 && (positions
[0] != 0.0f
|| positions
[count
-1] != 1.0f
)))
1126 return InvalidParameter
;
1128 new_blendfac
= GdipAlloc(count
* sizeof(REAL
));
1129 new_blendpos
= GdipAlloc(count
* sizeof(REAL
));
1131 if (!new_blendfac
|| !new_blendpos
)
1133 GdipFree(new_blendfac
);
1134 GdipFree(new_blendpos
);
1138 memcpy(new_blendfac
, factors
, count
* sizeof(REAL
));
1139 memcpy(new_blendpos
, positions
, count
* sizeof(REAL
));
1141 GdipFree(brush
->blendfac
);
1142 GdipFree(brush
->blendpos
);
1144 brush
->blendcount
= count
;
1145 brush
->blendfac
= new_blendfac
;
1146 brush
->blendpos
= new_blendpos
;
1151 GpStatus WINGDIPAPI
GdipGetLineBlend(GpLineGradient
*brush
, REAL
*factors
,
1152 REAL
*positions
, INT count
)
1154 TRACE("(%p, %p, %p, %i)\n", brush
, factors
, positions
, count
);
1156 if (!brush
|| !factors
|| !positions
|| count
<= 0)
1157 return InvalidParameter
;
1159 if (count
< brush
->blendcount
)
1160 return InsufficientBuffer
;
1162 memcpy(factors
, brush
->blendfac
, brush
->blendcount
* sizeof(REAL
));
1163 memcpy(positions
, brush
->blendpos
, brush
->blendcount
* sizeof(REAL
));
1168 GpStatus WINGDIPAPI
GdipGetLineBlendCount(GpLineGradient
*brush
, INT
*count
)
1170 TRACE("(%p, %p)\n", brush
, count
);
1172 if (!brush
|| !count
)
1173 return InvalidParameter
;
1175 *count
= brush
->blendcount
;
1180 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
1183 TRACE("(%p, %d)\n", line
, usegamma
);
1186 return InvalidParameter
;
1188 line
->gamma
= usegamma
;
1193 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
1198 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1199 return InvalidParameter
;
1202 FIXME("not implemented\n");
1204 return NotImplemented
;
1207 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
1210 TRACE("(%p, %d)\n", line
, wrap
);
1212 if(!line
|| wrap
== WrapModeClamp
)
1213 return InvalidParameter
;
1220 GpStatus WINGDIPAPI
GdipSetPathGradientBlend(GpPathGradient
*brush
, GDIPCONST REAL
*blend
,
1221 GDIPCONST REAL
*pos
, INT count
)
1226 FIXME("not implemented\n");
1228 return NotImplemented
;
1231 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
1234 TRACE("(%p, %x)\n", grad
, argb
);
1237 return InvalidParameter
;
1239 grad
->centercolor
= argb
;
1240 grad
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1242 DeleteObject(grad
->brush
.gdibrush
);
1243 grad
->brush
.gdibrush
= CreateSolidBrush(grad
->brush
.lb
.lbColor
);
1248 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
1251 TRACE("(%p, %p)\n", grad
, point
);
1254 return InvalidParameter
;
1256 grad
->center
.X
= point
->X
;
1257 grad
->center
.Y
= point
->Y
;
1262 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
1267 TRACE("(%p, %p)\n", grad
, point
);
1270 return InvalidParameter
;
1272 ptf
.X
= (REAL
)point
->X
;
1273 ptf
.Y
= (REAL
)point
->Y
;
1275 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
1278 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
1281 TRACE("(%p, %.2f, %.2f)\n", grad
, x
, y
);
1284 return InvalidParameter
;
1292 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
1295 TRACE("(%p, %d)\n", grad
, gamma
);
1298 return InvalidParameter
;
1300 grad
->gamma
= gamma
;
1305 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
1306 REAL focus
, REAL scale
)
1310 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
1311 return InvalidParameter
;
1314 FIXME("not implemented\n");
1316 return NotImplemented
;
1319 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1320 *grad
, ARGB
*argb
, INT
*count
)
1324 if(!grad
|| !argb
|| !count
|| (*count
<= 0) ||
1325 (*count
> grad
->pathdata
.Count
))
1326 return InvalidParameter
;
1329 FIXME("not implemented\n");
1331 return NotImplemented
;
1334 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
1337 TRACE("(%p, %d)\n", grad
, wrap
);
1340 return InvalidParameter
;
1347 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
1349 TRACE("(%p, %x)\n", sf
, argb
);
1352 return InvalidParameter
;
1355 sf
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
1357 DeleteObject(sf
->brush
.gdibrush
);
1358 sf
->brush
.gdibrush
= CreateSolidBrush(sf
->brush
.lb
.lbColor
);
1363 /******************************************************************************
1364 * GdipSetTextureTransform [GDIPLUS.@]
1366 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
1367 GDIPCONST GpMatrix
*matrix
)
1369 TRACE("(%p, %p)\n", texture
, matrix
);
1371 if(!texture
|| !matrix
)
1372 return InvalidParameter
;
1374 memcpy(texture
->transform
, matrix
, sizeof(GpMatrix
));
1379 /******************************************************************************
1380 * GdipSetTextureWrapMode [GDIPLUS.@]
1382 * WrapMode not used, only stored
1384 GpStatus WINGDIPAPI
GdipSetTextureWrapMode(GpTexture
*brush
, GpWrapMode wrapmode
)
1386 TRACE("(%p, %d)\n", brush
, wrapmode
);
1389 return InvalidParameter
;
1391 brush
->wrap
= wrapmode
;
1396 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
1399 TRACE("(%p, %x, %x)\n", brush
, color1
, color2
);
1402 return InvalidParameter
;
1404 brush
->startcolor
= color1
;
1405 brush
->endcolor
= color2
;
1410 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
1412 TRACE("(%p, %p)\n", brush
, colors
);
1414 if(!brush
|| !colors
)
1415 return InvalidParameter
;
1417 colors
[0] = brush
->startcolor
;
1418 colors
[1] = brush
->endcolor
;
1423 /******************************************************************************
1424 * GdipRotateTextureTransform [GDIPLUS.@]
1426 GpStatus WINGDIPAPI
GdipRotateTextureTransform(GpTexture
* brush
, REAL angle
,
1427 GpMatrixOrder order
)
1429 TRACE("(%p, %.2f, %d)\n", brush
, angle
, order
);
1432 return InvalidParameter
;
1434 return GdipRotateMatrix(brush
->transform
, angle
, order
);
1437 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
1443 FIXME("not implemented\n");
1445 return NotImplemented
;
1448 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
1449 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
1454 FIXME("not implemented\n");
1456 return NotImplemented
;
1459 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
1460 GDIPCONST GpMatrix
*matrix
)
1465 FIXME("not implemented\n");
1467 return NotImplemented
;
1470 GpStatus WINGDIPAPI
GdipTranslateLineTransform(GpLineGradient
* brush
,
1471 REAL dx
, REAL dy
, GpMatrixOrder order
)
1473 FIXME("stub: %p %f %f %d\n", brush
, dx
, dy
, order
);
1475 return NotImplemented
;
1478 /******************************************************************************
1479 * GdipTranslateTextureTransform [GDIPLUS.@]
1481 GpStatus WINGDIPAPI
GdipTranslateTextureTransform(GpTexture
* brush
, REAL dx
, REAL dy
,
1482 GpMatrixOrder order
)
1484 TRACE("(%p, %.2f, %.2f, %d)\n", brush
, dx
, dy
, order
);
1487 return InvalidParameter
;
1489 return GdipTranslateMatrix(brush
->transform
, dx
, dy
, order
);
1492 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
1494 TRACE("(%p, %p)\n", brush
, rect
);
1497 return InvalidParameter
;
1499 rect
->X
= (brush
->startpoint
.X
< brush
->endpoint
.X
? brush
->startpoint
.X
: brush
->endpoint
.X
);
1500 rect
->Y
= (brush
->startpoint
.Y
< brush
->endpoint
.Y
? brush
->startpoint
.Y
: brush
->endpoint
.Y
);
1502 rect
->Width
= fabs(brush
->startpoint
.X
- brush
->endpoint
.X
);
1503 rect
->Height
= fabs(brush
->startpoint
.Y
- brush
->endpoint
.Y
);
1508 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
1513 TRACE("(%p, %p)\n", brush
, rect
);
1516 return InvalidParameter
;
1518 ret
= GdipGetLineRect(brush
, &rectF
);
1521 rect
->X
= roundr(rectF
.X
);
1522 rect
->Y
= roundr(rectF
.Y
);
1523 rect
->Width
= roundr(rectF
.Width
);
1524 rect
->Height
= roundr(rectF
.Height
);
1530 GpStatus WINGDIPAPI
GdipRotateLineTransform(GpLineGradient
* brush
,
1531 REAL angle
, GpMatrixOrder order
)
1536 return InvalidParameter
;
1539 FIXME("(%p, %.2f, %d) stub\n", brush
, angle
, order
);
1541 return NotImplemented
;