dpwsockx: Implementation of SPInit
[wine/gsoc_dplay.git] / dlls / gdiplus / brush.c
blob370de616f42157978a01842d207d9fc635e584ee
1 /*
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
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
24 #include "wingdi.h"
26 #define COBJMACROS
27 #include "objbase.h"
28 #include "olectl.h"
29 #include "ole2.h"
31 #include "gdiplus.h"
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);
44 if(!brush || !clone)
45 return InvalidParameter;
47 switch(brush->bt){
48 case BrushTypeSolidColor:
50 GpSolidFill *fill;
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);
60 break;
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);
69 break;
70 case BrushTypePathGradient:{
71 GpPathGradient *src, *dest;
72 INT count;
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);
90 GdipFree(dest);
91 return OutOfMemory;
94 memcpy(dest->pathdata.Points, src->pathdata.Points, count * sizeof(PointF));
95 memcpy(dest->pathdata.Types, src->pathdata.Types, count);
97 /* blending */
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);
108 GdipFree(dest);
109 return OutOfMemory;
112 memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
113 memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
115 break;
117 case BrushTypeLinearGradient:{
118 GpLineGradient *dest, *src;
119 INT count;
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));
134 if (!dest->blendfac || !dest->blendpos)
136 GdipFree(dest->blendfac);
137 GdipFree(dest->blendpos);
138 DeleteObject(dest->brush.gdibrush);
139 GdipFree(dest);
140 return OutOfMemory;
143 memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
144 memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
146 *clone = &dest->brush;
147 break;
149 case BrushTypeTextureFill:
150 *clone = GdipAlloc(sizeof(GpTexture));
151 if(!*clone) return OutOfMemory;
153 memcpy(*clone, brush, sizeof(GpTexture));
155 (*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
156 break;
157 default:
158 ERR("not implemented for brush type %d\n", brush->bt);
159 return NotImplemented;
162 return Ok;
165 static LONG HatchStyleToHatch(HatchStyle hatchstyle)
167 switch (hatchstyle)
169 case HatchStyleHorizontal: return HS_HORIZONTAL;
170 case HatchStyleVertical: return HS_VERTICAL;
171 case HatchStyleForwardDiagonal: return HS_FDIAGONAL;
172 case HatchStyleBackwardDiagonal: return HS_BDIAGONAL;
173 case HatchStyleCross: return HS_CROSS;
174 case HatchStyleDiagonalCross: return HS_DIAGCROSS;
175 default: return 0;
179 /******************************************************************************
180 * GdipCreateHatchBrush [GDIPLUS.@]
182 GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
184 COLORREF fgcol = ARGB2COLORREF(forecol);
186 TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
188 if(!brush) return InvalidParameter;
190 *brush = GdipAlloc(sizeof(GpHatch));
191 if (!*brush) return OutOfMemory;
193 switch (hatchstyle)
195 case HatchStyleHorizontal:
196 case HatchStyleVertical:
197 case HatchStyleForwardDiagonal:
198 case HatchStyleBackwardDiagonal:
199 case HatchStyleCross:
200 case HatchStyleDiagonalCross:
201 /* Brushes that map to BS_HATCHED */
202 (*brush)->brush.lb.lbStyle = BS_HATCHED;
203 (*brush)->brush.lb.lbColor = fgcol;
204 (*brush)->brush.lb.lbHatch = HatchStyleToHatch(hatchstyle);
205 break;
207 default:
208 FIXME("Unimplemented hatch style %d\n", hatchstyle);
210 (*brush)->brush.lb.lbStyle = BS_SOLID;
211 (*brush)->brush.lb.lbColor = fgcol;
212 (*brush)->brush.lb.lbHatch = 0;
213 break;
217 (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
218 (*brush)->brush.bt = BrushTypeHatchFill;
219 (*brush)->forecol = forecol;
220 (*brush)->backcol = backcol;
221 (*brush)->hatchstyle = hatchstyle;
223 return Ok;
226 /******************************************************************************
227 * GdipCreateLineBrush [GDIPLUS.@]
229 GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
230 GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor,
231 GpWrapMode wrap, GpLineGradient **line)
233 COLORREF col = ARGB2COLORREF(startcolor);
235 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
236 startcolor, endcolor, wrap, line);
238 if(!line || !startpoint || !endpoint || wrap == WrapModeClamp)
239 return InvalidParameter;
241 *line = GdipAlloc(sizeof(GpLineGradient));
242 if(!*line) return OutOfMemory;
244 (*line)->brush.lb.lbStyle = BS_SOLID;
245 (*line)->brush.lb.lbColor = col;
246 (*line)->brush.lb.lbHatch = 0;
247 (*line)->brush.gdibrush = CreateSolidBrush(col);
248 (*line)->brush.bt = BrushTypeLinearGradient;
250 (*line)->startpoint.X = startpoint->X;
251 (*line)->startpoint.Y = startpoint->Y;
252 (*line)->endpoint.X = endpoint->X;
253 (*line)->endpoint.Y = endpoint->Y;
254 (*line)->startcolor = startcolor;
255 (*line)->endcolor = endcolor;
256 (*line)->wrap = wrap;
257 (*line)->gamma = FALSE;
259 (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X: endpoint->X);
260 (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y: endpoint->Y);
261 (*line)->rect.Width = fabs(startpoint->X - endpoint->X);
262 (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y);
264 if ((*line)->rect.Width == 0)
266 (*line)->rect.X -= (*line)->rect.Height / 2.0f;
267 (*line)->rect.Width = (*line)->rect.Height;
269 else if ((*line)->rect.Height == 0)
271 (*line)->rect.Y -= (*line)->rect.Width / 2.0f;
272 (*line)->rect.Height = (*line)->rect.Width;
275 (*line)->blendcount = 1;
276 (*line)->blendfac = GdipAlloc(sizeof(REAL));
277 (*line)->blendpos = GdipAlloc(sizeof(REAL));
279 if (!(*line)->blendfac || !(*line)->blendpos)
281 GdipFree((*line)->blendfac);
282 GdipFree((*line)->blendpos);
283 DeleteObject((*line)->brush.gdibrush);
284 GdipFree(*line);
285 *line = NULL;
286 return OutOfMemory;
289 (*line)->blendfac[0] = 1.0f;
290 (*line)->blendpos[0] = 1.0f;
292 return Ok;
295 GpStatus WINGDIPAPI GdipCreateLineBrushI(GDIPCONST GpPoint* startpoint,
296 GDIPCONST GpPoint* endpoint, ARGB startcolor, ARGB endcolor,
297 GpWrapMode wrap, GpLineGradient **line)
299 GpPointF stF;
300 GpPointF endF;
302 TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
303 startcolor, endcolor, wrap, line);
305 if(!startpoint || !endpoint)
306 return InvalidParameter;
308 stF.X = (REAL)startpoint->X;
309 stF.Y = (REAL)startpoint->Y;
310 endF.X = (REAL)endpoint->X;
311 endF.X = (REAL)endpoint->Y;
313 return GdipCreateLineBrush(&stF, &endF, startcolor, endcolor, wrap, line);
316 GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
317 ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
318 GpLineGradient **line)
320 GpPointF start, end;
321 GpStatus stat;
323 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
324 wrap, line);
326 if(!line || !rect)
327 return InvalidParameter;
329 switch (mode)
331 case LinearGradientModeHorizontal:
332 start.X = rect->X;
333 start.Y = rect->Y;
334 end.X = rect->X + rect->Width;
335 end.Y = rect->Y;
336 break;
337 case LinearGradientModeVertical:
338 start.X = rect->X;
339 start.Y = rect->Y;
340 end.X = rect->X;
341 end.Y = rect->Y + rect->Height;
342 break;
343 case LinearGradientModeForwardDiagonal:
344 start.X = rect->X;
345 start.Y = rect->Y;
346 end.X = rect->X + rect->Width;
347 end.Y = rect->Y + rect->Height;
348 break;
349 case LinearGradientModeBackwardDiagonal:
350 start.X = rect->X + rect->Width;
351 start.Y = rect->Y;
352 end.X = rect->X;
353 end.Y = rect->Y + rect->Height;
354 break;
355 default:
356 return InvalidParameter;
359 stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
361 if (stat == Ok)
362 (*line)->rect = *rect;
364 return stat;
367 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect,
368 ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
369 GpLineGradient **line)
371 GpRectF rectF;
373 TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
374 wrap, line);
376 rectF.X = (REAL) rect->X;
377 rectF.Y = (REAL) rect->Y;
378 rectF.Width = (REAL) rect->Width;
379 rectF.Height = (REAL) rect->Height;
381 return GdipCreateLineBrushFromRect(&rectF, startcolor, endcolor, mode, wrap, line);
384 /******************************************************************************
385 * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
387 * FIXME: angle value completely ignored. Don't know how to use it since native
388 * always set Brush rectangle to rect (independetly of this angle).
389 * Maybe it's used only on drawing.
391 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect,
392 ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
393 GpLineGradient **line)
395 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
396 wrap, line);
398 return GdipCreateLineBrushFromRect(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
399 wrap, line);
402 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect,
403 ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
404 GpLineGradient **line)
406 TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
407 wrap, line);
409 return GdipCreateLineBrushFromRectI(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
410 wrap, line);
413 GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points,
414 INT count, GpWrapMode wrap, GpPathGradient **grad)
416 COLORREF col = ARGB2COLORREF(0xffffffff);
418 TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
420 if(!points || !grad)
421 return InvalidParameter;
423 if(count <= 0)
424 return OutOfMemory;
426 *grad = GdipAlloc(sizeof(GpPathGradient));
427 if (!*grad) return OutOfMemory;
429 (*grad)->blendfac = GdipAlloc(sizeof(REAL));
430 if(!(*grad)->blendfac){
431 GdipFree(*grad);
432 return OutOfMemory;
434 (*grad)->blendfac[0] = 1.0;
435 (*grad)->blendpos = NULL;
436 (*grad)->blendcount = 1;
438 (*grad)->pathdata.Count = count;
439 (*grad)->pathdata.Points = GdipAlloc(count * sizeof(PointF));
440 (*grad)->pathdata.Types = GdipAlloc(count);
442 if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){
443 GdipFree((*grad)->pathdata.Points);
444 GdipFree((*grad)->pathdata.Types);
445 GdipFree(*grad);
446 return OutOfMemory;
449 memcpy((*grad)->pathdata.Points, points, count * sizeof(PointF));
450 memset((*grad)->pathdata.Types, PathPointTypeLine, count);
452 (*grad)->brush.lb.lbStyle = BS_SOLID;
453 (*grad)->brush.lb.lbColor = col;
454 (*grad)->brush.lb.lbHatch = 0;
456 (*grad)->brush.gdibrush = CreateSolidBrush(col);
457 (*grad)->brush.bt = BrushTypePathGradient;
458 (*grad)->centercolor = 0xffffffff;
459 (*grad)->wrap = wrap;
460 (*grad)->gamma = FALSE;
461 (*grad)->center.X = 0.0;
462 (*grad)->center.Y = 0.0;
463 (*grad)->focus.X = 0.0;
464 (*grad)->focus.Y = 0.0;
466 return Ok;
469 GpStatus WINGDIPAPI GdipCreatePathGradientI(GDIPCONST GpPoint* points,
470 INT count, GpWrapMode wrap, GpPathGradient **grad)
472 GpPointF *pointsF;
473 GpStatus ret;
474 INT i;
476 TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
478 if(!points || !grad)
479 return InvalidParameter;
481 if(count <= 0)
482 return OutOfMemory;
484 pointsF = GdipAlloc(sizeof(GpPointF) * count);
485 if(!pointsF)
486 return OutOfMemory;
488 for(i = 0; i < count; i++){
489 pointsF[i].X = (REAL)points[i].X;
490 pointsF[i].Y = (REAL)points[i].Y;
493 ret = GdipCreatePathGradient(pointsF, count, wrap, grad);
494 GdipFree(pointsF);
496 return ret;
499 /******************************************************************************
500 * GdipCreatePathGradientFromPath [GDIPLUS.@]
502 * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
504 GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
505 GpPathGradient **grad)
507 COLORREF col = ARGB2COLORREF(0xffffffff);
509 TRACE("(%p, %p)\n", path, grad);
511 if(!path || !grad)
512 return InvalidParameter;
514 *grad = GdipAlloc(sizeof(GpPathGradient));
515 if (!*grad) return OutOfMemory;
517 (*grad)->blendfac = GdipAlloc(sizeof(REAL));
518 if(!(*grad)->blendfac){
519 GdipFree(*grad);
520 return OutOfMemory;
522 (*grad)->blendfac[0] = 1.0;
523 (*grad)->blendpos = NULL;
524 (*grad)->blendcount = 1;
526 (*grad)->pathdata.Count = path->pathdata.Count;
527 (*grad)->pathdata.Points = GdipAlloc(path->pathdata.Count * sizeof(PointF));
528 (*grad)->pathdata.Types = GdipAlloc(path->pathdata.Count);
530 if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){
531 GdipFree((*grad)->pathdata.Points);
532 GdipFree((*grad)->pathdata.Types);
533 GdipFree(*grad);
534 return OutOfMemory;
537 memcpy((*grad)->pathdata.Points, path->pathdata.Points,
538 path->pathdata.Count * sizeof(PointF));
539 memcpy((*grad)->pathdata.Types, path->pathdata.Types, path->pathdata.Count);
541 (*grad)->brush.lb.lbStyle = BS_SOLID;
542 (*grad)->brush.lb.lbColor = col;
543 (*grad)->brush.lb.lbHatch = 0;
545 (*grad)->brush.gdibrush = CreateSolidBrush(col);
546 (*grad)->brush.bt = BrushTypePathGradient;
547 (*grad)->centercolor = 0xffffffff;
548 (*grad)->wrap = WrapModeClamp;
549 (*grad)->gamma = FALSE;
550 /* FIXME: this should be set to the "centroid" of the path by default */
551 (*grad)->center.X = 0.0;
552 (*grad)->center.Y = 0.0;
553 (*grad)->focus.X = 0.0;
554 (*grad)->focus.Y = 0.0;
556 return Ok;
559 /******************************************************************************
560 * GdipCreateSolidFill [GDIPLUS.@]
562 GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
564 COLORREF col = ARGB2COLORREF(color);
566 TRACE("(%x, %p)\n", color, sf);
568 if(!sf) return InvalidParameter;
570 *sf = GdipAlloc(sizeof(GpSolidFill));
571 if (!*sf) return OutOfMemory;
573 (*sf)->brush.lb.lbStyle = BS_SOLID;
574 (*sf)->brush.lb.lbColor = col;
575 (*sf)->brush.lb.lbHatch = 0;
577 (*sf)->brush.gdibrush = CreateSolidBrush(col);
578 (*sf)->brush.bt = BrushTypeSolidColor;
579 (*sf)->color = color;
580 (*sf)->bmp = ARGB2BMP(color);
582 return Ok;
585 /******************************************************************************
586 * GdipCreateTexture [GDIPLUS.@]
588 * PARAMS
589 * image [I] image to use
590 * wrapmode [I] optional
591 * texture [O] pointer to the resulting texturebrush
593 * RETURNS
594 * SUCCESS: Ok
595 * FAILURE: element of GpStatus
597 GpStatus WINGDIPAPI GdipCreateTexture(GpImage *image, GpWrapMode wrapmode,
598 GpTexture **texture)
600 UINT width, height;
601 GpImageAttributes attributes;
602 GpStatus stat;
604 TRACE("%p, %d %p\n", image, wrapmode, texture);
606 if (!(image && texture))
607 return InvalidParameter;
609 stat = GdipGetImageWidth(image, &width);
610 if (stat != Ok) return stat;
611 stat = GdipGetImageHeight(image, &height);
612 if (stat != Ok) return stat;
613 attributes.wrap = wrapmode;
615 return GdipCreateTextureIA(image, &attributes, 0, 0, width, height,
616 texture);
619 /******************************************************************************
620 * GdipCreateTexture2 [GDIPLUS.@]
622 GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode,
623 REAL x, REAL y, REAL width, REAL height, GpTexture **texture)
625 GpImageAttributes attributes;
627 TRACE("%p %d %f %f %f %f %p\n", image, wrapmode,
628 x, y, width, height, texture);
630 attributes.wrap = wrapmode;
631 return GdipCreateTextureIA(image, &attributes, x, y, width, height,
632 texture);
635 /******************************************************************************
636 * GdipCreateTextureIA [GDIPLUS.@]
638 * FIXME: imageattr ignored
640 GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
641 GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
642 REAL height, GpTexture **texture)
644 HDC hdc;
645 HBITMAP hbm, old = NULL;
646 BITMAPINFO *pbmi;
647 BITMAPINFOHEADER *bmih;
648 INT n_x, n_y, n_width, n_height, abs_height, stride, image_stride, i, bytespp;
649 BOOL bm_is_selected;
650 BYTE *dibits, *buff, *textbits;
651 GpStatus status;
653 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image, imageattr, x, y, width, height,
654 texture);
656 if(!image || !texture || x < 0.0 || y < 0.0 || width < 0.0 || height < 0.0)
657 return InvalidParameter;
659 if(image->type != ImageTypeBitmap){
660 FIXME("not implemented for image type %d\n", image->type);
661 return NotImplemented;
664 n_x = roundr(x);
665 n_y = roundr(y);
666 n_width = roundr(width);
667 n_height = roundr(height);
669 if(n_x + n_width > ((GpBitmap*)image)->width ||
670 n_y + n_height > ((GpBitmap*)image)->height)
671 return InvalidParameter;
673 hbm = ((GpBitmap*)image)->hbitmap;
674 if(!hbm) return GenericError;
675 hdc = ((GpBitmap*)image)->hdc;
676 bm_is_selected = (hdc != 0);
678 pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
679 if (!pbmi)
680 return OutOfMemory;
681 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
682 pbmi->bmiHeader.biBitCount = 0;
684 if(!bm_is_selected){
685 hdc = CreateCompatibleDC(0);
686 old = SelectObject(hdc, hbm);
689 /* fill out bmi */
690 GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
692 bytespp = pbmi->bmiHeader.biBitCount / 8;
693 abs_height = abs(pbmi->bmiHeader.biHeight);
695 if(n_x > pbmi->bmiHeader.biWidth || n_x + n_width > pbmi->bmiHeader.biWidth ||
696 n_y > abs_height || n_y + n_height > abs_height){
697 GdipFree(pbmi);
698 return InvalidParameter;
701 dibits = GdipAlloc(pbmi->bmiHeader.biSizeImage);
703 if(dibits) /* this is not a good place to error out */
704 GetDIBits(hdc, hbm, 0, abs_height, dibits, pbmi, DIB_RGB_COLORS);
706 if(!bm_is_selected){
707 SelectObject(hdc, old);
708 DeleteDC(hdc);
711 if(!dibits){
712 GdipFree(pbmi);
713 return OutOfMemory;
716 image_stride = (pbmi->bmiHeader.biWidth * bytespp + 3) & ~3;
717 stride = (n_width * bytespp + 3) & ~3;
718 buff = GdipAlloc(sizeof(BITMAPINFOHEADER) + stride * n_height);
719 if(!buff){
720 GdipFree(pbmi);
721 GdipFree(dibits);
722 return OutOfMemory;
725 bmih = (BITMAPINFOHEADER*)buff;
726 textbits = (BYTE*) (bmih + 1);
727 bmih->biSize = sizeof(BITMAPINFOHEADER);
728 bmih->biWidth = n_width;
729 bmih->biHeight = n_height;
730 bmih->biCompression = BI_RGB;
731 bmih->biSizeImage = stride * n_height;
732 bmih->biBitCount = pbmi->bmiHeader.biBitCount;
733 bmih->biClrUsed = 0;
734 bmih->biPlanes = 1;
736 /* image is flipped */
737 if(pbmi->bmiHeader.biHeight > 0){
738 dibits += pbmi->bmiHeader.biSizeImage;
739 image_stride *= -1;
740 textbits += stride * (n_height - 1);
741 stride *= -1;
744 GdipFree(pbmi);
746 for(i = 0; i < n_height; i++)
747 memcpy(&textbits[i * stride],
748 &dibits[n_x * bytespp + (n_y + i) * image_stride],
749 abs(stride));
751 *texture = GdipAlloc(sizeof(GpTexture));
752 if (!*texture){
753 GdipFree(dibits);
754 GdipFree(buff);
755 return OutOfMemory;
758 if((status = GdipCreateMatrix(&(*texture)->transform)) != Ok){
759 GdipFree(*texture);
760 GdipFree(dibits);
761 GdipFree(buff);
762 return status;
765 (*texture)->brush.lb.lbStyle = BS_DIBPATTERNPT;
766 (*texture)->brush.lb.lbColor = DIB_RGB_COLORS;
767 (*texture)->brush.lb.lbHatch = (ULONG_PTR)buff;
769 (*texture)->brush.gdibrush = CreateBrushIndirect(&(*texture)->brush.lb);
770 (*texture)->brush.bt = BrushTypeTextureFill;
771 (*texture)->wrap = imageattr->wrap;
773 GdipFree(dibits);
774 GdipFree(buff);
776 return Ok;
779 /******************************************************************************
780 * GdipCreateTextureIAI [GDIPLUS.@]
782 GpStatus WINGDIPAPI GdipCreateTextureIAI(GpImage *image, GDIPCONST GpImageAttributes *imageattr,
783 INT x, INT y, INT width, INT height, GpTexture **texture)
785 TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image, imageattr, x, y, width, height,
786 texture);
788 return GdipCreateTextureIA(image,imageattr,(REAL)x,(REAL)y,(REAL)width,(REAL)height,texture);
791 GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode,
792 INT x, INT y, INT width, INT height, GpTexture **texture)
794 GpImageAttributes imageattr;
796 TRACE("%p %d %d %d %d %d %p\n", image, wrapmode, x, y, width, height,
797 texture);
799 imageattr.wrap = wrapmode;
801 return GdipCreateTextureIA(image, &imageattr, x, y, width, height, texture);
804 GpStatus WINGDIPAPI GdipGetBrushType(GpBrush *brush, GpBrushType *type)
806 TRACE("(%p, %p)\n", brush, type);
808 if(!brush || !type) return InvalidParameter;
810 *type = brush->bt;
812 return Ok;
815 GpStatus WINGDIPAPI GdipGetHatchBackgroundColor(GpHatch *brush, ARGB *backcol)
817 TRACE("(%p, %p)\n", brush, backcol);
819 if(!brush || !backcol) return InvalidParameter;
821 *backcol = brush->backcol;
823 return Ok;
826 GpStatus WINGDIPAPI GdipGetHatchForegroundColor(GpHatch *brush, ARGB *forecol)
828 TRACE("(%p, %p)\n", brush, forecol);
830 if(!brush || !forecol) return InvalidParameter;
832 *forecol = brush->forecol;
834 return Ok;
837 GpStatus WINGDIPAPI GdipGetHatchStyle(GpHatch *brush, HatchStyle *hatchstyle)
839 TRACE("(%p, %p)\n", brush, hatchstyle);
841 if(!brush || !hatchstyle) return InvalidParameter;
843 *hatchstyle = brush->hatchstyle;
845 return Ok;
848 GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
850 TRACE("(%p)\n", brush);
852 if(!brush) return InvalidParameter;
854 switch(brush->bt)
856 case BrushTypePathGradient:
857 GdipFree(((GpPathGradient*) brush)->pathdata.Points);
858 GdipFree(((GpPathGradient*) brush)->pathdata.Types);
859 GdipFree(((GpPathGradient*) brush)->blendfac);
860 GdipFree(((GpPathGradient*) brush)->blendpos);
861 break;
862 case BrushTypeSolidColor:
863 if (((GpSolidFill*)brush)->bmp)
864 DeleteObject(((GpSolidFill*)brush)->bmp);
865 break;
866 case BrushTypeLinearGradient:
867 GdipFree(((GpLineGradient*)brush)->blendfac);
868 GdipFree(((GpLineGradient*)brush)->blendpos);
869 break;
870 case BrushTypeTextureFill:
871 GdipDeleteMatrix(((GpTexture*)brush)->transform);
872 break;
873 default:
874 break;
877 DeleteObject(brush->gdibrush);
878 GdipFree(brush);
880 return Ok;
883 GpStatus WINGDIPAPI GdipGetLineGammaCorrection(GpLineGradient *line,
884 BOOL *usinggamma)
886 TRACE("(%p, %p)\n", line, usinggamma);
888 if(!line || !usinggamma)
889 return InvalidParameter;
891 *usinggamma = line->gamma;
893 return Ok;
896 GpStatus WINGDIPAPI GdipGetLineWrapMode(GpLineGradient *brush, GpWrapMode *wrapmode)
898 TRACE("(%p, %p)\n", brush, wrapmode);
900 if(!brush || !wrapmode)
901 return InvalidParameter;
903 *wrapmode = brush->wrap;
905 return Ok;
908 GpStatus WINGDIPAPI GdipGetPathGradientBlend(GpPathGradient *brush, REAL *blend,
909 REAL *positions, INT count)
911 TRACE("(%p, %p, %p, %d)\n", brush, blend, positions, count);
913 if(!brush || !blend || !positions || count <= 0)
914 return InvalidParameter;
916 if(count < brush->blendcount)
917 return InsufficientBuffer;
919 memcpy(blend, brush->blendfac, count*sizeof(REAL));
920 if(brush->blendcount > 1){
921 memcpy(positions, brush->blendpos, count*sizeof(REAL));
924 return Ok;
927 GpStatus WINGDIPAPI GdipGetPathGradientBlendCount(GpPathGradient *brush, INT *count)
929 TRACE("(%p, %p)\n", brush, count);
931 if(!brush || !count)
932 return InvalidParameter;
934 *count = brush->blendcount;
936 return Ok;
939 GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient *grad,
940 GpPointF *point)
942 TRACE("(%p, %p)\n", grad, point);
944 if(!grad || !point)
945 return InvalidParameter;
947 point->X = grad->center.X;
948 point->Y = grad->center.Y;
950 return Ok;
953 GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient *grad,
954 GpPoint *point)
956 GpStatus ret;
957 GpPointF ptf;
959 TRACE("(%p, %p)\n", grad, point);
961 if(!point)
962 return InvalidParameter;
964 ret = GdipGetPathGradientCenterPoint(grad,&ptf);
966 if(ret == Ok){
967 point->X = roundr(ptf.X);
968 point->Y = roundr(ptf.Y);
971 return ret;
974 GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient *grad,
975 REAL *x, REAL *y)
977 TRACE("(%p, %p, %p)\n", grad, x, y);
979 if(!grad || !x || !y)
980 return InvalidParameter;
982 *x = grad->focus.X;
983 *y = grad->focus.Y;
985 return Ok;
988 GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient *grad,
989 BOOL *gamma)
991 TRACE("(%p, %p)\n", grad, gamma);
993 if(!grad || !gamma)
994 return InvalidParameter;
996 *gamma = grad->gamma;
998 return Ok;
1001 GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient *grad,
1002 INT *count)
1004 TRACE("(%p, %p)\n", grad, count);
1006 if(!grad || !count)
1007 return InvalidParameter;
1009 *count = grad->pathdata.Count;
1011 return Ok;
1014 GpStatus WINGDIPAPI GdipGetPathGradientRect(GpPathGradient *brush, GpRectF *rect)
1016 GpRectF r;
1017 GpPath* path;
1018 GpStatus stat;
1020 TRACE("(%p, %p)\n", brush, rect);
1022 if(!brush || !rect)
1023 return InvalidParameter;
1025 stat = GdipCreatePath2(brush->pathdata.Points, brush->pathdata.Types,
1026 brush->pathdata.Count, FillModeAlternate, &path);
1027 if(stat != Ok) return stat;
1029 stat = GdipGetPathWorldBounds(path, &r, NULL, NULL);
1030 if(stat != Ok){
1031 GdipDeletePath(path);
1032 return stat;
1035 memcpy(rect, &r, sizeof(GpRectF));
1037 GdipDeletePath(path);
1039 return Ok;
1042 GpStatus WINGDIPAPI GdipGetPathGradientRectI(GpPathGradient *brush, GpRect *rect)
1044 GpRectF rectf;
1045 GpStatus stat;
1047 TRACE("(%p, %p)\n", brush, rect);
1049 if(!brush || !rect)
1050 return InvalidParameter;
1052 stat = GdipGetPathGradientRect(brush, &rectf);
1053 if(stat != Ok) return stat;
1055 rect->X = roundr(rectf.X);
1056 rect->Y = roundr(rectf.Y);
1057 rect->Width = roundr(rectf.Width);
1058 rect->Height = roundr(rectf.Height);
1060 return Ok;
1063 GpStatus WINGDIPAPI GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1064 *grad, ARGB *argb, INT *count)
1066 static int calls;
1068 if(!grad || !argb || !count || (*count < grad->pathdata.Count))
1069 return InvalidParameter;
1071 if(!(calls++))
1072 FIXME("not implemented\n");
1074 return NotImplemented;
1077 GpStatus WINGDIPAPI GdipGetPathGradientWrapMode(GpPathGradient *brush,
1078 GpWrapMode *wrapmode)
1080 TRACE("(%p, %p)\n", brush, wrapmode);
1082 if(!brush || !wrapmode)
1083 return InvalidParameter;
1085 *wrapmode = brush->wrap;
1087 return Ok;
1090 GpStatus WINGDIPAPI GdipGetSolidFillColor(GpSolidFill *sf, ARGB *argb)
1092 TRACE("(%p, %p)\n", sf, argb);
1094 if(!sf || !argb)
1095 return InvalidParameter;
1097 *argb = sf->color;
1099 return Ok;
1102 /******************************************************************************
1103 * GdipGetTextureTransform [GDIPLUS.@]
1105 GpStatus WINGDIPAPI GdipGetTextureTransform(GpTexture *brush, GpMatrix *matrix)
1107 TRACE("(%p, %p)\n", brush, matrix);
1109 if(!brush || !matrix)
1110 return InvalidParameter;
1112 memcpy(matrix, brush->transform, sizeof(GpMatrix));
1114 return Ok;
1117 /******************************************************************************
1118 * GdipGetTextureWrapMode [GDIPLUS.@]
1120 GpStatus WINGDIPAPI GdipGetTextureWrapMode(GpTexture *brush, GpWrapMode *wrapmode)
1122 TRACE("(%p, %p)\n", brush, wrapmode);
1124 if(!brush || !wrapmode)
1125 return InvalidParameter;
1127 *wrapmode = brush->wrap;
1129 return Ok;
1132 /******************************************************************************
1133 * GdipMultiplyTextureTransform [GDIPLUS.@]
1135 GpStatus WINGDIPAPI GdipMultiplyTextureTransform(GpTexture* brush,
1136 GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
1138 TRACE("(%p, %p, %d)\n", brush, matrix, order);
1140 if(!brush || !matrix)
1141 return InvalidParameter;
1143 return GdipMultiplyMatrix(brush->transform, matrix, order);
1146 /******************************************************************************
1147 * GdipResetTextureTransform [GDIPLUS.@]
1149 GpStatus WINGDIPAPI GdipResetTextureTransform(GpTexture* brush)
1151 TRACE("(%p)\n", brush);
1153 if(!brush)
1154 return InvalidParameter;
1156 return GdipSetMatrixElements(brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1159 /******************************************************************************
1160 * GdipScaleTextureTransform [GDIPLUS.@]
1162 GpStatus WINGDIPAPI GdipScaleTextureTransform(GpTexture* brush,
1163 REAL sx, REAL sy, GpMatrixOrder order)
1165 TRACE("(%p, %.2f, %.2f, %d)\n", brush, sx, sy, order);
1167 if(!brush)
1168 return InvalidParameter;
1170 return GdipScaleMatrix(brush->transform, sx, sy, order);
1173 GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
1174 GDIPCONST REAL *factors, GDIPCONST REAL* positions, INT count)
1176 REAL *new_blendfac, *new_blendpos;
1178 TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
1180 if(!brush || !factors || !positions || count <= 0 ||
1181 (count >= 2 && (positions[0] != 0.0f || positions[count-1] != 1.0f)))
1182 return InvalidParameter;
1184 new_blendfac = GdipAlloc(count * sizeof(REAL));
1185 new_blendpos = GdipAlloc(count * sizeof(REAL));
1187 if (!new_blendfac || !new_blendpos)
1189 GdipFree(new_blendfac);
1190 GdipFree(new_blendpos);
1191 return OutOfMemory;
1194 memcpy(new_blendfac, factors, count * sizeof(REAL));
1195 memcpy(new_blendpos, positions, count * sizeof(REAL));
1197 GdipFree(brush->blendfac);
1198 GdipFree(brush->blendpos);
1200 brush->blendcount = count;
1201 brush->blendfac = new_blendfac;
1202 brush->blendpos = new_blendpos;
1204 return Ok;
1207 GpStatus WINGDIPAPI GdipGetLineBlend(GpLineGradient *brush, REAL *factors,
1208 REAL *positions, INT count)
1210 TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
1212 if (!brush || !factors || !positions || count <= 0)
1213 return InvalidParameter;
1215 if (count < brush->blendcount)
1216 return InsufficientBuffer;
1218 memcpy(factors, brush->blendfac, brush->blendcount * sizeof(REAL));
1219 memcpy(positions, brush->blendpos, brush->blendcount * sizeof(REAL));
1221 return Ok;
1224 GpStatus WINGDIPAPI GdipGetLineBlendCount(GpLineGradient *brush, INT *count)
1226 TRACE("(%p, %p)\n", brush, count);
1228 if (!brush || !count)
1229 return InvalidParameter;
1231 *count = brush->blendcount;
1233 return Ok;
1236 GpStatus WINGDIPAPI GdipSetLineGammaCorrection(GpLineGradient *line,
1237 BOOL usegamma)
1239 TRACE("(%p, %d)\n", line, usegamma);
1241 if(!line)
1242 return InvalidParameter;
1244 line->gamma = usegamma;
1246 return Ok;
1249 GpStatus WINGDIPAPI GdipSetLineSigmaBlend(GpLineGradient *line, REAL focus,
1250 REAL scale)
1252 REAL factors[33];
1253 REAL positions[33];
1254 int num_points = 0;
1255 int i;
1256 const int precision = 16;
1257 REAL erf_range; /* we use values erf(-erf_range) through erf(+erf_range) */
1258 REAL min_erf;
1259 REAL scale_erf;
1261 TRACE("(%p, %0.2f, %0.2f)\n", line, focus, scale);
1263 if(!line || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
1264 return InvalidParameter;
1266 /* we want 2 standard deviations */
1267 erf_range = 2.0 / sqrt(2);
1269 /* calculate the constants we need to normalize the error function to be
1270 between 0.0 and scale over the range we need */
1271 min_erf = erf(-erf_range);
1272 scale_erf = scale / (-2.0 * min_erf);
1274 if (focus != 0.0)
1276 positions[0] = 0.0;
1277 factors[0] = 0.0;
1278 for (i=1; i<precision; i++)
1280 positions[i] = focus * i / precision;
1281 factors[i] = scale_erf * (erf(2 * erf_range * i / precision - erf_range) - min_erf);
1283 num_points += precision;
1286 positions[num_points] = focus;
1287 factors[num_points] = scale;
1288 num_points += 1;
1290 if (focus != 1.0)
1292 for (i=1; i<precision; i++)
1294 positions[i+num_points-1] = (focus + ((1.0-focus) * i / precision));
1295 factors[i+num_points-1] = scale_erf * (erf(erf_range - 2 * erf_range * i / precision) - min_erf);
1297 num_points += precision;
1298 positions[num_points-1] = 1.0;
1299 factors[num_points-1] = 0.0;
1302 return GdipSetLineBlend(line, factors, positions, num_points);
1305 GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient *line,
1306 GpWrapMode wrap)
1308 TRACE("(%p, %d)\n", line, wrap);
1310 if(!line || wrap == WrapModeClamp)
1311 return InvalidParameter;
1313 line->wrap = wrap;
1315 return Ok;
1318 GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, GDIPCONST REAL *blend,
1319 GDIPCONST REAL *pos, INT count)
1321 static int calls;
1323 if(!(calls++))
1324 FIXME("not implemented\n");
1326 return NotImplemented;
1329 GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush,
1330 GDIPCONST ARGB *blend, GDIPCONST REAL *pos, INT count)
1332 FIXME("(%p,%p,%p,%i): stub\n", brush, blend, pos, count);
1333 return NotImplemented;
1336 GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
1337 ARGB argb)
1339 TRACE("(%p, %x)\n", grad, argb);
1341 if(!grad)
1342 return InvalidParameter;
1344 grad->centercolor = argb;
1345 grad->brush.lb.lbColor = ARGB2COLORREF(argb);
1347 DeleteObject(grad->brush.gdibrush);
1348 grad->brush.gdibrush = CreateSolidBrush(grad->brush.lb.lbColor);
1350 return Ok;
1353 GpStatus WINGDIPAPI GdipSetPathGradientCenterPoint(GpPathGradient *grad,
1354 GpPointF *point)
1356 TRACE("(%p, %p)\n", grad, point);
1358 if(!grad || !point)
1359 return InvalidParameter;
1361 grad->center.X = point->X;
1362 grad->center.Y = point->Y;
1364 return Ok;
1367 GpStatus WINGDIPAPI GdipSetPathGradientCenterPointI(GpPathGradient *grad,
1368 GpPoint *point)
1370 GpPointF ptf;
1372 TRACE("(%p, %p)\n", grad, point);
1374 if(!point)
1375 return InvalidParameter;
1377 ptf.X = (REAL)point->X;
1378 ptf.Y = (REAL)point->Y;
1380 return GdipSetPathGradientCenterPoint(grad,&ptf);
1383 GpStatus WINGDIPAPI GdipSetPathGradientFocusScales(GpPathGradient *grad,
1384 REAL x, REAL y)
1386 TRACE("(%p, %.2f, %.2f)\n", grad, x, y);
1388 if(!grad)
1389 return InvalidParameter;
1391 grad->focus.X = x;
1392 grad->focus.Y = y;
1394 return Ok;
1397 GpStatus WINGDIPAPI GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
1398 BOOL gamma)
1400 TRACE("(%p, %d)\n", grad, gamma);
1402 if(!grad)
1403 return InvalidParameter;
1405 grad->gamma = gamma;
1407 return Ok;
1410 GpStatus WINGDIPAPI GdipSetPathGradientSigmaBlend(GpPathGradient *grad,
1411 REAL focus, REAL scale)
1413 static int calls;
1415 if(!grad || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
1416 return InvalidParameter;
1418 if(!(calls++))
1419 FIXME("not implemented\n");
1421 return NotImplemented;
1424 GpStatus WINGDIPAPI GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1425 *grad, ARGB *argb, INT *count)
1427 static int calls;
1429 if(!grad || !argb || !count || (*count <= 0) ||
1430 (*count > grad->pathdata.Count))
1431 return InvalidParameter;
1433 if(!(calls++))
1434 FIXME("not implemented\n");
1436 return NotImplemented;
1439 GpStatus WINGDIPAPI GdipSetPathGradientWrapMode(GpPathGradient *grad,
1440 GpWrapMode wrap)
1442 TRACE("(%p, %d)\n", grad, wrap);
1444 if(!grad)
1445 return InvalidParameter;
1447 grad->wrap = wrap;
1449 return Ok;
1452 GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
1454 TRACE("(%p, %x)\n", sf, argb);
1456 if(!sf)
1457 return InvalidParameter;
1459 sf->color = argb;
1460 sf->brush.lb.lbColor = ARGB2COLORREF(argb);
1462 DeleteObject(sf->brush.gdibrush);
1463 sf->brush.gdibrush = CreateSolidBrush(sf->brush.lb.lbColor);
1465 return Ok;
1468 /******************************************************************************
1469 * GdipSetTextureTransform [GDIPLUS.@]
1471 GpStatus WINGDIPAPI GdipSetTextureTransform(GpTexture *texture,
1472 GDIPCONST GpMatrix *matrix)
1474 TRACE("(%p, %p)\n", texture, matrix);
1476 if(!texture || !matrix)
1477 return InvalidParameter;
1479 memcpy(texture->transform, matrix, sizeof(GpMatrix));
1481 return Ok;
1484 /******************************************************************************
1485 * GdipSetTextureWrapMode [GDIPLUS.@]
1487 * WrapMode not used, only stored
1489 GpStatus WINGDIPAPI GdipSetTextureWrapMode(GpTexture *brush, GpWrapMode wrapmode)
1491 TRACE("(%p, %d)\n", brush, wrapmode);
1493 if(!brush)
1494 return InvalidParameter;
1496 brush->wrap = wrapmode;
1498 return Ok;
1501 GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient *brush, ARGB color1,
1502 ARGB color2)
1504 TRACE("(%p, %x, %x)\n", brush, color1, color2);
1506 if(!brush)
1507 return InvalidParameter;
1509 brush->startcolor = color1;
1510 brush->endcolor = color2;
1512 return Ok;
1515 GpStatus WINGDIPAPI GdipGetLineColors(GpLineGradient *brush, ARGB *colors)
1517 TRACE("(%p, %p)\n", brush, colors);
1519 if(!brush || !colors)
1520 return InvalidParameter;
1522 colors[0] = brush->startcolor;
1523 colors[1] = brush->endcolor;
1525 return Ok;
1528 /******************************************************************************
1529 * GdipRotateTextureTransform [GDIPLUS.@]
1531 GpStatus WINGDIPAPI GdipRotateTextureTransform(GpTexture* brush, REAL angle,
1532 GpMatrixOrder order)
1534 TRACE("(%p, %.2f, %d)\n", brush, angle, order);
1536 if(!brush)
1537 return InvalidParameter;
1539 return GdipRotateMatrix(brush->transform, angle, order);
1542 GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus,
1543 REAL scale)
1545 REAL factors[3];
1546 REAL positions[3];
1547 int num_points = 0;
1549 TRACE("(%p,%.2f,%.2f)\n", brush, focus, scale);
1551 if (!brush) return InvalidParameter;
1553 if (focus != 0.0)
1555 factors[num_points] = 0.0;
1556 positions[num_points] = 0.0;
1557 num_points++;
1560 factors[num_points] = scale;
1561 positions[num_points] = focus;
1562 num_points++;
1564 if (focus != 1.0)
1566 factors[num_points] = 0.0;
1567 positions[num_points] = 1.0;
1568 num_points++;
1571 return GdipSetLineBlend(brush, factors, positions, num_points);
1574 GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient *brush,
1575 GDIPCONST ARGB *blend, GDIPCONST REAL* positions, INT count)
1577 static int calls;
1579 if(!(calls++))
1580 FIXME("not implemented\n");
1582 return NotImplemented;
1585 GpStatus WINGDIPAPI GdipSetLineTransform(GpLineGradient *brush,
1586 GDIPCONST GpMatrix *matrix)
1588 static int calls;
1590 if(!(calls++))
1591 FIXME("not implemented\n");
1593 return NotImplemented;
1596 GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient* brush,
1597 REAL dx, REAL dy, GpMatrixOrder order)
1599 FIXME("stub: %p %f %f %d\n", brush, dx, dy, order);
1601 return NotImplemented;
1604 /******************************************************************************
1605 * GdipTranslateTextureTransform [GDIPLUS.@]
1607 GpStatus WINGDIPAPI GdipTranslateTextureTransform(GpTexture* brush, REAL dx, REAL dy,
1608 GpMatrixOrder order)
1610 TRACE("(%p, %.2f, %.2f, %d)\n", brush, dx, dy, order);
1612 if(!brush)
1613 return InvalidParameter;
1615 return GdipTranslateMatrix(brush->transform, dx, dy, order);
1618 GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
1620 TRACE("(%p, %p)\n", brush, rect);
1622 if(!brush || !rect)
1623 return InvalidParameter;
1625 *rect = brush->rect;
1627 return Ok;
1630 GpStatus WINGDIPAPI GdipGetLineRectI(GpLineGradient *brush, GpRect *rect)
1632 GpRectF rectF;
1633 GpStatus ret;
1635 TRACE("(%p, %p)\n", brush, rect);
1637 if(!rect)
1638 return InvalidParameter;
1640 ret = GdipGetLineRect(brush, &rectF);
1642 if(ret == Ok){
1643 rect->X = roundr(rectF.X);
1644 rect->Y = roundr(rectF.Y);
1645 rect->Width = roundr(rectF.Width);
1646 rect->Height = roundr(rectF.Height);
1649 return ret;
1652 GpStatus WINGDIPAPI GdipRotateLineTransform(GpLineGradient* brush,
1653 REAL angle, GpMatrixOrder order)
1655 static int calls;
1657 if(!brush)
1658 return InvalidParameter;
1660 if(!(calls++))
1661 FIXME("(%p, %.2f, %d) stub\n", brush, angle, order);
1663 return NotImplemented;