~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdiplus/brush.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright (C) 2007 Google (Evan Stade)
  3  *
  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.
  8  *
  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.
 13  *
 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
 17  */
 18 
 19 #include <stdarg.h>
 20 
 21 #include "windef.h"
 22 #include "winbase.h"
 23 #include "winuser.h"
 24 #include "wingdi.h"
 25 
 26 #define COBJMACROS
 27 #include "objbase.h"
 28 #include "olectl.h"
 29 #include "ole2.h"
 30 
 31 #include "gdiplus.h"
 32 #include "gdiplus_private.h"
 33 #include "wine/debug.h"
 34 
 35 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 36 
 37 /******************************************************************************
 38  * GdipCloneBrush [GDIPLUS.@]
 39  */
 40 GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
 41 {
 42     TRACE("(%p, %p)\n", brush, clone);
 43 
 44     if(!brush || !clone)
 45         return InvalidParameter;
 46 
 47     switch(brush->bt){
 48         case BrushTypeSolidColor:
 49         {
 50             GpSolidFill *fill;
 51             *clone = GdipAlloc(sizeof(GpSolidFill));
 52             if (!*clone) return OutOfMemory;
 53 
 54             fill = (GpSolidFill*)*clone;
 55 
 56             memcpy(*clone, brush, sizeof(GpSolidFill));
 57 
 58             (*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
 59             fill->bmp = ARGB2BMP(fill->color);
 60             break;
 61         }
 62         case BrushTypeHatchFill:
 63             *clone = GdipAlloc(sizeof(GpHatch));
 64             if (!*clone) return OutOfMemory;
 65 
 66             memcpy(*clone, brush, sizeof(GpHatch));
 67 
 68             (*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
 69             break;
 70         case BrushTypePathGradient:{
 71             GpPathGradient *src, *dest;
 72             INT count;
 73 
 74             *clone = GdipAlloc(sizeof(GpPathGradient));
 75             if (!*clone) return OutOfMemory;
 76 
 77             src = (GpPathGradient*) brush,
 78             dest = (GpPathGradient*) *clone;
 79             count = src->pathdata.Count;
 80 
 81             memcpy(dest, src, sizeof(GpPathGradient));
 82 
 83             dest->pathdata.Count = count;
 84             dest->pathdata.Points = GdipAlloc(count * sizeof(PointF));
 85             dest->pathdata.Types = GdipAlloc(count);
 86 
 87             if(!dest->pathdata.Points || !dest->pathdata.Types){
 88                 GdipFree(dest->pathdata.Points);
 89                 GdipFree(dest->pathdata.Types);
 90                 GdipFree(dest);
 91                 return OutOfMemory;
 92             }
 93 
 94             memcpy(dest->pathdata.Points, src->pathdata.Points, count * sizeof(PointF));
 95             memcpy(dest->pathdata.Types, src->pathdata.Types, count);
 96 
 97             /* blending */
 98             count = src->blendcount;
 99             dest->blendcount = count;
100             dest->blendfac = GdipAlloc(count * sizeof(REAL));
101             dest->blendpos = GdipAlloc(count * sizeof(REAL));
102 
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;
110             }
111 
112             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
113             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
114 
115             break;
116         }
117         case BrushTypeLinearGradient:{
118             GpLineGradient *dest, *src;
119             INT count;
120 
121             dest = GdipAlloc(sizeof(GpLineGradient));
122             if(!dest)    return OutOfMemory;
123 
124             src = (GpLineGradient*)brush;
125 
126             memcpy(dest, src, sizeof(GpLineGradient));
127 
128             dest->brush.gdibrush = CreateSolidBrush(dest->brush.lb.lbColor);
129 
130             count = dest->blendcount;
131             dest->blendfac = GdipAlloc(count * sizeof(REAL));
132             dest->blendpos = GdipAlloc(count * sizeof(REAL));
133 
134             if (!dest->blendfac || !dest->blendpos)
135             {
136                 GdipFree(dest->blendfac);
137                 GdipFree(dest->blendpos);
138                 DeleteObject(dest->brush.gdibrush);
139                 GdipFree(dest);
140                 return OutOfMemory;
141             }
142 
143             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
144             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
145 
146             *clone = &dest->brush;
147             break;
148         }
149         case BrushTypeTextureFill:
150             *clone = GdipAlloc(sizeof(GpTexture));
151             if(!*clone)    return OutOfMemory;
152 
153             memcpy(*clone, brush, sizeof(GpTexture));
154 
155             (*clone)->gdibrush = CreateBrushIndirect(&(*clone)->lb);
156             break;
157         default:
158             ERR("not implemented for brush type %d\n", brush->bt);
159             return NotImplemented;
160     }
161 
162     return Ok;
163 }
164 
165 static LONG HatchStyleToHatch(HatchStyle hatchstyle)
166 {
167     switch (hatchstyle)
168     {
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;
176     }
177 }
178 
179 /******************************************************************************
180  * GdipCreateHatchBrush [GDIPLUS.@]
181  */
182 GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
183 {
184     COLORREF fgcol = ARGB2COLORREF(forecol);
185 
186     TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
187 
188     if(!brush)  return InvalidParameter;
189 
190     *brush = GdipAlloc(sizeof(GpHatch));
191     if (!*brush) return OutOfMemory;
192 
193     switch (hatchstyle)
194     {
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;
206 
207         default:
208             FIXME("Unimplemented hatch style %d\n", hatchstyle);
209 
210             (*brush)->brush.lb.lbStyle = BS_SOLID;
211             (*brush)->brush.lb.lbColor = fgcol;
212             (*brush)->brush.lb.lbHatch = 0;
213             break;
214     }
215 
216 
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;
222 
223     return Ok;
224 }
225 
226 /******************************************************************************
227  * GdipCreateLineBrush [GDIPLUS.@]
228  */
229 GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
230     GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor,
231     GpWrapMode wrap, GpLineGradient **line)
232 {
233     COLORREF col = ARGB2COLORREF(startcolor);
234 
235     TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
236           startcolor, endcolor, wrap, line);
237 
238     if(!line || !startpoint || !endpoint || wrap == WrapModeClamp)
239         return InvalidParameter;
240 
241     *line = GdipAlloc(sizeof(GpLineGradient));
242     if(!*line)  return OutOfMemory;
243 
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;
249 
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;
258 
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);
263 
264     if ((*line)->rect.Width == 0)
265     {
266         (*line)->rect.X -= (*line)->rect.Height / 2.0f;
267         (*line)->rect.Width = (*line)->rect.Height;
268     }
269     else if ((*line)->rect.Height == 0)
270     {
271         (*line)->rect.Y -= (*line)->rect.Width / 2.0f;
272         (*line)->rect.Height = (*line)->rect.Width;
273     }
274 
275     (*line)->blendcount = 1;
276     (*line)->blendfac = GdipAlloc(sizeof(REAL));
277     (*line)->blendpos = GdipAlloc(sizeof(REAL));
278 
279     if (!(*line)->blendfac || !(*line)->blendpos)
280     {
281         GdipFree((*line)->blendfac);
282         GdipFree((*line)->blendpos);
283         DeleteObject((*line)->brush.gdibrush);
284         GdipFree(*line);
285         *line = NULL;
286         return OutOfMemory;
287     }
288 
289     (*line)->blendfac[0] = 1.0f;
290     (*line)->blendpos[0] = 1.0f;
291 
292     return Ok;
293 }
294 
295 GpStatus WINGDIPAPI GdipCreateLineBrushI(GDIPCONST GpPoint* startpoint,
296     GDIPCONST GpPoint* endpoint, ARGB startcolor, ARGB endcolor,
297     GpWrapMode wrap, GpLineGradient **line)
298 {
299     GpPointF stF;
300     GpPointF endF;
301 
302     TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
303           startcolor, endcolor, wrap, line);
304 
305     if(!startpoint || !endpoint)
306         return InvalidParameter;
307 
308     stF.X  = (REAL)startpoint->X;
309     stF.Y  = (REAL)startpoint->Y;
310     endF.X = (REAL)endpoint->X;
311     endF.X = (REAL)endpoint->Y;
312 
313     return GdipCreateLineBrush(&stF, &endF, startcolor, endcolor, wrap, line);
314 }
315 
316 GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
317     ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
318     GpLineGradient **line)
319 {
320     GpPointF start, end;
321     GpStatus stat;
322 
323     TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
324           wrap, line);
325 
326     if(!line || !rect)
327         return InvalidParameter;
328 
329     switch (mode)
330     {
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;
357     }
358 
359     stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
360 
361     if (stat == Ok)
362         (*line)->rect = *rect;
363 
364     return stat;
365 }
366 
367 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect,
368     ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
369     GpLineGradient **line)
370 {
371     GpRectF rectF;
372 
373     TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
374           wrap, line);
375 
376     rectF.X      = (REAL) rect->X;
377     rectF.Y      = (REAL) rect->Y;
378     rectF.Width  = (REAL) rect->Width;
379     rectF.Height = (REAL) rect->Height;
380 
381     return GdipCreateLineBrushFromRect(&rectF, startcolor, endcolor, mode, wrap, line);
382 }
383 
384 /******************************************************************************
385  * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
386  *
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.
390  */
391 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect,
392     ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
393     GpLineGradient **line)
394 {
395     TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
396           wrap, line);
397 
398     return GdipCreateLineBrushFromRect(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
399                                        wrap, line);
400 }
401 
402 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect,
403     ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
404     GpLineGradient **line)
405 {
406     TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
407           wrap, line);
408 
409     return GdipCreateLineBrushFromRectI(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
410                                         wrap, line);
411 }
412 
413 GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points,
414     INT count, GpWrapMode wrap, GpPathGradient **grad)
415 {
416     COLORREF col = ARGB2COLORREF(0xffffffff);
417 
418     TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
419 
420     if(!points || !grad)
421         return InvalidParameter;
422 
423     if(count <= 0)
424         return OutOfMemory;
425 
426     *grad = GdipAlloc(sizeof(GpPathGradient));
427     if (!*grad) return OutOfMemory;
428 
429     (*grad)->blendfac = GdipAlloc(sizeof(REAL));
430     if(!(*grad)->blendfac){
431         GdipFree(*grad);
432         return OutOfMemory;
433     }
434     (*grad)->blendfac[0] = 1.0;
435     (*grad)->blendpos    = NULL;
436     (*grad)->blendcount  = 1;
437 
438     (*grad)->pathdata.Count = count;
439     (*grad)->pathdata.Points = GdipAlloc(count * sizeof(PointF));
440     (*grad)->pathdata.Types = GdipAlloc(count);
441 
442     if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){
443         GdipFree((*grad)->pathdata.Points);
444         GdipFree((*grad)->pathdata.Types);
445         GdipFree(*grad);
446         return OutOfMemory;
447     }
448 
449     memcpy((*grad)->pathdata.Points, points, count * sizeof(PointF));
450     memset((*grad)->pathdata.Types, PathPointTypeLine, count);
451 
452     (*grad)->brush.lb.lbStyle = BS_SOLID;
453     (*grad)->brush.lb.lbColor = col;
454     (*grad)->brush.lb.lbHatch = 0;
455 
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;
465 
466     return Ok;
467 }
468 
469 GpStatus WINGDIPAPI GdipCreatePathGradientI(GDIPCONST GpPoint* points,
470     INT count, GpWrapMode wrap, GpPathGradient **grad)
471 {
472     GpPointF *pointsF;
473     GpStatus ret;
474     INT i;
475 
476     TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
477 
478     if(!points || !grad)
479         return InvalidParameter;
480 
481     if(count <= 0)
482         return OutOfMemory;
483 
484     pointsF = GdipAlloc(sizeof(GpPointF) * count);
485     if(!pointsF)
486         return OutOfMemory;
487 
488     for(i = 0; i < count; i++){
489         pointsF[i].X = (REAL)points[i].X;
490         pointsF[i].Y = (REAL)points[i].Y;
491     }
492 
493     ret = GdipCreatePathGradient(pointsF, count, wrap, grad);
494     GdipFree(pointsF);
495 
496     return ret;
497 }
498 
499 /******************************************************************************
500  * GdipCreatePathGradientFromPath [GDIPLUS.@]
501  *
502  * FIXME: path gradient brushes not truly supported (drawn as solid brushes)
503  */
504 GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
505     GpPathGradient **grad)
506 {
507     COLORREF col = ARGB2COLORREF(0xffffffff);
508 
509     TRACE("(%p, %p)\n", path, grad);
510 
511     if(!path || !grad)
512         return InvalidParameter;
513 
514     *grad = GdipAlloc(sizeof(GpPathGradient));
515     if (!*grad) return OutOfMemory;
516 
517     (*grad)->blendfac = GdipAlloc(sizeof(REAL));
518     if(!(*grad)->blendfac){
519         GdipFree(*grad);
520         return OutOfMemory;
521     }
522     (*grad)->blendfac[0] = 1.0;
523     (*grad)->blendpos    = NULL;
524     (*grad)->blendcount  = 1;
525 
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);
529 
530     if(!(*grad)->pathdata.Points || !(*grad)->pathdata.Types){
531         GdipFree((*grad)->pathdata.Points);
532         GdipFree((*grad)->pathdata.Types);
533         GdipFree(*grad);
534         return OutOfMemory;
535     }
536 
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);
540 
541     (*grad)->brush.lb.lbStyle = BS_SOLID;
542     (*grad)->brush.lb.lbColor = col;
543     (*grad)->brush.lb.lbHatch = 0;
544 
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;
555 
556     return Ok;
557 }
558 
559 /******************************************************************************
560  * GdipCreateSolidFill [GDIPLUS.@]
561  */
562 GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
563 {
564     COLORREF col = ARGB2COLORREF(color);
565 
566     TRACE("(%x, %p)\n", color, sf);
567 
568     if(!sf)  return InvalidParameter;
569 
570     *sf = GdipAlloc(sizeof(GpSolidFill));
571     if (!*sf) return OutOfMemory;
572 
573     (*sf)->brush.lb.lbStyle = BS_SOLID;
574     (*sf)->brush.lb.lbColor = col;
575     (*sf)->brush.lb.lbHatch = 0;
576 
577     (*sf)->brush.gdibrush = CreateSolidBrush(col);
578     (*sf)->brush.bt = BrushTypeSolidColor;
579     (*sf)->color = color;
580     (*sf)->bmp = ARGB2BMP(color);
581 
582     return Ok;
583 }
584 
585 /******************************************************************************
586  * GdipCreateTexture [GDIPLUS.@]
587  *
588  * PARAMS
589  *  image       [I] image to use
590  *  wrapmode    [I] optional
591  *  texture     [O] pointer to the resulting texturebrush
592  *
593  * RETURNS
594  *  SUCCESS: Ok
595  *  FAILURE: element of GpStatus
596  */
597 GpStatus WINGDIPAPI GdipCreateTexture(GpImage *image, GpWrapMode wrapmode,
598         GpTexture **texture)
599 {
600     UINT width, height;
601     GpImageAttributes attributes;
602     GpStatus stat;
603 
604     TRACE("%p, %d %p\n", image, wrapmode, texture);
605 
606     if (!(image && texture))
607         return InvalidParameter;
608 
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;
614 
615     return GdipCreateTextureIA(image, &attributes, 0, 0, width, height,
616             texture);
617 }
618 
619 /******************************************************************************
620  * GdipCreateTexture2 [GDIPLUS.@]
621  */
622 GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode,
623         REAL x, REAL y, REAL width, REAL height, GpTexture **texture)
624 {
625     GpImageAttributes attributes;
626 
627     TRACE("%p %d %f %f %f %f %p\n", image, wrapmode,
628             x, y, width, height, texture);
629 
630     attributes.wrap = wrapmode;
631     return GdipCreateTextureIA(image, &attributes, x, y, width, height,
632             texture);
633 }
634 
635 /******************************************************************************
636  * GdipCreateTextureIA [GDIPLUS.@]
637  *
638  * FIXME: imageattr ignored
639  */
640 GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
641     GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
642     REAL height, GpTexture **texture)
643 {
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;
652 
653     TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image, imageattr, x, y, width, height,
654            texture);
655 
656     if(!image || !texture || x < 0.0 || y < 0.0 || width < 0.0 || height < 0.0)
657         return InvalidParameter;
658 
659     if(image->type != ImageTypeBitmap){
660         FIXME("not implemented for image type %d\n", image->type);
661         return NotImplemented;
662     }
663 
664     n_x = roundr(x);
665     n_y = roundr(y);
666     n_width = roundr(width);
667     n_height = roundr(height);
668 
669     if(n_x + n_width > ((GpBitmap*)image)->width ||
670        n_y + n_height > ((GpBitmap*)image)->height)
671         return InvalidParameter;
672 
673     IPicture_get_Handle(image->picture, (OLE_HANDLE*)&hbm);
674     if(!hbm)   return GenericError;
675     IPicture_get_CurDC(image->picture, &hdc);
676     bm_is_selected = (hdc != 0);
677 
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;
683 
684     if(!bm_is_selected){
685         hdc = CreateCompatibleDC(0);
686         old = SelectObject(hdc, hbm);
687     }
688 
689     /* fill out bmi */
690     GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
691 
692     bytespp = pbmi->bmiHeader.biBitCount / 8;
693     abs_height = abs(pbmi->bmiHeader.biHeight);
694 
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;
699     }
700 
701     dibits = GdipAlloc(pbmi->bmiHeader.biSizeImage);
702 
703     if(dibits)  /* this is not a good place to error out */
704         GetDIBits(hdc, hbm, 0, abs_height, dibits, pbmi, DIB_RGB_COLORS);
705 
706     if(!bm_is_selected){
707         SelectObject(hdc, old);
708         DeleteDC(hdc);
709     }
710 
711     if(!dibits){
712         GdipFree(pbmi);
713         return OutOfMemory;
714     }
715 
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;
723     }
724 
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;
735 
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;
742     }
743 
744     GdipFree(pbmi);
745 
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));
750 
751     *texture = GdipAlloc(sizeof(GpTexture));
752     if (!*texture){
753         GdipFree(dibits);
754         GdipFree(buff);
755         return OutOfMemory;
756     }
757 
758     if((status = GdipCreateMatrix(&(*texture)->transform)) != Ok){
759         GdipFree(*texture);
760         GdipFree(dibits);
761         GdipFree(buff);
762         return status;
763     }
764 
765     (*texture)->brush.lb.lbStyle = BS_DIBPATTERNPT;
766     (*texture)->brush.lb.lbColor = DIB_RGB_COLORS;
767     (*texture)->brush.lb.lbHatch = (ULONG_PTR)buff;
768 
769     (*texture)->brush.gdibrush = CreateBrushIndirect(&(*texture)->brush.lb);
770     (*texture)->brush.bt = BrushTypeTextureFill;
771     (*texture)->wrap = imageattr->wrap;
772 
773     GdipFree(dibits);
774     GdipFree(buff);
775 
776     return Ok;
777 }
778 
779 /******************************************************************************
780  * GdipCreateTextureIAI [GDIPLUS.@]
781  */
782 GpStatus WINGDIPAPI GdipCreateTextureIAI(GpImage *image, GDIPCONST GpImageAttributes *imageattr,
783     INT x, INT y, INT width, INT height, GpTexture **texture)
784 {
785     TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image, imageattr, x, y, width, height,
786            texture);
787 
788     return GdipCreateTextureIA(image,imageattr,(REAL)x,(REAL)y,(REAL)width,(REAL)height,texture);
789 }
790 
791 GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode,
792         INT x, INT y, INT width, INT height, GpTexture **texture)
793 {
794     GpImageAttributes imageattr;
795 
796     TRACE("%p %d %d %d %d %d %p\n", image, wrapmode, x, y, width, height,
797             texture);
798 
799     imageattr.wrap = wrapmode;
800 
801     return GdipCreateTextureIA(image, &imageattr, x, y, width, height, texture);
802 }
803 
804 GpStatus WINGDIPAPI GdipGetBrushType(GpBrush *brush, GpBrushType *type)
805 {
806     TRACE("(%p, %p)\n", brush, type);
807 
808     if(!brush || !type)  return InvalidParameter;
809 
810     *type = brush->bt;
811 
812     return Ok;
813 }
814 
815 GpStatus WINGDIPAPI GdipGetHatchBackgroundColor(GpHatch *brush, ARGB *backcol)
816 {
817     TRACE("(%p, %p)\n", brush, backcol);
818 
819     if(!brush || !backcol)  return InvalidParameter;
820 
821     *backcol = brush->backcol;
822 
823     return Ok;
824 }
825 
826 GpStatus WINGDIPAPI GdipGetHatchForegroundColor(GpHatch *brush, ARGB *forecol)
827 {
828     TRACE("(%p, %p)\n", brush, forecol);
829 
830     if(!brush || !forecol)  return InvalidParameter;
831 
832     *forecol = brush->forecol;
833 
834     return Ok;
835 }
836 
837 GpStatus WINGDIPAPI GdipGetHatchStyle(GpHatch *brush, HatchStyle *hatchstyle)
838 {
839     TRACE("(%p, %p)\n", brush, hatchstyle);
840 
841     if(!brush || !hatchstyle)  return InvalidParameter;
842 
843     *hatchstyle = brush->hatchstyle;
844 
845     return Ok;
846 }
847 
848 GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
849 {
850     TRACE("(%p)\n", brush);
851 
852     if(!brush)  return InvalidParameter;
853 
854     switch(brush->bt)
855     {
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;
875     }
876 
877     DeleteObject(brush->gdibrush);
878     GdipFree(brush);
879 
880     return Ok;
881 }
882 
883 GpStatus WINGDIPAPI GdipGetLineGammaCorrection(GpLineGradient *line,
884     BOOL *usinggamma)
885 {
886     TRACE("(%p, %p)\n", line, usinggamma);
887 
888     if(!line || !usinggamma)
889         return InvalidParameter;
890 
891     *usinggamma = line->gamma;
892 
893     return Ok;
894 }
895 
896 GpStatus WINGDIPAPI GdipGetLineWrapMode(GpLineGradient *brush, GpWrapMode *wrapmode)
897 {
898     TRACE("(%p, %p)\n", brush, wrapmode);
899 
900     if(!brush || !wrapmode)
901         return InvalidParameter;
902 
903     *wrapmode = brush->wrap;
904 
905     return Ok;
906 }
907 
908 GpStatus WINGDIPAPI GdipGetPathGradientBlend(GpPathGradient *brush, REAL *blend,
909     REAL *positions, INT count)
910 {
911     TRACE("(%p, %p, %p, %d)\n", brush, blend, positions, count);
912 
913     if(!brush || !blend || !positions || count <= 0)
914         return InvalidParameter;
915 
916     if(count < brush->blendcount)
917         return InsufficientBuffer;
918 
919     memcpy(blend, brush->blendfac, count*sizeof(REAL));
920     if(brush->blendcount > 1){
921         memcpy(positions, brush->blendpos, count*sizeof(REAL));
922     }
923 
924     return Ok;
925 }
926 
927 GpStatus WINGDIPAPI GdipGetPathGradientBlendCount(GpPathGradient *brush, INT *count)
928 {
929     TRACE("(%p, %p)\n", brush, count);
930 
931     if(!brush || !count)
932         return InvalidParameter;
933 
934     *count = brush->blendcount;
935 
936     return Ok;
937 }
938 
939 GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient *grad,
940     GpPointF *point)
941 {
942     TRACE("(%p, %p)\n", grad, point);
943 
944     if(!grad || !point)
945         return InvalidParameter;
946 
947     point->X = grad->center.X;
948     point->Y = grad->center.Y;
949 
950     return Ok;
951 }
952 
953 GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient *grad,
954     GpPoint *point)
955 {
956     GpStatus ret;
957     GpPointF ptf;
958 
959     TRACE("(%p, %p)\n", grad, point);
960 
961     if(!point)
962         return InvalidParameter;
963 
964     ret = GdipGetPathGradientCenterPoint(grad,&ptf);
965 
966     if(ret == Ok){
967         point->X = roundr(ptf.X);
968         point->Y = roundr(ptf.Y);
969     }
970 
971     return ret;
972 }
973 
974 GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient *grad,
975     REAL *x, REAL *y)
976 {
977     TRACE("(%p, %p, %p)\n", grad, x, y);
978 
979     if(!grad || !x || !y)
980         return InvalidParameter;
981 
982     *x = grad->focus.X;
983     *y = grad->focus.Y;
984 
985     return Ok;
986 }
987 
988 GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient *grad,
989     BOOL *gamma)
990 {
991     TRACE("(%p, %p)\n", grad, gamma);
992 
993     if(!grad || !gamma)
994         return InvalidParameter;
995 
996     *gamma = grad->gamma;
997 
998     return Ok;
999 }
1000 
1001 GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient *grad,
1002     INT *count)
1003 {
1004     TRACE("(%p, %p)\n", grad, count);
1005 
1006     if(!grad || !count)
1007         return InvalidParameter;
1008 
1009     *count = grad->pathdata.Count;
1010 
1011     return Ok;
1012 }
1013 
1014 GpStatus WINGDIPAPI GdipGetPathGradientRect(GpPathGradient *brush, GpRectF *rect)
1015 {
1016     GpRectF r;
1017     GpPath* path;
1018     GpStatus stat;
1019 
1020     TRACE("(%p, %p)\n", brush, rect);
1021 
1022     if(!brush || !rect)
1023         return InvalidParameter;
1024 
1025     stat = GdipCreatePath2(brush->pathdata.Points, brush->pathdata.Types,
1026                            brush->pathdata.Count, FillModeAlternate, &path);
1027     if(stat != Ok)  return stat;
1028 
1029     stat = GdipGetPathWorldBounds(path, &r, NULL, NULL);
1030     if(stat != Ok){
1031         GdipDeletePath(path);
1032         return stat;
1033     }
1034 
1035     memcpy(rect, &r, sizeof(GpRectF));
1036 
1037     GdipDeletePath(path);
1038 
1039     return Ok;
1040 }
1041 
1042 GpStatus WINGDIPAPI GdipGetPathGradientRectI(GpPathGradient *brush, GpRect *rect)
1043 {
1044     GpRectF rectf;
1045     GpStatus stat;
1046 
1047     TRACE("(%p, %p)\n", brush, rect);
1048 
1049     if(!brush || !rect)
1050         return InvalidParameter;
1051 
1052     stat = GdipGetPathGradientRect(brush, &rectf);
1053     if(stat != Ok)  return stat;
1054 
1055     rect->X = roundr(rectf.X);
1056     rect->Y = roundr(rectf.Y);
1057     rect->Width  = roundr(rectf.Width);
1058     rect->Height = roundr(rectf.Height);
1059 
1060     return Ok;
1061 }
1062 
1063 GpStatus WINGDIPAPI GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
1064     *grad, ARGB *argb, INT *count)
1065 {
1066     static int calls;
1067 
1068     if(!grad || !argb || !count || (*count < grad->pathdata.Count))
1069         return InvalidParameter;
1070 
1071     if(!(calls++))
1072         FIXME("not implemented\n");
1073 
1074     return NotImplemented;
1075 }
1076 
1077 GpStatus WINGDIPAPI GdipGetPathGradientWrapMode(GpPathGradient *brush,
1078     GpWrapMode *wrapmode)
1079 {
1080     TRACE("(%p, %p)\n", brush, wrapmode);
1081 
1082     if(!brush || !wrapmode)
1083         return InvalidParameter;
1084 
1085     *wrapmode = brush->wrap;
1086 
1087     return Ok;
1088 }
1089 
1090 GpStatus WINGDIPAPI GdipGetSolidFillColor(GpSolidFill *sf, ARGB *argb)
1091 {
1092     TRACE("(%p, %p)\n", sf, argb);
1093 
1094     if(!sf || !argb)
1095         return InvalidParameter;
1096 
1097     *argb = sf->color;
1098 
1099     return Ok;
1100 }
1101 
1102 /******************************************************************************
1103  * GdipGetTextureTransform [GDIPLUS.@]
1104  */
1105 GpStatus WINGDIPAPI GdipGetTextureTransform(GpTexture *brush, GpMatrix *matrix)
1106 {
1107     TRACE("(%p, %p)\n", brush, matrix);
1108 
1109     if(!brush || !matrix)
1110         return InvalidParameter;
1111 
1112     memcpy(matrix, brush->transform, sizeof(GpMatrix));
1113 
1114     return Ok;
1115 }
1116 
1117 /******************************************************************************
1118  * GdipGetTextureWrapMode [GDIPLUS.@]
1119  */
1120 GpStatus WINGDIPAPI GdipGetTextureWrapMode(GpTexture *brush, GpWrapMode *wrapmode)
1121 {
1122     TRACE("(%p, %p)\n", brush, wrapmode);
1123 
1124     if(!brush || !wrapmode)
1125         return InvalidParameter;
1126 
1127     *wrapmode = brush->wrap;
1128 
1129     return Ok;
1130 }
1131 
1132 /******************************************************************************
1133  * GdipMultiplyTextureTransform [GDIPLUS.@]
1134  */
1135 GpStatus WINGDIPAPI GdipMultiplyTextureTransform(GpTexture* brush,
1136     GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
1137 {
1138     TRACE("(%p, %p, %d)\n", brush, matrix, order);
1139 
1140     if(!brush || !matrix)
1141         return InvalidParameter;
1142 
1143     return GdipMultiplyMatrix(brush->transform, matrix, order);
1144 }
1145 
1146 /******************************************************************************
1147  * GdipResetTextureTransform [GDIPLUS.@]
1148  */
1149 GpStatus WINGDIPAPI GdipResetTextureTransform(GpTexture* brush)
1150 {
1151     TRACE("(%p)\n", brush);
1152 
1153     if(!brush)
1154         return InvalidParameter;
1155 
1156     return GdipSetMatrixElements(brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1157 }
1158 
1159 /******************************************************************************
1160  * GdipScaleTextureTransform [GDIPLUS.@]
1161  */
1162 GpStatus WINGDIPAPI GdipScaleTextureTransform(GpTexture* brush,
1163     REAL sx, REAL sy, GpMatrixOrder order)
1164 {
1165     TRACE("(%p, %.2f, %.2f, %d)\n", brush, sx, sy, order);
1166 
1167     if(!brush)
1168         return InvalidParameter;
1169 
1170     return GdipScaleMatrix(brush->transform, sx, sy, order);
1171 }
1172 
1173 GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
1174     GDIPCONST REAL *factors, GDIPCONST REAL* positions, INT count)
1175 {
1176     REAL *new_blendfac, *new_blendpos;
1177 
1178     TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
1179 
1180     if(!brush || !factors || !positions || count <= 0 ||
1181        (count >= 2 && (positions[0] != 0.0f || positions[count-1] != 1.0f)))
1182         return InvalidParameter;
1183 
1184     new_blendfac = GdipAlloc(count * sizeof(REAL));
1185     new_blendpos = GdipAlloc(count * sizeof(REAL));
1186 
1187     if (!new_blendfac || !new_blendpos)
1188     {
1189         GdipFree(new_blendfac);
1190         GdipFree(new_blendpos);
1191         return OutOfMemory;
1192     }
1193 
1194     memcpy(new_blendfac, factors, count * sizeof(REAL));
1195     memcpy(new_blendpos, positions, count * sizeof(REAL));
1196 
1197     GdipFree(brush->blendfac);
1198     GdipFree(brush->blendpos);
1199 
1200     brush->blendcount = count;
1201     brush->blendfac = new_blendfac;
1202     brush->blendpos = new_blendpos;
1203 
1204     return Ok;
1205 }
1206 
1207 GpStatus WINGDIPAPI GdipGetLineBlend(GpLineGradient *brush, REAL *factors,
1208     REAL *positions, INT count)
1209 {
1210     TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
1211 
1212     if (!brush || !factors || !positions || count <= 0)
1213         return InvalidParameter;
1214 
1215     if (count < brush->blendcount)
1216         return InsufficientBuffer;
1217 
1218     memcpy(factors, brush->blendfac, brush->blendcount * sizeof(REAL));
1219     memcpy(positions, brush->blendpos, brush->blendcount * sizeof(REAL));
1220 
1221     return Ok;
1222 }
1223 
1224 GpStatus WINGDIPAPI GdipGetLineBlendCount(GpLineGradient *brush, INT *count)
1225 {
1226     TRACE("(%p, %p)\n", brush, count);
1227 
1228     if (!brush || !count)
1229         return InvalidParameter;
1230 
1231     *count = brush->blendcount;
1232 
1233     return Ok;
1234 }
1235 
1236 GpStatus WINGDIPAPI GdipSetLineGammaCorrection(GpLineGradient *line,
1237     BOOL usegamma)
1238 {
1239     TRACE("(%p, %d)\n", line, usegamma);
1240 
1241     if(!line)
1242         return InvalidParameter;
1243 
1244     line->gamma = usegamma;
1245 
1246     return Ok;
1247 }
1248 
1249 GpStatus WINGDIPAPI GdipSetLineSigmaBlend(GpLineGradient *line, REAL focus,
1250     REAL scale)
1251 {
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;
1260 
1261     TRACE("(%p, %0.2f, %0.2f)\n", line, focus, scale);
1262 
1263     if(!line || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
1264         return InvalidParameter;
1265 
1266     /* we want 2 standard deviations */
1267     erf_range = 2.0 / sqrt(2);
1268 
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);
1273 
1274     if (focus != 0.0)
1275     {
1276         positions[0] = 0.0;
1277         factors[0] = 0.0;
1278         for (i=1; i<precision; i++)
1279         {
1280             positions[i] = focus * i / precision;
1281             factors[i] = scale_erf * (erf(2 * erf_range * i / precision - erf_range) - min_erf);
1282         }
1283         num_points += precision;
1284     }
1285 
1286     positions[num_points] = focus;
1287     factors[num_points] = scale;
1288     num_points += 1;
1289 
1290     if (focus != 1.0)
1291     {
1292         for (i=1; i<precision; i++)
1293         {
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);
1296         }
1297         num_points += precision;
1298         positions[num_points-1] = 1.0;
1299         factors[num_points-1] = 0.0;
1300     }
1301 
1302     return GdipSetLineBlend(line, factors, positions, num_points);
1303 }
1304 
1305 GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient *line,
1306     GpWrapMode wrap)
1307 {
1308     TRACE("(%p, %d)\n", line, wrap);
1309 
1310     if(!line || wrap == WrapModeClamp)
1311         return InvalidParameter;
1312 
1313     line->wrap = wrap;
1314 
1315     return Ok;
1316 }
1317 
1318 GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, GDIPCONST REAL *blend,
1319     GDIPCONST REAL *pos, INT count)
1320 {
1321     static int calls;
1322 
1323     if(!(calls++))
1324         FIXME("not implemented\n");
1325 
1326     return NotImplemented;
1327 }
1328 
1329 GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush,
1330     GDIPCONST ARGB *blend, GDIPCONST REAL *pos, INT count)
1331 {
1332     FIXME("(%p,%p,%p,%i): stub\n", brush, blend, pos, count);
1333     return NotImplemented;
1334 }
1335 
1336 GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
1337     ARGB argb)
1338 {
1339     TRACE("(%p, %x)\n", grad, argb);
1340 
1341     if(!grad)
1342         return InvalidParameter;
1343 
1344     grad->centercolor = argb;
1345     grad->brush.lb.lbColor = ARGB2COLORREF(argb);
1346 
1347     DeleteObject(grad->brush.gdibrush);
1348     grad->brush.gdibrush = CreateSolidBrush(grad->brush.lb.lbColor);
1349 
1350     return Ok;
1351 }
1352 
1353 GpStatus WINGDIPAPI GdipSetPathGradientCenterPoint(GpPathGradient *grad,
1354     GpPointF *point)
1355 {
1356     TRACE("(%p, %p)\n", grad, point);
1357 
1358     if(!grad || !point)
1359         return InvalidParameter;
1360 
1361     grad->center.X = point->X;
1362     grad->center.Y = point->Y;
1363 
1364     return Ok;
1365 }
1366 
1367 GpStatus WINGDIPAPI GdipSetPathGradientCenterPointI(GpPathGradient *grad,
1368     GpPoint *point)
1369 {
1370     GpPointF ptf;
1371 
1372     TRACE("(%p, %p)\n", grad, point);
1373 
1374     if(!point)
1375         return InvalidParameter;
1376 
1377     ptf.X = (REAL)point->X;
1378     ptf.Y = (REAL)point->Y;
1379 
1380     return GdipSetPathGradientCenterPoint(grad,&ptf);
1381 }
1382 
1383 GpStatus WINGDIPAPI GdipSetPathGradientFocusScales(GpPathGradient *grad,
1384     REAL x, REAL y)
1385 {
1386     TRACE("(%p, %.2f, %.2f)\n", grad, x, y);
1387 
1388     if(!grad)
1389         return InvalidParameter;
1390 
1391     grad->focus.X = x;
1392     grad->focus.Y = y;
1393 
1394     return Ok;
1395 }
1396 
1397 GpStatus WINGDIPAPI GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
1398     BOOL gamma)
1399 {
1400     TRACE("(%p, %d)\n", grad, gamma);
1401 
1402     if(!grad)
1403         return InvalidParameter;
1404 
1405     grad->gamma = gamma;
1406 
1407     return Ok;
1408 }
1409 
1410 GpStatus WINGDIPAPI GdipSetPathGradientSigmaBlend(GpPathGradient *grad,
1411     REAL focus, REAL scale)
1412 {
1413     static int calls;
1414 
1415     if(!grad || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
1416         return InvalidParameter;
1417 
1418     if(!(calls++))
1419         FIXME("not implemented\n");
1420 
1421     return NotImplemented;
1422 }
1423 
1424 GpStatus WINGDIPAPI GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
1425     *grad, ARGB *argb, INT *count)
1426 {
1427     static int calls;
1428 
1429     if(!grad || !argb || !count || (*count <= 0) ||
1430         (*count > grad->pathdata.Count))
1431         return InvalidParameter;
1432 
1433     if(!(calls++))
1434         FIXME("not implemented\n");
1435 
1436     return NotImplemented;
1437 }
1438 
1439 GpStatus WINGDIPAPI GdipSetPathGradientWrapMode(GpPathGradient *grad,
1440     GpWrapMode wrap)
1441 {
1442     TRACE("(%p, %d)\n", grad, wrap);
1443 
1444     if(!grad)
1445         return InvalidParameter;
1446 
1447     grad->wrap = wrap;
1448 
1449     return Ok;
1450 }
1451 
1452 GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
1453 {
1454     TRACE("(%p, %x)\n", sf, argb);
1455 
1456     if(!sf)
1457         return InvalidParameter;
1458 
1459     sf->color = argb;
1460     sf->brush.lb.lbColor = ARGB2COLORREF(argb);
1461 
1462     DeleteObject(sf->brush.gdibrush);
1463     sf->brush.gdibrush = CreateSolidBrush(sf->brush.lb.lbColor);
1464 
1465     return Ok;
1466 }
1467 
1468 /******************************************************************************
1469  * GdipSetTextureTransform [GDIPLUS.@]
1470  */
1471 GpStatus WINGDIPAPI GdipSetTextureTransform(GpTexture *texture,
1472     GDIPCONST GpMatrix *matrix)
1473 {
1474     TRACE("(%p, %p)\n", texture, matrix);
1475 
1476     if(!texture || !matrix)
1477         return InvalidParameter;
1478 
1479     memcpy(texture->transform, matrix, sizeof(GpMatrix));
1480 
1481     return Ok;
1482 }
1483 
1484 /******************************************************************************
1485  * GdipSetTextureWrapMode [GDIPLUS.@]
1486  *
1487  * WrapMode not used, only stored
1488  */
1489 GpStatus WINGDIPAPI GdipSetTextureWrapMode(GpTexture *brush, GpWrapMode wrapmode)
1490 {
1491     TRACE("(%p, %d)\n", brush, wrapmode);
1492 
1493     if(!brush)
1494         return InvalidParameter;
1495 
1496     brush->wrap = wrapmode;
1497 
1498     return Ok;
1499 }
1500 
1501 GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient *brush, ARGB color1,
1502     ARGB color2)
1503 {
1504     TRACE("(%p, %x, %x)\n", brush, color1, color2);
1505 
1506     if(!brush)
1507         return InvalidParameter;
1508 
1509     brush->startcolor = color1;
1510     brush->endcolor   = color2;
1511 
1512     return Ok;
1513 }
1514 
1515 GpStatus WINGDIPAPI GdipGetLineColors(GpLineGradient *brush, ARGB *colors)
1516 {
1517     TRACE("(%p, %p)\n", brush, colors);
1518 
1519     if(!brush || !colors)
1520         return InvalidParameter;
1521 
1522     colors[0] = brush->startcolor;
1523     colors[1] = brush->endcolor;
1524 
1525     return Ok;
1526 }
1527 
1528 /******************************************************************************
1529  * GdipRotateTextureTransform [GDIPLUS.@]
1530  */
1531 GpStatus WINGDIPAPI GdipRotateTextureTransform(GpTexture* brush, REAL angle,
1532     GpMatrixOrder order)
1533 {
1534     TRACE("(%p, %.2f, %d)\n", brush, angle, order);
1535 
1536     if(!brush)
1537         return InvalidParameter;
1538 
1539     return GdipRotateMatrix(brush->transform, angle, order);
1540 }
1541 
1542 GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus,
1543     REAL scale)
1544 {
1545     REAL factors[3];
1546     REAL positions[3];
1547     int num_points = 0;
1548 
1549     TRACE("(%p,%.2f,%.2f)\n", brush, focus, scale);
1550 
1551     if (!brush) return InvalidParameter;
1552 
1553     if (focus != 0.0)
1554     {
1555         factors[num_points] = 0.0;
1556         positions[num_points] = 0.0;
1557         num_points++;
1558     }
1559 
1560     factors[num_points] = scale;
1561     positions[num_points] = focus;
1562     num_points++;
1563 
1564     if (focus != 1.0)
1565     {
1566         factors[num_points] = 0.0;
1567         positions[num_points] = 1.0;
1568         num_points++;
1569     }
1570 
1571     return GdipSetLineBlend(brush, factors, positions, num_points);
1572 }
1573 
1574 GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient *brush,
1575     GDIPCONST ARGB *blend, GDIPCONST REAL* positions, INT count)
1576 {
1577     static int calls;
1578 
1579     if(!(calls++))
1580         FIXME("not implemented\n");
1581 
1582     return NotImplemented;
1583 }
1584 
1585 GpStatus WINGDIPAPI GdipSetLineTransform(GpLineGradient *brush,
1586     GDIPCONST GpMatrix *matrix)
1587 {
1588     static int calls;
1589 
1590     if(!(calls++))
1591         FIXME("not implemented\n");
1592 
1593     return NotImplemented;
1594 }
1595 
1596 GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient* brush,
1597         REAL dx, REAL dy, GpMatrixOrder order)
1598 {
1599     FIXME("stub: %p %f %f %d\n", brush, dx, dy, order);
1600 
1601     return NotImplemented;
1602 }
1603 
1604 /******************************************************************************
1605  * GdipTranslateTextureTransform [GDIPLUS.@]
1606  */
1607 GpStatus WINGDIPAPI GdipTranslateTextureTransform(GpTexture* brush, REAL dx, REAL dy,
1608     GpMatrixOrder order)
1609 {
1610     TRACE("(%p, %.2f, %.2f, %d)\n", brush, dx, dy, order);
1611 
1612     if(!brush)
1613         return InvalidParameter;
1614 
1615     return GdipTranslateMatrix(brush->transform, dx, dy, order);
1616 }
1617 
1618 GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
1619 {
1620     TRACE("(%p, %p)\n", brush, rect);
1621 
1622     if(!brush || !rect)
1623         return InvalidParameter;
1624 
1625     *rect = brush->rect;
1626 
1627     return Ok;
1628 }
1629 
1630 GpStatus WINGDIPAPI GdipGetLineRectI(GpLineGradient *brush, GpRect *rect)
1631 {
1632     GpRectF  rectF;
1633     GpStatus ret;
1634 
1635     TRACE("(%p, %p)\n", brush, rect);
1636 
1637     if(!rect)
1638         return InvalidParameter;
1639 
1640     ret = GdipGetLineRect(brush, &rectF);
1641 
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);
1647     }
1648 
1649     return ret;
1650 }
1651 
1652 GpStatus WINGDIPAPI GdipRotateLineTransform(GpLineGradient* brush,
1653     REAL angle, GpMatrixOrder order)
1654 {
1655     static int calls;
1656 
1657     if(!brush)
1658         return InvalidParameter;
1659 
1660     if(!(calls++))
1661         FIXME("(%p, %.2f, %d) stub\n", brush, angle, order);
1662 
1663     return NotImplemented;
1664 }
1665 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.