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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.