ReactOS 0.4.15-dev-7788-g1ad9096
graphics.c
Go to the documentation of this file.
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#include <math.h>
21#include <limits.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "winuser.h"
26#include "wingdi.h"
27#include "wine/unicode.h"
28
29#define COBJMACROS
30#include "objbase.h"
31#include "ocidl.h"
32#include "olectl.h"
33#include "ole2.h"
34
35#include "winreg.h"
36#include "shlwapi.h"
37
38#include "gdiplus.h"
39#include "gdiplus_private.h"
40#include "wine/debug.h"
41#include "wine/list.h"
42
44
45/* Mike "tamlin" Nordell 2012-09-14 for ReactOS:
46 * NOTE: Wine uses per-GpGraphics id's ('contid' starting from zero in
47 * every GpGraphics). Windows seems to use process-global id's, or at
48 * least more unique id's.
49 * This have the following implications. It:
50 * 1. fails the current gdiplus test case.
51 * 2. is not what Windows does.
52 *
53 * We therefore "obfuscate" the 'contid' a little to more match Windows'
54 * behaviour. The observable behviour should still remain the same,
55 * except for handing out more "unique" id's.
56 */
57#define GDIP_CONTID_STEP 64
59#define GDIP_GET_NEW_CONTID_FOR(pGpGraphics) \
60 (UINT)(InterlockedExchangeAdd(&g_priv_contid,GDIP_CONTID_STEP))
61
62
63/* ReactOS FIXME: Inspect */
64#define fmax max
65
66/* looks-right constants */
67#define ANCHOR_WIDTH (2.0)
68#define MAX_ITERS (50)
69
72 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
74
75/* Converts from gdiplus path point type to gdi path point type. */
77{
78 BYTE ret;
79
83 break;
85 ret = PT_LINETO;
86 break;
88 ret = PT_MOVETO;
89 break;
90 default:
91 ERR("Bad point type\n");
92 return 0;
93 }
94
97
98 return ret;
99}
100
102{
103 ARGB argb;
104
105 switch (brush->bt)
106 {
108 {
109 const GpSolidFill *sf = (const GpSolidFill *)brush;
110 argb = sf->color;
111 break;
112 }
114 {
115 const GpHatch *hatch = (const GpHatch *)brush;
116 argb = hatch->forecol;
117 break;
118 }
120 {
121 const GpLineGradient *line = (const GpLineGradient *)brush;
122 argb = line->startcolor;
123 break;
124 }
126 {
127 const GpPathGradient *grad = (const GpPathGradient *)brush;
128 argb = grad->centercolor;
129 break;
130 }
131 default:
132 FIXME("unhandled brush type %d\n", brush->bt);
133 argb = 0;
134 break;
135 }
136 return ARGB2COLORREF(argb);
137}
138
140{
142 BITMAPINFOHEADER bmih;
143 DWORD *bits;
144 int x, y;
145
146 bmih.biSize = sizeof(bmih);
147 bmih.biWidth = 8;
148 bmih.biHeight = 8;
149 bmih.biPlanes = 1;
150 bmih.biBitCount = 32;
151 bmih.biCompression = BI_RGB;
152 bmih.biSizeImage = 0;
153
154 hbmp = CreateDIBSection(0, (BITMAPINFO *)&bmih, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
155 if (hbmp)
156 {
157 const char *hatch_data;
158
159 if (get_hatch_data(hatch->hatchstyle, &hatch_data) == Ok)
160 {
161 for (y = 0; y < 8; y++)
162 {
163 for (x = 0; x < 8; x++)
164 {
165 if (hatch_data[y] & (0x80 >> x))
166 bits[y * 8 + x] = hatch->forecol;
167 else
168 bits[y * 8 + x] = hatch->backcol;
169 }
170 }
171 }
172 else
173 {
174 FIXME("Unimplemented hatch style %d\n", hatch->hatchstyle);
175
176 for (y = 0; y < 64; y++)
177 bits[y] = hatch->forecol;
178 }
179 }
180
181 return hbmp;
182}
183
185{
186 switch (brush->bt)
187 {
189 {
190 const GpSolidFill *sf = (const GpSolidFill *)brush;
191 lb->lbStyle = BS_SOLID;
192 lb->lbColor = ARGB2COLORREF(sf->color);
193 lb->lbHatch = 0;
194 return Ok;
195 }
196
198 {
199 const GpHatch *hatch = (const GpHatch *)brush;
201
202 hbmp = create_hatch_bitmap(hatch);
203 if (!hbmp) return OutOfMemory;
204
205 lb->lbStyle = BS_PATTERN;
206 lb->lbColor = 0;
207 lb->lbHatch = (ULONG_PTR)hbmp;
208 return Ok;
209 }
210
211 default:
212 FIXME("unhandled brush type %d\n", brush->bt);
213 lb->lbStyle = BS_SOLID;
214 lb->lbColor = get_gdi_brush_color(brush);
215 lb->lbHatch = 0;
216 return Ok;
217 }
218}
219
221{
222 switch (lb->lbStyle)
223 {
224 case BS_PATTERN:
226 break;
227 }
228 return Ok;
229}
230
231static HBRUSH create_gdi_brush(const GpBrush *brush)
232{
233 LOGBRUSH lb;
234 HBRUSH gdibrush;
235
236 if (create_gdi_logbrush(brush, &lb) != Ok) return 0;
237
238 gdibrush = CreateBrushIndirect(&lb);
240
241 return gdibrush;
242}
243
244static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
245{
246 LOGBRUSH lb;
247 HPEN gdipen;
248 REAL width;
249 INT save_state, i, numdashes;
250 GpPointF pt[2];
251 DWORD dash_array[MAX_DASHLEN];
252
253 save_state = SaveDC(graphics->hdc);
254
255 EndPath(graphics->hdc);
256
257 if(pen->unit == UnitPixel){
258 width = pen->width;
259 }
260 else{
261 /* Get an estimate for the amount the pen width is affected by the world
262 * transform. (This is similar to what some of the wine drivers do.) */
263 pt[0].X = 0.0;
264 pt[0].Y = 0.0;
265 pt[1].X = 1.0;
266 pt[1].Y = 1.0;
268 width = sqrt((pt[1].X - pt[0].X) * (pt[1].X - pt[0].X) +
269 (pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0);
270
271 width *= units_to_pixels(pen->width, pen->unit == UnitWorld ? graphics->unit : pen->unit, graphics->xres);
272 width *= graphics->scale;
273
274 pt[0].X = 0.0;
275 pt[0].Y = 0.0;
276 pt[1].X = 1.0;
277 pt[1].Y = 1.0;
279 width *= sqrt((pt[1].X - pt[0].X) * (pt[1].X - pt[0].X) +
280 (pt[1].Y - pt[0].Y) * (pt[1].Y - pt[0].Y)) / sqrt(2.0);
281 }
282
283 if(pen->dash == DashStyleCustom){
284 numdashes = min(pen->numdashes, MAX_DASHLEN);
285
286 TRACE("dashes are: ");
287 for(i = 0; i < numdashes; i++){
288 dash_array[i] = gdip_round(width * pen->dashes[i]);
289 TRACE("%d, ", dash_array[i]);
290 }
291 TRACE("\n and the pen style is %x\n", pen->style);
292
293 create_gdi_logbrush(pen->brush, &lb);
294 gdipen = ExtCreatePen(pen->style, gdip_round(width), &lb,
295 numdashes, dash_array);
297 }
298 else
299 {
300 create_gdi_logbrush(pen->brush, &lb);
301 gdipen = ExtCreatePen(pen->style, gdip_round(width), &lb, 0, NULL);
303 }
304
305 SelectObject(graphics->hdc, gdipen);
306
307 return save_state;
308}
309
310static void restore_dc(GpGraphics *graphics, INT state)
311{
313 RestoreDC(graphics->hdc, state);
314}
315
316static void round_points(POINT *pti, GpPointF *ptf, INT count)
317{
318 int i;
319
320 for(i = 0; i < count; i++){
321 pti[i].x = gdip_round(ptf[i].X);
322 pti[i].y = gdip_round(ptf[i].Y);
323 }
324}
325
326static void gdi_alpha_blend(GpGraphics *graphics, INT dst_x, INT dst_y, INT dst_width, INT dst_height,
327 HDC hdc, INT src_x, INT src_y, INT src_width, INT src_height)
328{
329 if (GetDeviceCaps(graphics->hdc, TECHNOLOGY) == DT_RASPRINTER &&
330 GetDeviceCaps(graphics->hdc, SHADEBLENDCAPS) == SB_NONE)
331 {
332 TRACE("alpha blending not supported by device, fallback to StretchBlt\n");
333
334 StretchBlt(graphics->hdc, dst_x, dst_y, dst_width, dst_height,
335 hdc, src_x, src_y, src_width, src_height, SRCCOPY);
336 }
337 else
338 {
339 BLENDFUNCTION bf;
340
341 bf.BlendOp = AC_SRC_OVER;
342 bf.BlendFlags = 0;
343 bf.SourceConstantAlpha = 255;
345
346 GdiAlphaBlend(graphics->hdc, dst_x, dst_y, dst_width, dst_height,
347 hdc, src_x, src_y, src_width, src_height, bf);
348 }
349}
350
351static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
352{
353 GpRegion *rgn;
357
359
360 if (stat == Ok)
362
363 if (stat == Ok)
364 stat = GdipCloneRegion(graphics->clip, &rgn);
365
366 if (stat == Ok)
367 {
368 if (!identity)
370
371 if (stat == Ok)
373
374 GdipDeleteRegion(rgn);
375 }
376
377 if (stat == Ok && graphics->gdi_clip)
378 {
379 if (*hrgn)
380 CombineRgn(*hrgn, *hrgn, graphics->gdi_clip, RGN_AND);
381 else
382 {
383 *hrgn = CreateRectRgn(0,0,0,0);
384 CombineRgn(*hrgn, graphics->gdi_clip, graphics->gdi_clip, RGN_COPY);
385 }
386 }
387
388 return stat;
389}
390
391/* Draw ARGB data to the given graphics object */
392static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
393 const BYTE *src, INT src_width, INT src_height, INT src_stride, const PixelFormat fmt)
394{
395 GpBitmap *dst_bitmap = (GpBitmap*)graphics->image;
396 INT x, y;
397
398 for (y=0; y<src_height; y++)
399 {
400 for (x=0; x<src_width; x++)
401 {
402 ARGB dst_color, src_color;
403 src_color = ((ARGB*)(src + src_stride * y))[x];
404
405 if (!(src_color & 0xff000000))
406 continue;
407
408 GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color);
410 GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over_fgpremult(dst_color, src_color));
411 else
412 GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color));
413 }
414 }
415
416 return Ok;
417}
418
419static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
420 const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
421{
422 HDC hdc;
425 BYTE *temp_bits;
426
428
429 bih.biSize = sizeof(BITMAPINFOHEADER);
430 bih.biWidth = src_width;
431 bih.biHeight = -src_height;
432 bih.biPlanes = 1;
433 bih.biBitCount = 32;
434 bih.biCompression = BI_RGB;
435 bih.biSizeImage = 0;
436 bih.biXPelsPerMeter = 0;
437 bih.biYPelsPerMeter = 0;
438 bih.biClrUsed = 0;
439 bih.biClrImportant = 0;
440
442 (void**)&temp_bits, NULL, 0);
443
444 if ((GetDeviceCaps(graphics->hdc, TECHNOLOGY) == DT_RASPRINTER &&
445 GetDeviceCaps(graphics->hdc, SHADEBLENDCAPS) == SB_NONE) ||
447 memcpy(temp_bits, src, src_width * src_height * 4);
448 else
449 convert_32bppARGB_to_32bppPARGB(src_width, src_height, temp_bits,
450 4 * src_width, src, src_stride);
451
453 gdi_alpha_blend(graphics, dst_x, dst_y, src_width, src_height,
454 hdc, 0, 0, src_width, src_height);
455 DeleteDC(hdc);
457
458 return Ok;
459}
460
461static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst_y,
462 const BYTE *src, INT src_width, INT src_height, INT src_stride, HRGN hregion, PixelFormat fmt)
463{
465
466 if (graphics->image && graphics->image->type == ImageTypeBitmap)
467 {
468 DWORD i;
469 int size;
470 RGNDATA *rgndata;
471 RECT *rects;
472 HRGN hrgn, visible_rgn;
473
474 hrgn = CreateRectRgn(dst_x, dst_y, dst_x + src_width, dst_y + src_height);
475 if (!hrgn)
476 return OutOfMemory;
477
478 stat = get_clip_hrgn(graphics, &visible_rgn);
479 if (stat != Ok)
480 {
482 return stat;
483 }
484
485 if (visible_rgn)
486 {
487 CombineRgn(hrgn, hrgn, visible_rgn, RGN_AND);
488 DeleteObject(visible_rgn);
489 }
490
491 if (hregion)
492 CombineRgn(hrgn, hrgn, hregion, RGN_AND);
493
495
496 rgndata = heap_alloc_zero(size);
497 if (!rgndata)
498 {
500 return OutOfMemory;
501 }
502
503 GetRegionData(hrgn, size, rgndata);
504
505 rects = (RECT*)rgndata->Buffer;
506
507 for (i=0; stat == Ok && i<rgndata->rdh.nCount; i++)
508 {
509 stat = alpha_blend_bmp_pixels(graphics, rects[i].left, rects[i].top,
510 &src[(rects[i].left - dst_x) * 4 + (rects[i].top - dst_y) * src_stride],
511 rects[i].right - rects[i].left, rects[i].bottom - rects[i].top,
512 src_stride, fmt);
513 }
514
515 heap_free(rgndata);
516
518
519 return stat;
520 }
521 else if (graphics->image && graphics->image->type == ImageTypeMetafile)
522 {
523 ERR("This should not be used for metafiles; fix caller\n");
524 return NotImplemented;
525 }
526 else
527 {
528 HRGN hrgn;
529 int save;
530
531 stat = get_clip_hrgn(graphics, &hrgn);
532
533 if (stat != Ok)
534 return stat;
535
536 save = SaveDC(graphics->hdc);
537
538 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
539
540 if (hregion)
541 ExtSelectClipRgn(graphics->hdc, hregion, RGN_AND);
542
543 stat = alpha_blend_hdc_pixels(graphics, dst_x, dst_y, src, src_width,
544 src_height, src_stride, fmt);
545
546 RestoreDC(graphics->hdc, save);
547
549
550 return stat;
551 }
552}
553
554static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
555 const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
556{
557 return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt);
558}
559
560/* NOTE: start and end pixels must be in pre-multiplied ARGB format */
561static inline ARGB blend_colors_premult(ARGB start, ARGB end, REAL position)
562{
563 UINT pos = position * 255.0f + 0.5f;
564 return
565 (((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 |
566 (((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 |
567 (((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 |
568 (((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8);
569}
570
572{
573 INT start_a, end_a, final_a;
574 INT pos;
575
576 pos = (INT)(position * 255.0f + 0.5f);
577
578 start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
579 end_a = ((end >> 24) & 0xff) * pos;
580
581 final_a = start_a + end_a;
582
583 if (final_a < 0xff) return 0;
584
585 return (final_a / 0xff) << 24 |
586 ((((start >> 16) & 0xff) * start_a + (((end >> 16) & 0xff) * end_a)) / final_a) << 16 |
587 ((((start >> 8) & 0xff) * start_a + (((end >> 8) & 0xff) * end_a)) / final_a) << 8 |
588 (((start & 0xff) * start_a + ((end & 0xff) * end_a)) / final_a);
589}
590
592{
593 REAL blendfac;
594
595 /* clamp to between 0.0 and 1.0, using the wrap mode */
596 position = (position - brush->rect.X) / brush->rect.Width;
597 if (brush->wrap == WrapModeTile)
598 {
599 position = fmodf(position, 1.0f);
600 if (position < 0.0f) position += 1.0f;
601 }
602 else /* WrapModeFlip* */
603 {
604 position = fmodf(position, 2.0f);
605 if (position < 0.0f) position += 2.0f;
606 if (position > 1.0f) position = 2.0f - position;
607 }
608
609 if (brush->blendcount == 1)
610 blendfac = position;
611 else
612 {
613 int i=1;
614 REAL left_blendpos, left_blendfac, right_blendpos, right_blendfac;
615 REAL range;
616
617 /* locate the blend positions surrounding this position */
618 while (position > brush->blendpos[i])
619 i++;
620
621 /* interpolate between the blend positions */
622 left_blendpos = brush->blendpos[i-1];
623 left_blendfac = brush->blendfac[i-1];
624 right_blendpos = brush->blendpos[i];
625 right_blendfac = brush->blendfac[i];
626 range = right_blendpos - left_blendpos;
627 blendfac = (left_blendfac * (right_blendpos - position) +
628 right_blendfac * (position - left_blendpos)) / range;
629 }
630
631 if (brush->pblendcount == 0)
632 return blend_colors(brush->startcolor, brush->endcolor, blendfac);
633 else
634 {
635 int i=1;
636 ARGB left_blendcolor, right_blendcolor;
637 REAL left_blendpos, right_blendpos;
638
639 /* locate the blend colors surrounding this position */
640 while (blendfac > brush->pblendpos[i])
641 i++;
642
643 /* interpolate between the blend colors */
644 left_blendpos = brush->pblendpos[i-1];
645 left_blendcolor = brush->pblendcolor[i-1];
646 right_blendpos = brush->pblendpos[i];
647 right_blendcolor = brush->pblendcolor[i];
648 blendfac = (blendfac - left_blendpos) / (right_blendpos - left_blendpos);
649 return blend_colors(left_blendcolor, right_blendcolor, blendfac);
650 }
651}
652
654{
655 /* Convert floating point color matrix to int[5][5], return TRUE if it's an identity */
657 int i, j;
658
659 for (i=0; i<4; i++)
660 for (j=0; j<5; j++)
661 {
662 if (matrix->m[j][i] != (i == j ? 1.0 : 0.0))
663 identity = FALSE;
664 values[j][i] = gdip_round(matrix->m[j][i] * 256.0);
665 }
666
667 return identity;
668}
669
671{
672 int val[5], res[4];
673 int i, j;
674 unsigned char a, r, g, b;
675
676 val[0] = ((color >> 16) & 0xff); /* red */
677 val[1] = ((color >> 8) & 0xff); /* green */
678 val[2] = (color & 0xff); /* blue */
679 val[3] = ((color >> 24) & 0xff); /* alpha */
680 val[4] = 255; /* translation */
681
682 for (i=0; i<4; i++)
683 {
684 res[i] = 0;
685
686 for (j=0; j<5; j++)
687 res[i] += matrix[j][i] * val[j];
688 }
689
690 a = min(max(res[3] / 256, 0), 255);
691 r = min(max(res[0] / 256, 0), 255);
692 g = min(max(res[1] / 256, 0), 255);
693 b = min(max(res[2] / 256, 0), 255);
694
695 return (a << 24) | (r << 16) | (g << 8) | b;
696}
697
699{
700 unsigned char r, g, b;
701
702 r = (color >> 16) & 0xff;
703 g = (color >> 8) & 0xff;
704 b = color & 0xff;
705
706 return (r == g) && (g == b);
707}
708
709/* returns preferred pixel format for the applied attributes */
712{
713 UINT x, y;
714 INT i;
715
716 if ((attributes->noop[type] == IMAGEATTR_NOOP_UNDEFINED &&
718 (attributes->noop[type] == IMAGEATTR_NOOP_SET))
719 return fmt;
720
721 if (attributes->colorkeys[type].enabled ||
722 attributes->colorkeys[ColorAdjustTypeDefault].enabled)
723 {
724 const struct color_key *key;
725 BYTE min_blue, min_green, min_red;
726 BYTE max_blue, max_green, max_red;
727
728 if (!data || fmt != PixelFormat32bppARGB)
730
731 if (attributes->colorkeys[type].enabled)
732 key = &attributes->colorkeys[type];
733 else
734 key = &attributes->colorkeys[ColorAdjustTypeDefault];
735
736 min_blue = key->low&0xff;
737 min_green = (key->low>>8)&0xff;
738 min_red = (key->low>>16)&0xff;
739
740 max_blue = key->high&0xff;
741 max_green = (key->high>>8)&0xff;
742 max_red = (key->high>>16)&0xff;
743
744 for (x=0; x<width; x++)
745 for (y=0; y<height; y++)
746 {
747 ARGB *src_color;
748 BYTE blue, green, red;
749 src_color = (ARGB*)(data + stride * y + sizeof(ARGB) * x);
750 blue = *src_color&0xff;
751 green = (*src_color>>8)&0xff;
752 red = (*src_color>>16)&0xff;
753 if (blue >= min_blue && green >= min_green && red >= min_red &&
754 blue <= max_blue && green <= max_green && red <= max_red)
755 *src_color = 0x00000000;
756 }
757 }
758
759 if (attributes->colorremaptables[type].enabled ||
760 attributes->colorremaptables[ColorAdjustTypeDefault].enabled)
761 {
762 const struct color_remap_table *table;
763
764 if (!data || fmt != PixelFormat32bppARGB)
766
767 if (attributes->colorremaptables[type].enabled)
768 table = &attributes->colorremaptables[type];
769 else
771
772 for (x=0; x<width; x++)
773 for (y=0; y<height; y++)
774 {
775 ARGB *src_color;
776 src_color = (ARGB*)(data + stride * y + sizeof(ARGB) * x);
777 for (i=0; i<table->mapsize; i++)
778 {
779 if (*src_color == table->colormap[i].oldColor.Argb)
780 {
781 *src_color = table->colormap[i].newColor.Argb;
782 break;
783 }
784 }
785 }
786 }
787
788 if (attributes->colormatrices[type].enabled ||
789 attributes->colormatrices[ColorAdjustTypeDefault].enabled)
790 {
791 const struct color_matrix *colormatrices;
792 int color_matrix[5][5];
793 int gray_matrix[5][5];
795
796 if (!data || fmt != PixelFormat32bppARGB)
798
799 if (attributes->colormatrices[type].enabled)
800 colormatrices = &attributes->colormatrices[type];
801 else
802 colormatrices = &attributes->colormatrices[ColorAdjustTypeDefault];
803
805
806 if (colormatrices->flags == ColorMatrixFlagsAltGray)
807 identity = (round_color_matrix(&colormatrices->graymatrix, gray_matrix) && identity);
808
809 if (!identity)
810 {
811 for (x=0; x<width; x++)
812 {
813 for (y=0; y<height; y++)
814 {
815 ARGB *src_color;
816 src_color = (ARGB*)(data + stride * y + sizeof(ARGB) * x);
817
818 if (colormatrices->flags == ColorMatrixFlagsDefault ||
819 !color_is_gray(*src_color))
820 {
821 *src_color = transform_color(*src_color, color_matrix);
822 }
823 else if (colormatrices->flags == ColorMatrixFlagsAltGray)
824 {
825 *src_color = transform_color(*src_color, gray_matrix);
826 }
827 }
828 }
829 }
830 }
831
832 if (attributes->gamma_enabled[type] ||
834 {
835 REAL gamma;
836
837 if (!data || fmt != PixelFormat32bppARGB)
839
840 if (attributes->gamma_enabled[type])
841 gamma = attributes->gamma[type];
842 else
843 gamma = attributes->gamma[ColorAdjustTypeDefault];
844
845 for (x=0; x<width; x++)
846 for (y=0; y<height; y++)
847 {
848 ARGB *src_color;
849 BYTE blue, green, red;
850 src_color = (ARGB*)(data + stride * y + sizeof(ARGB) * x);
851
852 blue = *src_color&0xff;
853 green = (*src_color>>8)&0xff;
854 red = (*src_color>>16)&0xff;
855
856 /* FIXME: We should probably use a table for this. */
857 blue = floorf(powf(blue / 255.0, gamma) * 255.0);
858 green = floorf(powf(green / 255.0, gamma) * 255.0);
859 red = floorf(powf(red / 255.0, gamma) * 255.0);
860
861 *src_color = (*src_color & 0xff000000) | (red << 16) | (green << 8) | blue;
862 }
863 }
864
865 return fmt;
866}
867
868/* Given a bitmap and its source rectangle, find the smallest rectangle in the
869 * bitmap that contains all the pixels we may need to draw it. */
871 GpBitmap* bitmap, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight,
872 GpRect *rect)
873{
875
876 switch (interpolation)
877 {
880 /* FIXME: Include a greater range for the prefilter? */
883 left = (INT)(floorf(srcx));
884 top = (INT)(floorf(srcy));
885 right = (INT)(ceilf(srcx+srcwidth));
886 bottom = (INT)(ceilf(srcy+srcheight));
887 break;
889 default:
890 left = gdip_round(srcx);
891 top = gdip_round(srcy);
892 right = gdip_round(srcx+srcwidth);
893 bottom = gdip_round(srcy+srcheight);
894 break;
895 }
896
897 if (wrap == WrapModeClamp)
898 {
899 if (left < 0)
900 left = 0;
901 if (top < 0)
902 top = 0;
903 if (right >= bitmap->width)
904 right = bitmap->width-1;
905 if (bottom >= bitmap->height)
906 bottom = bitmap->height-1;
907 if (bottom < top || right < left)
908 /* entirely outside image, just sample a pixel so we don't have to
909 * special-case this later */
910 left = top = right = bottom = 0;
911 }
912 else
913 {
914 /* In some cases we can make the rectangle smaller here, but the logic
915 * is hard to get right, and tiling suggests we're likely to use the
916 * entire source image. */
917 if (left < 0 || right >= bitmap->width)
918 {
919 left = 0;
920 right = bitmap->width-1;
921 }
922
923 if (top < 0 || bottom >= bitmap->height)
924 {
925 top = 0;
926 bottom = bitmap->height-1;
927 }
928 }
929
930 rect->X = left;
931 rect->Y = top;
932 rect->Width = right - left + 1;
933 rect->Height = bottom - top + 1;
934}
935
938{
939 if (attributes->wrap == WrapModeClamp)
940 {
941 if (x < 0 || y < 0 || x >= width || y >= height)
942 return attributes->outside_color;
943 }
944 else
945 {
946 /* Tiling. Make sure co-ordinates are positive as it simplifies the math. */
947 if (x < 0)
948 x = width*2 + x % (width * 2);
949 if (y < 0)
950 y = height*2 + y % (height * 2);
951
952 if (attributes->wrap & WrapModeTileFlipX)
953 {
954 if ((x / width) % 2 == 0)
955 x = x % width;
956 else
957 x = width - 1 - x % width;
958 }
959 else
960 x = x % width;
961
962 if (attributes->wrap & WrapModeTileFlipY)
963 {
964 if ((y / height) % 2 == 0)
965 y = y % height;
966 else
967 y = height - 1 - y % height;
968 }
969 else
970 y = y % height;
971 }
972
973 if (x < src_rect->X || y < src_rect->Y || x >= src_rect->X + src_rect->Width || y >= src_rect->Y + src_rect->Height)
974 {
975 ERR("out of range pixel requested\n");
976 return 0xffcd0084;
977 }
978
979 return ((DWORD*)(bits))[(x - src_rect->X) + (y - src_rect->Y) * src_rect->Width];
980}
981
982static inline int positive_ceilf(float f)
983{
984 return f - (int)f > 0.0f ? f + 1.0f : f;
985}
986
989 InterpolationMode interpolation, PixelOffsetMode offset_mode)
990{
991 static int fixme;
992
993 switch (interpolation)
994 {
995 default:
996 if (!fixme++)
997 FIXME("Unimplemented interpolation %i\n", interpolation);
998 /* fall-through */
1000 {
1001 REAL leftxf, topyf;
1002 INT leftx, rightx, topy, bottomy;
1003 ARGB topleft, topright, bottomleft, bottomright;
1004 ARGB top, bottom;
1005 float x_offset;
1006
1007 leftx = (INT)point->X;
1008 leftxf = (REAL)leftx;
1009 rightx = positive_ceilf(point->X);
1010 topy = (INT)point->Y;
1011 topyf = (REAL)topy;
1012 bottomy = positive_ceilf(point->Y);
1013
1014 if (leftx == rightx && topy == bottomy)
1015 return sample_bitmap_pixel(src_rect, bits, width, height,
1016 leftx, topy, attributes);
1017
1018 topleft = sample_bitmap_pixel(src_rect, bits, width, height,
1019 leftx, topy, attributes);
1020 topright = sample_bitmap_pixel(src_rect, bits, width, height,
1021 rightx, topy, attributes);
1022 bottomleft = sample_bitmap_pixel(src_rect, bits, width, height,
1023 leftx, bottomy, attributes);
1024 bottomright = sample_bitmap_pixel(src_rect, bits, width, height,
1025 rightx, bottomy, attributes);
1026
1027 x_offset = point->X - leftxf;
1028 top = blend_colors(topleft, topright, x_offset);
1029 bottom = blend_colors(bottomleft, bottomright, x_offset);
1030
1031 return blend_colors(top, bottom, point->Y - topyf);
1032 }
1034 {
1035 FLOAT pixel_offset;
1036 switch (offset_mode)
1037 {
1038 default:
1041 pixel_offset = 0.5;
1042 break;
1043
1046 pixel_offset = 0.0;
1047 break;
1048 }
1049 return sample_bitmap_pixel(src_rect, bits, width, height,
1050 floorf(point->X + pixel_offset), floorf(point->Y + pixel_offset), attributes);
1051 }
1052
1053 }
1054}
1055
1058 InterpolationMode interpolation, PixelOffsetMode offset_mode)
1059{
1060 static int fixme;
1061
1062 switch (interpolation)
1063 {
1064 default:
1065 if (!fixme++)
1066 FIXME("Unimplemented interpolation %i\n", interpolation);
1067 /* fall-through */
1069 {
1070 REAL leftxf, topyf;
1071 INT leftx, rightx, topy, bottomy;
1072 ARGB topleft, topright, bottomleft, bottomright;
1073 ARGB top, bottom;
1074 float x_offset;
1075
1076 leftx = (INT)point->X;
1077 leftxf = (REAL)leftx;
1078 rightx = positive_ceilf(point->X);
1079 topy = (INT)point->Y;
1080 topyf = (REAL)topy;
1081 bottomy = positive_ceilf(point->Y);
1082
1083 if (leftx == rightx && topy == bottomy)
1084 return sample_bitmap_pixel(src_rect, bits, width, height,
1085 leftx, topy, attributes);
1086
1087 topleft = sample_bitmap_pixel(src_rect, bits, width, height,
1088 leftx, topy, attributes);
1089 topright = sample_bitmap_pixel(src_rect, bits, width, height,
1090 rightx, topy, attributes);
1091 bottomleft = sample_bitmap_pixel(src_rect, bits, width, height,
1092 leftx, bottomy, attributes);
1093 bottomright = sample_bitmap_pixel(src_rect, bits, width, height,
1094 rightx, bottomy, attributes);
1095
1096 x_offset = point->X - leftxf;
1097 top = blend_colors_premult(topleft, topright, x_offset);
1098 bottom = blend_colors_premult(bottomleft, bottomright, x_offset);
1099
1100 return blend_colors_premult(top, bottom, point->Y - topyf);
1101 }
1103 {
1104 FLOAT pixel_offset;
1105 switch (offset_mode)
1106 {
1107 default:
1110 pixel_offset = 0.5;
1111 break;
1112
1115 pixel_offset = 0.0;
1116 break;
1117 }
1118 return sample_bitmap_pixel(src_rect, bits, width, height,
1119 floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes);
1120 }
1121
1122 }
1123}
1124
1126{
1127 return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X;
1128}
1129
1130/* is_fill is TRUE if filling regions, FALSE for drawing primitives */
1131static BOOL brush_can_fill_path(GpBrush *brush, BOOL is_fill)
1132{
1133 switch (brush->bt)
1134 {
1136 {
1137 if (is_fill)
1138 return TRUE;
1139 else
1140 {
1141 /* cannot draw semi-transparent colors */
1142 return (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000;
1143 }
1144 }
1145 case BrushTypeHatchFill:
1146 {
1147 GpHatch *hatch = (GpHatch*)brush;
1148 return ((hatch->forecol & 0xff000000) == 0xff000000) &&
1149 ((hatch->backcol & 0xff000000) == 0xff000000);
1150 }
1153 /* Gdi32 isn't much help with these, so we should use brush_fill_pixels instead. */
1154 default:
1155 return FALSE;
1156 }
1157}
1158
1160{
1161 GpStatus status = Ok;
1162 switch (brush->bt)
1163 {
1165 {
1166 GpSolidFill *fill = (GpSolidFill*)brush;
1167 HBITMAP bmp = ARGB2BMP(fill->color);
1168
1169 if (bmp)
1170 {
1171 RECT rc;
1172 /* partially transparent fill */
1173
1174 if (!SelectClipPath(graphics->hdc, RGN_AND))
1175 {
1178 break;
1179 }
1180 if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
1181 {
1183
1184 if (!hdc)
1185 {
1188 break;
1189 }
1190
1192 gdi_alpha_blend(graphics, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
1193 hdc, 0, 0, 1, 1);
1194 DeleteDC(hdc);
1195 }
1196
1198 break;
1199 }
1200 /* else fall through */
1201 }
1202 default:
1203 {
1204 HBRUSH gdibrush, old_brush;
1205
1206 gdibrush = create_gdi_brush(brush);
1207 if (!gdibrush)
1208 {
1210 break;
1211 }
1212
1213 old_brush = SelectObject(graphics->hdc, gdibrush);
1214 FillPath(graphics->hdc);
1215 SelectObject(graphics->hdc, old_brush);
1216 DeleteObject(gdibrush);
1217 break;
1218 }
1219 }
1220
1221 return status;
1222}
1223
1225{
1226 switch (brush->bt)
1227 {
1229 case BrushTypeHatchFill:
1233 return TRUE;
1234 default:
1235 return FALSE;
1236 }
1237}
1238
1240 DWORD *argb_pixels, GpRect *fill_area, UINT cdwStride)
1241{
1242 switch (brush->bt)
1243 {
1245 {
1246 int x, y;
1247 GpSolidFill *fill = (GpSolidFill*)brush;
1248 for (x=0; x<fill_area->Width; x++)
1249 for (y=0; y<fill_area->Height; y++)
1250 argb_pixels[x + y*cdwStride] = fill->color;
1251 return Ok;
1252 }
1253 case BrushTypeHatchFill:
1254 {
1255 int x, y;
1256 GpHatch *fill = (GpHatch*)brush;
1257 const char *hatch_data;
1258
1259 if (get_hatch_data(fill->hatchstyle, &hatch_data) != Ok)
1260 return NotImplemented;
1261
1262 for (x=0; x<fill_area->Width; x++)
1263 for (y=0; y<fill_area->Height; y++)
1264 {
1265 int hx, hy;
1266
1267 /* FIXME: Account for the rendering origin */
1268 hx = (x + fill_area->X) % 8;
1269 hy = (y + fill_area->Y) % 8;
1270
1271 if ((hatch_data[7-hy] & (0x80 >> hx)) != 0)
1272 argb_pixels[x + y*cdwStride] = fill->forecol;
1273 else
1274 argb_pixels[x + y*cdwStride] = fill->backcol;
1275 }
1276
1277 return Ok;
1278 }
1280 {
1282 GpPointF draw_points[3];
1283 GpStatus stat;
1284 int x, y;
1285
1286 draw_points[0].X = fill_area->X;
1287 draw_points[0].Y = fill_area->Y;
1288 draw_points[1].X = fill_area->X+1;
1289 draw_points[1].Y = fill_area->Y;
1290 draw_points[2].X = fill_area->X;
1291 draw_points[2].Y = fill_area->Y+1;
1292
1293 /* Transform the points to a co-ordinate space where X is the point's
1294 * position in the gradient, 0.0 being the start point and 1.0 the
1295 * end point. */
1297 WineCoordinateSpaceGdiDevice, draw_points, 3);
1298
1299 if (stat == Ok)
1300 {
1301 GpMatrix world_to_gradient = fill->transform;
1302
1303 stat = GdipInvertMatrix(&world_to_gradient);
1304 if (stat == Ok)
1305 stat = GdipTransformMatrixPoints(&world_to_gradient, draw_points, 3);
1306 }
1307
1308 if (stat == Ok)
1309 {
1310 REAL x_delta = draw_points[1].X - draw_points[0].X;
1311 REAL y_delta = draw_points[2].X - draw_points[0].X;
1312
1313 for (y=0; y<fill_area->Height; y++)
1314 {
1315 for (x=0; x<fill_area->Width; x++)
1316 {
1317 REAL pos = draw_points[0].X + x * x_delta + y * y_delta;
1318
1319 argb_pixels[x + y*cdwStride] = blend_line_gradient(fill, pos);
1320 }
1321 }
1322 }
1323
1324 return stat;
1325 }
1327 {
1328 GpTexture *fill = (GpTexture*)brush;
1329 GpPointF draw_points[3];
1330 GpStatus stat;
1331 int x, y;
1333 int src_stride;
1334 GpRect src_area;
1335
1336 if (fill->image->type != ImageTypeBitmap)
1337 {
1338 FIXME("metafile texture brushes not implemented\n");
1339 return NotImplemented;
1340 }
1341
1342 bitmap = (GpBitmap*)fill->image;
1343 src_stride = sizeof(ARGB) * bitmap->width;
1344
1345 src_area.X = src_area.Y = 0;
1346 src_area.Width = bitmap->width;
1347 src_area.Height = bitmap->height;
1348
1349 draw_points[0].X = fill_area->X;
1350 draw_points[0].Y = fill_area->Y;
1351 draw_points[1].X = fill_area->X+1;
1352 draw_points[1].Y = fill_area->Y;
1353 draw_points[2].X = fill_area->X;
1354 draw_points[2].Y = fill_area->Y+1;
1355
1356 /* Transform the points to the co-ordinate space of the bitmap. */
1358 WineCoordinateSpaceGdiDevice, draw_points, 3);
1359
1360 if (stat == Ok)
1361 {
1362 GpMatrix world_to_texture = fill->transform;
1363
1364 stat = GdipInvertMatrix(&world_to_texture);
1365 if (stat == Ok)
1366 stat = GdipTransformMatrixPoints(&world_to_texture, draw_points, 3);
1367 }
1368
1369 if (stat == Ok && !fill->bitmap_bits)
1370 {
1371 BitmapData lockeddata;
1372
1373 fill->bitmap_bits = heap_alloc_zero(sizeof(ARGB) * bitmap->width * bitmap->height);
1374 if (!fill->bitmap_bits)
1375 stat = OutOfMemory;
1376
1377 if (stat == Ok)
1378 {
1379 lockeddata.Width = bitmap->width;
1380 lockeddata.Height = bitmap->height;
1381 lockeddata.Stride = src_stride;
1382 lockeddata.PixelFormat = PixelFormat32bppARGB;
1383 lockeddata.Scan0 = fill->bitmap_bits;
1384
1386 PixelFormat32bppARGB, &lockeddata);
1387 }
1388
1389 if (stat == Ok)
1390 stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
1391
1392 if (stat == Ok)
1393 apply_image_attributes(fill->imageattributes, fill->bitmap_bits,
1395 src_stride, ColorAdjustTypeBitmap, lockeddata.PixelFormat);
1396
1397 if (stat != Ok)
1398 {
1399 heap_free(fill->bitmap_bits);
1400 fill->bitmap_bits = NULL;
1401 }
1402 }
1403
1404 if (stat == Ok)
1405 {
1406 REAL x_dx = draw_points[1].X - draw_points[0].X;
1407 REAL x_dy = draw_points[1].Y - draw_points[0].Y;
1408 REAL y_dx = draw_points[2].X - draw_points[0].X;
1409 REAL y_dy = draw_points[2].Y - draw_points[0].Y;
1410
1411 for (y=0; y<fill_area->Height; y++)
1412 {
1413 for (x=0; x<fill_area->Width; x++)
1414 {
1416 point.X = draw_points[0].X + x * x_dx + y * y_dx;
1417 point.Y = draw_points[0].Y + y * x_dy + y * y_dy;
1418
1419 argb_pixels[x + y*cdwStride] = resample_bitmap_pixel(
1420 &src_area, fill->bitmap_bits, bitmap->width, bitmap->height,
1421 &point, fill->imageattributes, graphics->interpolation,
1422 graphics->pixeloffset);
1423 }
1424 }
1425 }
1426
1427 return stat;
1428 }
1430 {
1432 GpPath *flat_path;
1433 GpMatrix world_to_device;
1434 GpStatus stat;
1435 int i, figure_start=0;
1436 GpPointF start_point, end_point, center_point;
1437 BYTE type;
1438 REAL min_yf, max_yf, line1_xf, line2_xf;
1439 INT min_y, max_y, min_x, max_x;
1440 INT x, y;
1441 ARGB outer_color;
1442 static BOOL transform_fixme_once;
1443
1444 if (fill->focus.X != 0.0 || fill->focus.Y != 0.0)
1445 {
1446 static int once;
1447 if (!once++)
1448 FIXME("path gradient focus not implemented\n");
1449 }
1450
1451 if (fill->gamma)
1452 {
1453 static int once;
1454 if (!once++)
1455 FIXME("path gradient gamma correction not implemented\n");
1456 }
1457
1458 if (fill->blendcount)
1459 {
1460 static int once;
1461 if (!once++)
1462 FIXME("path gradient blend not implemented\n");
1463 }
1464
1465 if (fill->pblendcount)
1466 {
1467 static int once;
1468 if (!once++)
1469 FIXME("path gradient preset blend not implemented\n");
1470 }
1471
1472 if (!transform_fixme_once)
1473 {
1475 GdipIsMatrixIdentity(&fill->transform, &is_identity);
1476 if (!is_identity)
1477 {
1478 FIXME("path gradient transform not implemented\n");
1479 transform_fixme_once = TRUE;
1480 }
1481 }
1482
1483 stat = GdipClonePath(fill->path, &flat_path);
1484
1485 if (stat != Ok)
1486 return stat;
1487
1489 CoordinateSpaceWorld, &world_to_device);
1490 if (stat == Ok)
1491 {
1492 stat = GdipTransformPath(flat_path, &world_to_device);
1493
1494 if (stat == Ok)
1495 {
1496 center_point = fill->center;
1497 stat = GdipTransformMatrixPoints(&world_to_device, &center_point, 1);
1498 }
1499
1500 if (stat == Ok)
1501 stat = GdipFlattenPath(flat_path, NULL, 0.5);
1502 }
1503
1504 if (stat != Ok)
1505 {
1506 GdipDeletePath(flat_path);
1507 return stat;
1508 }
1509
1510 for (i=0; i<flat_path->pathdata.Count; i++)
1511 {
1512 int start_center_line=0, end_center_line=0;
1513 BOOL seen_start = FALSE, seen_end = FALSE, seen_center = FALSE;
1514 REAL center_distance;
1515 ARGB start_color, end_color;
1516 REAL dy, dx;
1517
1518 type = flat_path->pathdata.Types[i];
1519
1521 figure_start = i;
1522
1523 start_point = flat_path->pathdata.Points[i];
1524
1525 start_color = fill->surroundcolors[min(i, fill->surroundcolorcount-1)];
1526
1528 {
1529 end_point = flat_path->pathdata.Points[figure_start];
1530 end_color = fill->surroundcolors[min(figure_start, fill->surroundcolorcount-1)];
1531 }
1532 else if ((flat_path->pathdata.Types[i+1] & PathPointTypePathTypeMask) == PathPointTypeLine)
1533 {
1534 end_point = flat_path->pathdata.Points[i+1];
1535 end_color = fill->surroundcolors[min(i+1, fill->surroundcolorcount-1)];
1536 }
1537 else
1538 continue;
1539
1540 outer_color = start_color;
1541
1542 min_yf = center_point.Y;
1543 if (min_yf > start_point.Y) min_yf = start_point.Y;
1544 if (min_yf > end_point.Y) min_yf = end_point.Y;
1545
1546 if (min_yf < fill_area->Y)
1547 min_y = fill_area->Y;
1548 else
1549 min_y = (INT)ceil(min_yf);
1550
1551 max_yf = center_point.Y;
1552 if (max_yf < start_point.Y) max_yf = start_point.Y;
1553 if (max_yf < end_point.Y) max_yf = end_point.Y;
1554
1555 if (max_yf > fill_area->Y + fill_area->Height)
1556 max_y = fill_area->Y + fill_area->Height;
1557 else
1558 max_y = (INT)ceil(max_yf);
1559
1560 dy = end_point.Y - start_point.Y;
1561 dx = end_point.X - start_point.X;
1562
1563 /* This is proportional to the distance from start-end line to center point. */
1564 center_distance = dy * (start_point.X - center_point.X) +
1565 dx * (center_point.Y - start_point.Y);
1566
1567 for (y=min_y; y<max_y; y++)
1568 {
1569 REAL yf = (REAL)y;
1570
1571 if (!seen_start && yf >= start_point.Y)
1572 {
1573 seen_start = TRUE;
1574 start_center_line ^= 1;
1575 }
1576 if (!seen_end && yf >= end_point.Y)
1577 {
1578 seen_end = TRUE;
1579 end_center_line ^= 1;
1580 }
1581 if (!seen_center && yf >= center_point.Y)
1582 {
1583 seen_center = TRUE;
1584 start_center_line ^= 1;
1585 end_center_line ^= 1;
1586 }
1587
1588 if (start_center_line)
1589 line1_xf = intersect_line_scanline(&start_point, &center_point, yf);
1590 else
1591 line1_xf = intersect_line_scanline(&start_point, &end_point, yf);
1592
1593 if (end_center_line)
1594 line2_xf = intersect_line_scanline(&end_point, &center_point, yf);
1595 else
1596 line2_xf = intersect_line_scanline(&start_point, &end_point, yf);
1597
1598 if (line1_xf < line2_xf)
1599 {
1600 min_x = (INT)ceil(line1_xf);
1601 max_x = (INT)ceil(line2_xf);
1602 }
1603 else
1604 {
1605 min_x = (INT)ceil(line2_xf);
1606 max_x = (INT)ceil(line1_xf);
1607 }
1608
1609 if (min_x < fill_area->X)
1610 min_x = fill_area->X;
1611 if (max_x > fill_area->X + fill_area->Width)
1612 max_x = fill_area->X + fill_area->Width;
1613
1614 for (x=min_x; x<max_x; x++)
1615 {
1616 REAL xf = (REAL)x;
1617 REAL distance;
1618
1619 if (start_color != end_color)
1620 {
1621 REAL blend_amount, pdy, pdx;
1622 pdy = yf - center_point.Y;
1623 pdx = xf - center_point.X;
1624
1625 if (fabs(pdx) <= 0.001 && fabs(pdy) <= 0.001)
1626 {
1627 /* Too close to center point, don't try to calculate outer color */
1628 outer_color = start_color;
1629 }
1630 else
1631 {
1632 blend_amount = ( (center_point.Y - start_point.Y) * pdx + (start_point.X - center_point.X) * pdy ) / ( dy * pdx - dx * pdy );
1633 outer_color = blend_colors(start_color, end_color, blend_amount);
1634 }
1635 }
1636
1637 distance = (end_point.Y - start_point.Y) * (start_point.X - xf) +
1638 (end_point.X - start_point.X) * (yf - start_point.Y);
1639
1640 distance = distance / center_distance;
1641
1642 argb_pixels[(x-fill_area->X) + (y-fill_area->Y)*cdwStride] =
1643 blend_colors(outer_color, fill->centercolor, distance);
1644 }
1645 }
1646 }
1647
1648 GdipDeletePath(flat_path);
1649 return stat;
1650 }
1651 default:
1652 return NotImplemented;
1653 }
1654}
1655
1656/* Draws the linecap the specified color and size on the hdc. The linecap is in
1657 * direction of the line from x1, y1 to x2, y2 and is anchored on x2, y2. Probably
1658 * should not be called on an hdc that has a path you care about. */
1660 const GpCustomLineCap *custom, REAL x1, REAL y1, REAL x2, REAL y2)
1661{
1662 HGDIOBJ oldbrush = NULL, oldpen = NULL;
1664 HBRUSH brush = NULL;
1665 HPEN pen = NULL;
1666 PointF ptf[4], *custptf = NULL;
1667 POINT pt[4], *custpt = NULL;
1668 BYTE *tp = NULL;
1669 REAL theta, dsmall, dbig, dx, dy = 0.0;
1670 INT i, count;
1671 LOGBRUSH lb;
1672 BOOL customstroke;
1673
1674 if((x1 == x2) && (y1 == y2))
1675 return;
1676
1677 theta = gdiplus_atan2(y2 - y1, x2 - x1);
1678
1679 customstroke = (cap == LineCapCustom) && custom && (!custom->fill);
1680 if(!customstroke){
1681 brush = CreateSolidBrush(color);
1682 lb.lbStyle = BS_SOLID;
1683 lb.lbColor = color;
1684 lb.lbHatch = 0;
1686 PS_JOIN_MITER, 1, &lb, 0,
1687 NULL);
1688 oldbrush = SelectObject(graphics->hdc, brush);
1689 oldpen = SelectObject(graphics->hdc, pen);
1690 }
1691
1692 switch(cap){
1693 case LineCapFlat:
1694 break;
1695 case LineCapSquare:
1698 size = size * (cap & LineCapNoAnchor ? ANCHOR_WIDTH : 1.0) / 2.0;
1700 dsmall = cos(theta + M_PI_2) * size;
1701 dbig = sin(theta + M_PI_2) * size;
1702 }
1703 else{
1704 dsmall = cos(theta + M_PI_4) * size;
1705 dbig = sin(theta + M_PI_4) * size;
1706 }
1707
1708 ptf[0].X = x2 - dsmall;
1709 ptf[1].X = x2 + dbig;
1710
1711 ptf[0].Y = y2 - dbig;
1712 ptf[3].Y = y2 + dsmall;
1713
1714 ptf[1].Y = y2 - dsmall;
1715 ptf[2].Y = y2 + dbig;
1716
1717 ptf[3].X = x2 - dbig;
1718 ptf[2].X = x2 + dsmall;
1719
1721
1722 round_points(pt, ptf, 4);
1723
1724 Polygon(graphics->hdc, pt, 4);
1725
1726 break;
1727 case LineCapArrowAnchor:
1728 size = size * 4.0 / sqrt(3.0);
1729
1730 dx = cos(M_PI / 6.0 + theta) * size;
1731 dy = sin(M_PI / 6.0 + theta) * size;
1732
1733 ptf[0].X = x2 - dx;
1734 ptf[0].Y = y2 - dy;
1735
1736 dx = cos(- M_PI / 6.0 + theta) * size;
1737 dy = sin(- M_PI / 6.0 + theta) * size;
1738
1739 ptf[1].X = x2 - dx;
1740 ptf[1].Y = y2 - dy;
1741
1742 ptf[2].X = x2;
1743 ptf[2].Y = y2;
1744
1746
1747 round_points(pt, ptf, 3);
1748
1749 Polygon(graphics->hdc, pt, 3);
1750
1751 break;
1752 case LineCapRoundAnchor:
1753 dx = dy = ANCHOR_WIDTH * size / 2.0;
1754
1755 ptf[0].X = x2 - dx;
1756 ptf[0].Y = y2 - dy;
1757 ptf[1].X = x2 + dx;
1758 ptf[1].Y = y2 + dy;
1759
1761
1762 round_points(pt, ptf, 2);
1763
1764 Ellipse(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
1765
1766 break;
1767 case LineCapTriangle:
1768 size = size / 2.0;
1769 dx = cos(M_PI_2 + theta) * size;
1770 dy = sin(M_PI_2 + theta) * size;
1771
1772 ptf[0].X = x2 - dx;
1773 ptf[0].Y = y2 - dy;
1774 ptf[1].X = x2 + dx;
1775 ptf[1].Y = y2 + dy;
1776
1777 dx = cos(theta) * size;
1778 dy = sin(theta) * size;
1779
1780 ptf[2].X = x2 + dx;
1781 ptf[2].Y = y2 + dy;
1782
1784
1785 round_points(pt, ptf, 3);
1786
1787 Polygon(graphics->hdc, pt, 3);
1788
1789 break;
1790 case LineCapRound:
1791 dx = dy = size / 2.0;
1792
1793 ptf[0].X = x2 - dx;
1794 ptf[0].Y = y2 - dy;
1795 ptf[1].X = x2 + dx;
1796 ptf[1].Y = y2 + dy;
1797
1798 dx = -cos(M_PI_2 + theta) * size;
1799 dy = -sin(M_PI_2 + theta) * size;
1800
1801 ptf[2].X = x2 - dx;
1802 ptf[2].Y = y2 - dy;
1803 ptf[3].X = x2 + dx;
1804 ptf[3].Y = y2 + dy;
1805
1807
1808 round_points(pt, ptf, 4);
1809
1810 Pie(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y, pt[2].x,
1811 pt[2].y, pt[3].x, pt[3].y);
1812
1813 break;
1814 case LineCapCustom:
1815 if(!custom)
1816 break;
1817
1819 {
1820 GpAdjustableArrowCap *arrow = (GpAdjustableArrowCap *)custom;
1821 if (arrow->cap.fill && arrow->height <= 0.0)
1822 break;
1823 }
1824
1825 count = custom->pathdata.Count;
1826 custptf = heap_alloc_zero(count * sizeof(PointF));
1827 custpt = heap_alloc_zero(count * sizeof(POINT));
1828 tp = heap_alloc_zero(count);
1829
1830 if(!custptf || !custpt || !tp)
1831 goto custend;
1832
1833 memcpy(custptf, custom->pathdata.Points, count * sizeof(PointF));
1834
1835 GdipSetMatrixElements(&matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1837 GdipRotateMatrix(&matrix, (180.0 / M_PI) * (theta - M_PI_2),
1841
1843
1844 round_points(custpt, custptf, count);
1845
1846 for(i = 0; i < count; i++)
1848
1849 if(custom->fill){
1850 BeginPath(graphics->hdc);
1851 PolyDraw(graphics->hdc, custpt, tp, count);
1852 EndPath(graphics->hdc);
1853 StrokeAndFillPath(graphics->hdc);
1854 }
1855 else
1856 PolyDraw(graphics->hdc, custpt, tp, count);
1857
1858custend:
1859 heap_free(custptf);
1860 heap_free(custpt);
1861 heap_free(tp);
1862 break;
1863 default:
1864 break;
1865 }
1866
1867 if(!customstroke){
1868 SelectObject(graphics->hdc, oldbrush);
1869 SelectObject(graphics->hdc, oldpen);
1870 DeleteObject(brush);
1871 DeleteObject(pen);
1872 }
1873}
1874
1875/* Shortens the line by the given percent by changing x2, y2.
1876 * If percent is > 1.0 then the line will change direction.
1877 * If percent is negative it can lengthen the line. */
1878static void shorten_line_percent(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL percent)
1879{
1880 REAL dist, theta, dx, dy;
1881
1882 if((y1 == *y2) && (x1 == *x2))
1883 return;
1884
1885 dist = sqrt((*x2 - x1) * (*x2 - x1) + (*y2 - y1) * (*y2 - y1)) * -percent;
1886 theta = gdiplus_atan2((*y2 - y1), (*x2 - x1));
1887 dx = cos(theta) * dist;
1888 dy = sin(theta) * dist;
1889
1890 *x2 = *x2 + dx;
1891 *y2 = *y2 + dy;
1892}
1893
1894/* Shortens the line by the given amount by changing x2, y2.
1895 * If the amount is greater than the distance, the line will become length 0.
1896 * If the amount is negative, it can lengthen the line. */
1898{
1899 REAL dx, dy, percent;
1900
1901 dx = *x2 - x1;
1902 dy = *y2 - y1;
1903 if(dx == 0 && dy == 0)
1904 return;
1905
1906 percent = amt / sqrt(dx * dx + dy * dy);
1907 if(percent >= 1.0){
1908 *x2 = x1;
1909 *y2 = y1;
1910 return;
1911 }
1912
1913 shorten_line_percent(x1, y1, x2, y2, percent);
1914}
1915
1916/* Conducts a linear search to find the bezier points that will back off
1917 * the endpoint of the curve by a distance of amt. Linear search works
1918 * better than binary in this case because there are multiple solutions,
1919 * and binary searches often find a bad one. I don't think this is what
1920 * Windows does but short of rendering the bezier without GDI's help it's
1921 * the best we can do. If rev then work from the start of the passed points
1922 * instead of the end. */
1924{
1925 GpPointF origpt[4];
1926 REAL percent = 0.00, dx, dy, origx, origy, diff = -1.0;
1927 INT i, first = 0, second = 1, third = 2, fourth = 3;
1928
1929 if(rev){
1930 first = 3;
1931 second = 2;
1932 third = 1;
1933 fourth = 0;
1934 }
1935
1936 origx = pt[fourth].X;
1937 origy = pt[fourth].Y;
1938 memcpy(origpt, pt, sizeof(GpPointF) * 4);
1939
1940 for(i = 0; (i < MAX_ITERS) && (diff < amt); i++){
1941 /* reset bezier points to original values */
1942 memcpy(pt, origpt, sizeof(GpPointF) * 4);
1943 /* Perform magic on bezier points. Order is important here.*/
1944 shorten_line_percent(pt[third].X, pt[third].Y, &pt[fourth].X, &pt[fourth].Y, percent);
1945 shorten_line_percent(pt[second].X, pt[second].Y, &pt[third].X, &pt[third].Y, percent);
1946 shorten_line_percent(pt[third].X, pt[third].Y, &pt[fourth].X, &pt[fourth].Y, percent);
1947 shorten_line_percent(pt[first].X, pt[first].Y, &pt[second].X, &pt[second].Y, percent);
1948 shorten_line_percent(pt[second].X, pt[second].Y, &pt[third].X, &pt[third].Y, percent);
1949 shorten_line_percent(pt[third].X, pt[third].Y, &pt[fourth].X, &pt[fourth].Y, percent);
1950
1951 dx = pt[fourth].X - origx;
1952 dy = pt[fourth].Y - origy;
1953
1954 diff = sqrt(dx * dx + dy * dy);
1955 percent += 0.0005 * amt;
1956 }
1957}
1958
1959/* Draws a combination of bezier curves and lines between points. */
1961 GDIPCONST BYTE * types, INT count, BOOL caps)
1962{
1963 POINT *pti = heap_alloc_zero(count * sizeof(POINT));
1964 BYTE *tp = heap_alloc_zero(count);
1965 GpPointF *ptcopy = heap_alloc_zero(count * sizeof(GpPointF));
1966 INT i, j;
1968
1969 if(!count){
1970 status = Ok;
1971 goto end;
1972 }
1973 if(!pti || !tp || !ptcopy){
1975 goto end;
1976 }
1977
1978 for(i = 1; i < count; i++){
1980 if((i + 2 >= count) || !(types[i + 1] & PathPointTypeBezier)
1981 || !(types[i + 2] & PathPointTypeBezier)){
1982 ERR("Bad bezier points\n");
1983 goto end;
1984 }
1985 i += 2;
1986 }
1987 }
1988
1989 memcpy(ptcopy, pt, count * sizeof(GpPointF));
1990
1991 /* If we are drawing caps, go through the points and adjust them accordingly,
1992 * and draw the caps. */
1993 if(caps){
1994 switch(types[count - 1] & PathPointTypePathTypeMask){
1996 if(pen->endcap == LineCapArrowAnchor)
1997 shorten_bezier_amt(&ptcopy[count - 4], pen->width, FALSE);
1998 else if((pen->endcap == LineCapCustom) && pen->customend)
1999 shorten_bezier_amt(&ptcopy[count - 4],
2000 pen->width * pen->customend->inset, FALSE);
2001
2002 draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
2003 pt[count - 1].X - (ptcopy[count - 1].X - ptcopy[count - 2].X),
2004 pt[count - 1].Y - (ptcopy[count - 1].Y - ptcopy[count - 2].Y),
2005 pt[count - 1].X, pt[count - 1].Y);
2006
2007 break;
2008 case PathPointTypeLine:
2009 if(pen->endcap == LineCapArrowAnchor)
2010 shorten_line_amt(ptcopy[count - 2].X, ptcopy[count - 2].Y,
2011 &ptcopy[count - 1].X, &ptcopy[count - 1].Y,
2012 pen->width);
2013 else if((pen->endcap == LineCapCustom) && pen->customend)
2014 shorten_line_amt(ptcopy[count - 2].X, ptcopy[count - 2].Y,
2015 &ptcopy[count - 1].X, &ptcopy[count - 1].Y,
2016 pen->customend->inset * pen->width);
2017
2018 draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->endcap, pen->width, pen->customend,
2019 pt[count - 2].X, pt[count - 2].Y, pt[count - 1].X,
2020 pt[count - 1].Y);
2021
2022 break;
2023 default:
2024 ERR("Bad path last point\n");
2025 goto end;
2026 }
2027
2028 /* Find start of points */
2029 for(j = 1; j < count && ((types[j] & PathPointTypePathTypeMask)
2030 == PathPointTypeStart); j++);
2031
2034 if(pen->startcap == LineCapArrowAnchor)
2035 shorten_bezier_amt(&ptcopy[j - 1], pen->width, TRUE);
2036 else if((pen->startcap == LineCapCustom) && pen->customstart)
2037 shorten_bezier_amt(&ptcopy[j - 1],
2038 pen->width * pen->customstart->inset, TRUE);
2039
2040 draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
2041 pt[j - 1].X - (ptcopy[j - 1].X - ptcopy[j].X),
2042 pt[j - 1].Y - (ptcopy[j - 1].Y - ptcopy[j].Y),
2043 pt[j - 1].X, pt[j - 1].Y);
2044
2045 break;
2046 case PathPointTypeLine:
2047 if(pen->startcap == LineCapArrowAnchor)
2048 shorten_line_amt(ptcopy[j].X, ptcopy[j].Y,
2049 &ptcopy[j - 1].X, &ptcopy[j - 1].Y,
2050 pen->width);
2051 else if((pen->startcap == LineCapCustom) && pen->customstart)
2052 shorten_line_amt(ptcopy[j].X, ptcopy[j].Y,
2053 &ptcopy[j - 1].X, &ptcopy[j - 1].Y,
2054 pen->customstart->inset * pen->width);
2055
2056 draw_cap(graphics, get_gdi_brush_color(pen->brush), pen->startcap, pen->width, pen->customstart,
2057 pt[j].X, pt[j].Y, pt[j - 1].X,
2058 pt[j - 1].Y);
2059
2060 break;
2061 default:
2062 ERR("Bad path points\n");
2063 goto end;
2064 }
2065 }
2066
2068
2069 round_points(pti, ptcopy, count);
2070
2071 for(i = 0; i < count; i++){
2073 }
2074
2075 PolyDraw(graphics->hdc, pti, tp, count);
2076
2077 status = Ok;
2078
2079end:
2080 heap_free(pti);
2081 heap_free(ptcopy);
2082 heap_free(tp);
2083
2084 return status;
2085}
2086
2088{
2090
2091 BeginPath(graphics->hdc);
2092 result = draw_poly(graphics, NULL, path->pathdata.Points,
2093 path->pathdata.Types, path->pathdata.Count, FALSE);
2094 EndPath(graphics->hdc);
2095 return result;
2096}
2097
2102
2104 struct list entry;
2107
2121
2124 GpStatus sts;
2125
2126 *container = heap_alloc_zero(sizeof(GraphicsContainerItem));
2127 if(!(*container))
2128 return OutOfMemory;
2129
2130 (*container)->contid = graphics->contid + 1;
2131 (*container)->type = type;
2132
2133 (*container)->smoothing = graphics->smoothing;
2134 (*container)->compqual = graphics->compqual;
2135 (*container)->interpolation = graphics->interpolation;
2136 (*container)->compmode = graphics->compmode;
2137 (*container)->texthint = graphics->texthint;
2138 (*container)->scale = graphics->scale;
2139 (*container)->unit = graphics->unit;
2140 (*container)->textcontrast = graphics->textcontrast;
2141 (*container)->pixeloffset = graphics->pixeloffset;
2142 (*container)->origin_x = graphics->origin_x;
2143 (*container)->origin_y = graphics->origin_y;
2144 (*container)->worldtrans = graphics->worldtrans;
2145
2146 sts = GdipCloneRegion(graphics->clip, &(*container)->clip);
2147 if(sts != Ok){
2149 *container = NULL;
2150 return sts;
2151 }
2152
2153 return Ok;
2154}
2155
2157{
2160}
2161
2164 GpStatus sts;
2165 GpRegion *newClip;
2166
2167 sts = GdipCloneRegion(container->clip, &newClip);
2168 if(sts != Ok) return sts;
2169
2170 graphics->worldtrans = container->worldtrans;
2171
2172 GdipDeleteRegion(graphics->clip);
2173 graphics->clip = newClip;
2174
2175 graphics->contid = container->contid - 1;
2176
2177 graphics->smoothing = container->smoothing;
2178 graphics->compqual = container->compqual;
2179 graphics->interpolation = container->interpolation;
2180 graphics->compmode = container->compmode;
2181 graphics->texthint = container->texthint;
2182 graphics->scale = container->scale;
2183 graphics->unit = container->unit;
2184 graphics->textcontrast = container->textcontrast;
2185 graphics->pixeloffset = container->pixeloffset;
2186 graphics->origin_x = container->origin_x;
2187 graphics->origin_y = container->origin_y;
2188
2189 return Ok;
2190}
2191
2193{
2194 RECT wnd_rect;
2196 GpUnit unit;
2197
2198 if(graphics->hwnd) {
2199 if(!GetClientRect(graphics->hwnd, &wnd_rect))
2200 return GenericError;
2201
2202 rect->X = wnd_rect.left;
2203 rect->Y = wnd_rect.top;
2204 rect->Width = wnd_rect.right - wnd_rect.left;
2205 rect->Height = wnd_rect.bottom - wnd_rect.top;
2206 }else if (graphics->image){
2207 stat = GdipGetImageBounds(graphics->image, rect, &unit);
2208 if (stat == Ok && unit != UnitPixel)
2209 FIXME("need to convert from unit %i\n", unit);
2210 }else if (GetObjectType(graphics->hdc) == OBJ_MEMDC){
2211 HBITMAP hbmp;
2212 BITMAP bmp;
2213
2214 rect->X = 0;
2215 rect->Y = 0;
2216
2217 hbmp = GetCurrentObject(graphics->hdc, OBJ_BITMAP);
2218 if (hbmp && GetObjectW(hbmp, sizeof(bmp), &bmp))
2219 {
2220 rect->Width = bmp.bmWidth;
2221 rect->Height = bmp.bmHeight;
2222 }
2223 else
2224 {
2225 /* FIXME: ??? */
2226 rect->Width = 1;
2227 rect->Height = 1;
2228 }
2229 }else{
2230 rect->X = 0;
2231 rect->Y = 0;
2232 rect->Width = GetDeviceCaps(graphics->hdc, HORZRES);
2233 rect->Height = GetDeviceCaps(graphics->hdc, VERTRES);
2234 }
2235
2236 return stat;
2237}
2238
2240{
2242
2243 if (stat == Ok && graphics->hdc)
2244 {
2245 GpPointF points[4], min_point, max_point;
2246 int i;
2247
2248 points[0].X = points[2].X = rect->X;
2249 points[0].Y = points[1].Y = rect->Y;
2250 points[1].X = points[3].X = rect->X + rect->Width;
2251 points[2].Y = points[3].Y = rect->Y + rect->Height;
2252
2254
2255 min_point = max_point = points[0];
2256
2257 for (i=1; i<4; i++)
2258 {
2259 if (points[i].X < min_point.X) min_point.X = points[i].X;
2260 if (points[i].Y < min_point.Y) min_point.Y = points[i].Y;
2261 if (points[i].X > max_point.X) max_point.X = points[i].X;
2262 if (points[i].Y > max_point.Y) max_point.Y = points[i].Y;
2263 }
2264
2265 rect->X = min_point.X;
2266 rect->Y = min_point.Y;
2267 rect->Width = max_point.X - min_point.X;
2268 rect->Height = max_point.Y - min_point.Y;
2269 }
2270
2271 return stat;
2272}
2273
2274/* on success, rgn will contain the region of the graphics object which
2275 * is visible after clipping has been applied */
2277{
2278 GpStatus stat;
2279 GpRectF rectf;
2280 GpRegion* tmp;
2281
2282 /* Ignore graphics image bounds for metafiles */
2283 if (graphics->image && graphics->image_type == ImageTypeMetafile)
2284 return GdipCombineRegionRegion(rgn, graphics->clip, CombineModeReplace);
2285
2286 if((stat = get_graphics_bounds(graphics, &rectf)) != Ok)
2287 return stat;
2288
2289 if((stat = GdipCreateRegion(&tmp)) != Ok)
2290 return stat;
2291
2292 if((stat = GdipCombineRegionRect(tmp, &rectf, CombineModeReplace)) != Ok)
2293 goto end;
2294
2295 if((stat = GdipCombineRegionRegion(tmp, graphics->clip, CombineModeIntersect)) != Ok)
2296 goto end;
2297
2299
2300end:
2301 GdipDeleteRegion(tmp);
2302 return stat;
2303}
2304
2305void get_log_fontW(const GpFont *font, GpGraphics *graphics, LOGFONTW *lf)
2306{
2307 REAL height;
2308
2309 if (font->unit == UnitPixel)
2310 {
2311 height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
2312 }
2313 else
2314 {
2315 if (graphics->unit == UnitDisplay || graphics->unit == UnitPixel)
2316 height = units_to_pixels(font->emSize, font->unit, graphics->xres);
2317 else
2318 height = units_to_pixels(font->emSize, font->unit, graphics->yres);
2319 }
2320
2321 lf->lfHeight = -(height + 0.5);
2322 lf->lfWidth = 0;
2323 lf->lfEscapement = 0;
2324 lf->lfOrientation = 0;
2325 lf->lfWeight = font->otm.otmTextMetrics.tmWeight;
2326 lf->lfItalic = font->otm.otmTextMetrics.tmItalic ? 1 : 0;
2327 lf->lfUnderline = font->otm.otmTextMetrics.tmUnderlined ? 1 : 0;
2328 lf->lfStrikeOut = font->otm.otmTextMetrics.tmStruckOut ? 1 : 0;
2329 lf->lfCharSet = font->otm.otmTextMetrics.tmCharSet;
2333 lf->lfPitchAndFamily = 0;
2334 strcpyW(lf->lfFaceName, font->family->FamilyName);
2335}
2336
2340{
2342 GpPointF pt[3];
2343 REAL angle, rel_width, rel_height, font_height;
2344 LOGFONTW lfw;
2345 HFONT unscaled_font;
2346 TEXTMETRICW textmet;
2347
2348 if (font->unit == UnitPixel || font->unit == UnitWorld)
2349 font_height = font->emSize;
2350 else
2351 {
2352 REAL unit_scale, res;
2353
2354 res = (graphics->unit == UnitDisplay || graphics->unit == UnitPixel) ? graphics->xres : graphics->yres;
2355 unit_scale = units_scale(font->unit, graphics->unit, res);
2356
2357 font_height = font->emSize * unit_scale;
2358 }
2359
2360 pt[0].X = 0.0;
2361 pt[0].Y = 0.0;
2362 pt[1].X = 1.0;
2363 pt[1].Y = 0.0;
2364 pt[2].X = 0.0;
2365 pt[2].Y = 1.0;
2366 if (matrix)
2367 {
2368 GpMatrix xform = *matrix;
2369 GdipTransformMatrixPoints(&xform, pt, 3);
2370 }
2371
2373 angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X));
2374 rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
2375 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
2376 rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
2377 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
2378
2379 get_log_fontW(font, graphics, &lfw);
2380 lfw.lfHeight = -gdip_round(font_height * rel_height);
2381 unscaled_font = CreateFontIndirectW(&lfw);
2382
2383 SelectObject(hdc, unscaled_font);
2384 GetTextMetricsW(hdc, &textmet);
2385
2386 lfw.lfWidth = gdip_round(textmet.tmAveCharWidth * rel_width / rel_height);
2387 lfw.lfEscapement = lfw.lfOrientation = gdip_round((angle / M_PI) * 1800.0);
2388
2389 *hfont = CreateFontIndirectW(&lfw);
2390
2391 DeleteDC(hdc);
2392 DeleteObject(unscaled_font);
2393}
2394
2396{
2397 TRACE("(%p, %p)\n", hdc, graphics);
2398
2399 return GdipCreateFromHDC2(hdc, NULL, graphics);
2400}
2401
2403{
2404 XFORM xform;
2405
2406 if (graphics->hdc == NULL)
2407 {
2408 GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
2409 return;
2410 }
2411
2412 GetTransform(graphics->hdc, 0x204, &xform);
2413 GdipSetMatrixElements(matrix, xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
2414}
2415
2417{
2418 GpStatus retval;
2421
2422 TRACE("(%p, %p, %p)\n", hdc, hDevice, graphics);
2423
2424 if(hDevice != NULL)
2425 FIXME("Don't know how to handle parameter hDevice\n");
2426
2427 if(hdc == NULL)
2428 return OutOfMemory;
2429
2430 if(graphics == NULL)
2431 return InvalidParameter;
2432
2433 *graphics = heap_alloc_zero(sizeof(GpGraphics));
2434 if(!*graphics) return OutOfMemory;
2435
2436 GdipSetMatrixElements(&(*graphics)->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
2437
2438 if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){
2439 heap_free(*graphics);
2440 return retval;
2441 }
2442
2444 if (hbitmap && GetObjectW(hbitmap, sizeof(dib), &dib) == sizeof(dib) &&
2445 dib.dsBmih.biBitCount == 32 && dib.dsBmih.biCompression == BI_RGB)
2446 {
2447 (*graphics)->alpha_hdc = 1;
2448 }
2449
2450 (*graphics)->hdc = hdc;
2451 (*graphics)->hwnd = WindowFromDC(hdc);
2452 (*graphics)->owndc = FALSE;
2453 (*graphics)->smoothing = SmoothingModeDefault;
2454 (*graphics)->compqual = CompositingQualityDefault;
2455 (*graphics)->interpolation = InterpolationModeBilinear;
2456 (*graphics)->pixeloffset = PixelOffsetModeDefault;
2457 (*graphics)->compmode = CompositingModeSourceOver;
2458 (*graphics)->unit = UnitDisplay;
2459 (*graphics)->scale = 1.0;
2460 (*graphics)->xres = GetDeviceCaps(hdc, LOGPIXELSX);
2461 (*graphics)->yres = GetDeviceCaps(hdc, LOGPIXELSY);
2462 (*graphics)->busy = FALSE;
2463 (*graphics)->textcontrast = 4;
2464 list_init(&(*graphics)->containers);
2465#ifdef __REACTOS__
2466 (*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics);
2467#else
2468 (*graphics)->contid = 0;
2469#endif
2470 get_gdi_transform(*graphics, &(*graphics)->gdi_transform);
2471
2472 (*graphics)->gdi_clip = CreateRectRgn(0,0,0,0);
2473 if (!GetClipRgn(hdc, (*graphics)->gdi_clip))
2474 {
2475 DeleteObject((*graphics)->gdi_clip);
2476 (*graphics)->gdi_clip = NULL;
2477 }
2478
2479 TRACE("<-- %p\n", *graphics);
2480
2481 return Ok;
2482}
2483
2485{
2486 GpStatus retval;
2487
2488 *graphics = heap_alloc_zero(sizeof(GpGraphics));
2489 if(!*graphics) return OutOfMemory;
2490
2491 GdipSetMatrixElements(&(*graphics)->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
2492 GdipSetMatrixElements(&(*graphics)->gdi_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
2493
2494 if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){
2495 heap_free(*graphics);
2496 return retval;
2497 }
2498
2499 (*graphics)->hdc = NULL;
2500 (*graphics)->hwnd = NULL;
2501 (*graphics)->owndc = FALSE;
2502 (*graphics)->image = image;
2503 /* We have to store the image type here because the image may be freed
2504 * before GdipDeleteGraphics is called, and metafiles need special treatment. */
2505 (*graphics)->image_type = image->type;
2506 (*graphics)->smoothing = SmoothingModeDefault;
2507 (*graphics)->compqual = CompositingQualityDefault;
2508 (*graphics)->interpolation = InterpolationModeBilinear;
2509 (*graphics)->pixeloffset = PixelOffsetModeDefault;
2510 (*graphics)->compmode = CompositingModeSourceOver;
2511 (*graphics)->unit = UnitDisplay;
2512 (*graphics)->scale = 1.0;
2513 (*graphics)->xres = image->xres;
2514 (*graphics)->yres = image->yres;
2515 (*graphics)->busy = FALSE;
2516 (*graphics)->textcontrast = 4;
2517 list_init(&(*graphics)->containers);
2518#ifdef __REACTOS__
2519 (*graphics)->contid = GDIP_GET_NEW_CONTID_FOR(*graphics);
2520#else
2521 (*graphics)->contid = 0;
2522#endif
2523
2524 TRACE("<-- %p\n", *graphics);
2525
2526 return Ok;
2527}
2528
2530{
2531 GpStatus ret;
2532 HDC hdc;
2533
2534 TRACE("(%p, %p)\n", hwnd, graphics);
2535
2536 hdc = GetDC(hwnd);
2537
2538 if((ret = GdipCreateFromHDC(hdc, graphics)) != Ok)
2539 {
2540 ReleaseDC(hwnd, hdc);
2541 return ret;
2542 }
2543
2544 (*graphics)->hwnd = hwnd;
2545 (*graphics)->owndc = TRUE;
2546
2547 return Ok;
2548}
2549
2550/* FIXME: no icm handling */
2552{
2553 TRACE("(%p, %p)\n", hwnd, graphics);
2554
2555 return GdipCreateFromHWND(hwnd, graphics);
2556}
2557
2560{
2561 DWORD dwMode;
2562 HRESULT ret;
2563
2564 TRACE("(%s, %u, %p)\n", debugstr_w(filename), access, stream);
2565
2566 if(!stream || !filename)
2567 return InvalidParameter;
2568
2569 if(access & GENERIC_WRITE)
2571 else if(access & GENERIC_READ)
2573 else
2574 return InvalidParameter;
2575
2577
2578 return hresult_to_status(ret);
2579}
2580
2582{
2584 GpStatus stat;
2585 TRACE("(%p)\n", graphics);
2586
2587 if(!graphics) return InvalidParameter;
2588 if(graphics->busy) return ObjectBusy;
2589
2590 if (graphics->image && graphics->image_type == ImageTypeMetafile)
2591 {
2593 if (stat != Ok)
2594 return stat;
2595 }
2596
2597 if(graphics->owndc)
2598 ReleaseDC(graphics->hwnd, graphics->hdc);
2599
2601 list_remove(&cont->entry);
2602 delete_container(cont);
2603 }
2604
2605 GdipDeleteRegion(graphics->clip);
2606
2607 DeleteObject(graphics->gdi_clip);
2608
2609 /* Native returns ObjectBusy on the second free, instead of crashing as we'd
2610 * do otherwise, but we can't have that in the test suite because it means
2611 * accessing freed memory. */
2612 graphics->busy = TRUE;
2613
2614 heap_free(graphics);
2615
2616 return Ok;
2617}
2618
2620 REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
2621{
2623 GpPath *path;
2624
2625 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y,
2626 width, height, startAngle, sweepAngle);
2627
2628 if(!graphics || !pen || width <= 0 || height <= 0)
2629 return InvalidParameter;
2630
2631 if(graphics->busy)
2632 return ObjectBusy;
2633
2635 if (status != Ok) return status;
2636
2637 status = GdipAddPathArc(path, x, y, width, height, startAngle, sweepAngle);
2638 if (status == Ok)
2639 status = GdipDrawPath(graphics, pen, path);
2640
2642 return status;
2643}
2644
2646 INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
2647{
2648 TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n", graphics, pen, x, y,
2649 width, height, startAngle, sweepAngle);
2650
2651 return GdipDrawArc(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
2652}
2653
2655 REAL y1, REAL x2, REAL y2, REAL x3, REAL y3, REAL x4, REAL y4)
2656{
2657 GpPointF pt[4];
2658
2659 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1,
2660 x2, y2, x3, y3, x4, y4);
2661
2662 if(!graphics || !pen)
2663 return InvalidParameter;
2664
2665 if(graphics->busy)
2666 return ObjectBusy;
2667
2668 pt[0].X = x1;
2669 pt[0].Y = y1;
2670 pt[1].X = x2;
2671 pt[1].Y = y2;
2672 pt[2].X = x3;
2673 pt[2].Y = y3;
2674 pt[3].X = x4;
2675 pt[3].Y = y4;
2676 return GdipDrawBeziers(graphics, pen, pt, 4);
2677}
2678
2680 INT y1, INT x2, INT y2, INT x3, INT y3, INT x4, INT y4)
2681{
2682 TRACE("(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", graphics, pen, x1, y1,
2683 x2, y2, x3, y3, x4, y4);
2684
2685 return GdipDrawBezier(graphics, pen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2, (REAL)x3, (REAL)y3, (REAL)x4, (REAL)y4);
2686}
2687
2690{
2692 GpPath *path;
2693
2694 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2695
2696 if(!graphics || !pen || !points || (count <= 0))
2697 return InvalidParameter;
2698
2699 if(graphics->busy)
2700 return ObjectBusy;
2701
2703 if (status != Ok) return status;
2704
2706 if (status == Ok)
2707 status = GdipDrawPath(graphics, pen, path);
2708
2710 return status;
2711}
2712
2715{
2716 GpPointF *pts;
2717 GpStatus ret;
2718 INT i;
2719
2720 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2721
2722 if(!graphics || !pen || !points || (count <= 0))
2723 return InvalidParameter;
2724
2725 if(graphics->busy)
2726 return ObjectBusy;
2727
2728 pts = heap_alloc_zero(sizeof(GpPointF) * count);
2729 if(!pts)
2730 return OutOfMemory;
2731
2732 for(i = 0; i < count; i++){
2733 pts[i].X = (REAL)points[i].X;
2734 pts[i].Y = (REAL)points[i].Y;
2735 }
2736
2737 ret = GdipDrawBeziers(graphics,pen,pts,count);
2738
2739 heap_free(pts);
2740
2741 return ret;
2742}
2743
2746{
2747 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2748
2749 return GdipDrawClosedCurve2(graphics, pen, points, count, 1.0);
2750}
2751
2754{
2755 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2756
2757 return GdipDrawClosedCurve2I(graphics, pen, points, count, 1.0);
2758}
2759
2762{
2763 GpPath *path;
2765
2766 TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
2767
2768 if(!graphics || !pen || !points || count <= 0)
2769 return InvalidParameter;
2770
2771 if(graphics->busy)
2772 return ObjectBusy;
2773
2775 if (status != Ok) return status;
2776
2778 if (status == Ok)
2779 status = GdipDrawPath(graphics, pen, path);
2780
2782
2783 return status;
2784}
2785
2787 GDIPCONST GpPoint *points, INT count, REAL tension)
2788{
2789 GpPointF *ptf;
2790 GpStatus stat;
2791 INT i;
2792
2793 TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
2794
2795 if(!points || count <= 0)
2796 return InvalidParameter;
2797
2798 ptf = heap_alloc_zero(sizeof(GpPointF)*count);
2799 if(!ptf)
2800 return OutOfMemory;
2801
2802 for(i = 0; i < count; i++){
2803 ptf[i].X = (REAL)points[i].X;
2804 ptf[i].Y = (REAL)points[i].Y;
2805 }
2806
2807 stat = GdipDrawClosedCurve2(graphics, pen, ptf, count, tension);
2808
2809 heap_free(ptf);
2810
2811 return stat;
2812}
2813
2816{
2817 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2818
2819 return GdipDrawCurve2(graphics,pen,points,count,1.0);
2820}
2821
2824{
2825 GpPointF *pointsF;
2826 GpStatus ret;
2827 INT i;
2828
2829 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
2830
2831 if(!points)
2832 return InvalidParameter;
2833
2834 pointsF = heap_alloc_zero(sizeof(GpPointF)*count);
2835 if(!pointsF)
2836 return OutOfMemory;
2837
2838 for(i = 0; i < count; i++){
2839 pointsF[i].X = (REAL)points[i].X;
2840 pointsF[i].Y = (REAL)points[i].Y;
2841 }
2842
2843 ret = GdipDrawCurve(graphics,pen,pointsF,count);
2844 heap_free(pointsF);
2845
2846 return ret;
2847}
2848
2849/* Approximates cardinal spline with Bezier curves. */
2852{
2853 GpPath *path;
2855
2856 TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
2857
2858 if(!graphics || !pen)
2859 return InvalidParameter;
2860
2861 if(graphics->busy)
2862 return ObjectBusy;
2863
2864 if(count < 2)
2865 return InvalidParameter;
2866
2868 if (status != Ok) return status;
2869
2871 if (status == Ok)
2872 status = GdipDrawPath(graphics, pen, path);
2873
2875 return status;
2876}
2877
2879 GDIPCONST GpPoint *points, INT count, REAL tension)
2880{
2881 GpPointF *pointsF;
2882 GpStatus ret;
2883 INT i;
2884
2885 TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
2886
2887 if(!points)
2888 return InvalidParameter;
2889
2890 pointsF = heap_alloc_zero(sizeof(GpPointF)*count);
2891 if(!pointsF)
2892 return OutOfMemory;
2893
2894 for(i = 0; i < count; i++){
2895 pointsF[i].X = (REAL)points[i].X;
2896 pointsF[i].Y = (REAL)points[i].Y;
2897 }
2898
2899 ret = GdipDrawCurve2(graphics,pen,pointsF,count,tension);
2900 heap_free(pointsF);
2901
2902 return ret;
2903}
2904
2906 GDIPCONST GpPointF *points, INT count, INT offset, INT numberOfSegments,
2907 REAL tension)
2908{
2909 TRACE("(%p, %p, %p, %d, %d, %d, %.2f)\n", graphics, pen, points, count, offset, numberOfSegments, tension);
2910
2911 if(offset >= count || numberOfSegments > count - offset - 1 || numberOfSegments <= 0){
2912 return InvalidParameter;
2913 }
2914
2915 return GdipDrawCurve2(graphics, pen, points + offset, numberOfSegments + 1, tension);
2916}
2917
2919 GDIPCONST GpPoint *points, INT count, INT offset, INT numberOfSegments,
2920 REAL tension)
2921{
2922 TRACE("(%p, %p, %p, %d, %d, %d, %.2f)\n", graphics, pen, points, count, offset, numberOfSegments, tension);
2923
2924 if(count < 0){
2925 return OutOfMemory;
2926 }
2927
2928 if(offset >= count || numberOfSegments > count - offset - 1 || numberOfSegments <= 0){
2929 return InvalidParameter;
2930 }
2931
2932 return GdipDrawCurve2I(graphics, pen, points + offset, numberOfSegments + 1, tension);
2933}
2934
2937{
2938 GpPath *path;
2940
2941 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y, width, height);
2942
2943 if(!graphics || !pen)
2944 return InvalidParameter;
2945
2946 if(graphics->busy)
2947 return ObjectBusy;
2948
2950 if (status != Ok) return status;
2951
2953 if (status == Ok)
2954 status = GdipDrawPath(graphics, pen, path);
2955
2957 return status;
2958}
2959
2961 INT y, INT width, INT height)
2962{
2963 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x, y, width, height);
2964
2965 return GdipDrawEllipse(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
2966}
2967
2968
2970{
2971 UINT width, height;
2972
2973 TRACE("(%p, %p, %.2f, %.2f)\n", graphics, image, x, y);
2974
2975 if(!graphics || !image)
2976 return InvalidParameter;
2977
2980
2981 return GdipDrawImagePointRect(graphics, image, x, y,
2982 0.0, 0.0, (REAL)width, (REAL)height, UnitPixel);
2983}
2984
2986 INT y)
2987{
2988 TRACE("(%p, %p, %d, %d)\n", graphics, image, x, y);
2989
2990 return GdipDrawImage(graphics, image, (REAL)x, (REAL)y);
2991}
2992
2994 REAL x, REAL y, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight,
2995 GpUnit srcUnit)
2996{
2997 GpPointF points[3];
2998 REAL scale_x, scale_y, width, height;
2999
3000 TRACE("(%p, %p, %f, %f, %f, %f, %f, %f, %d)\n", graphics, image, x, y, srcx, srcy, srcwidth, srcheight, srcUnit);
3001
3002 if (!graphics || !image) return InvalidParameter;
3003
3004 scale_x = units_scale(srcUnit, graphics->unit, graphics->xres);
3005 scale_x *= graphics->xres / image->xres;
3006 scale_y = units_scale(srcUnit, graphics->unit, graphics->yres);
3007 scale_y *= graphics->yres / image->yres;
3008 width = srcwidth * scale_x;
3009 height = srcheight * scale_y;
3010
3011 points[0].X = points[2].X = x;
3012 points[0].Y = points[1].Y = y;
3013 points[1].X = x + width;
3014 points[2].Y = y + height;
3015
3016 return GdipDrawImagePointsRect(graphics, image, points, 3, srcx, srcy,
3017 srcwidth, srcheight, srcUnit, NULL, NULL, NULL);
3018}
3019
3021 INT x, INT y, INT srcx, INT srcy, INT srcwidth, INT srcheight,
3022 GpUnit srcUnit)
3023{
3024 return GdipDrawImagePointRect(graphics, image, x, y, srcx, srcy, srcwidth, srcheight, srcUnit);
3025}
3026
3028 GDIPCONST GpPointF *dstpoints, INT count)
3029{
3030 UINT width, height;
3031
3032 TRACE("(%p, %p, %p, %d)\n", graphics, image, dstpoints, count);
3033
3034 if(!image)
3035 return InvalidParameter;
3036
3039
3040 return GdipDrawImagePointsRect(graphics, image, dstpoints, count, 0, 0,
3042}
3043
3045 GDIPCONST GpPoint *dstpoints, INT count)
3046{
3047 GpPointF ptf[3];
3048
3049 TRACE("(%p, %p, %p, %d)\n", graphics, image, dstpoints, count);
3050
3051 if (count != 3 || !dstpoints)
3052 return InvalidParameter;
3053
3054 ptf[0].X = (REAL)dstpoints[0].X;
3055 ptf[0].Y = (REAL)dstpoints[0].Y;
3056 ptf[1].X = (REAL)dstpoints[1].X;
3057 ptf[1].Y = (REAL)dstpoints[1].Y;
3058 ptf[2].X = (REAL)dstpoints[2].X;
3059 ptf[2].Y = (REAL)dstpoints[2].Y;
3060
3061 return GdipDrawImagePoints(graphics, image, ptf, count);
3062}
3063
3064static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
3065 unsigned int dataSize, const unsigned char *pStr, void *userdata)
3066{
3067 GdipPlayMetafileRecord(userdata, record_type, flags, dataSize, pStr);
3068 return TRUE;
3069}
3070
3072 GDIPCONST GpPointF *points, INT count, REAL srcx, REAL srcy, REAL srcwidth,
3073 REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
3074 DrawImageAbort callback, VOID * callbackData)
3075{
3076 GpPointF ptf[4];
3077 POINT pti[4];
3078 GpStatus stat;
3079
3080 TRACE("(%p, %p, %p, %d, %f, %f, %f, %f, %d, %p, %p, %p)\n", graphics, image, points,
3081 count, srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
3082 callbackData);
3083
3084 if (count > 3)
3085 return NotImplemented;
3086
3087 if(!graphics || !image || !points || count != 3)
3088 return InvalidParameter;
3089
3090 TRACE("%s %s %s\n", debugstr_pointf(&points[0]), debugstr_pointf(&points[1]),
3091 debugstr_pointf(&points[2]));
3092
3093 if (graphics->image && graphics->image->type == ImageTypeMetafile)
3094 {
3096 image, points, count, srcx, srcy, srcwidth, srcheight,
3097 srcUnit, imageAttributes, callback, callbackData);
3098 }
3099
3100 memcpy(ptf, points, 3 * sizeof(GpPointF));
3101
3102 /* Ensure source width/height is positive */
3103 if (srcwidth < 0)
3104 {
3105 GpPointF tmp = ptf[1];
3106 srcx = srcx + srcwidth;
3107 srcwidth = -srcwidth;
3108 ptf[2].X = ptf[2].X + ptf[1].X - ptf[0].X;
3109 ptf[2].Y = ptf[2].Y + ptf[1].Y - ptf[0].Y;
3110 ptf[1] = ptf[0];
3111 ptf[0] = tmp;
3112 }
3113
3114 if (srcheight < 0)
3115 {
3116 GpPointF tmp = ptf[2];
3117 srcy = srcy + srcheight;
3118 srcheight = -srcheight;
3119 ptf[1].X = ptf[1].X + ptf[2].X - ptf[0].X;
3120 ptf[1].Y = ptf[1].Y + ptf[2].Y - ptf[0].Y;
3121 ptf[2] = ptf[0];
3122 ptf[0] = tmp;
3123 }
3124
3125 ptf[3].X = ptf[2].X + ptf[1].X - ptf[0].X;
3126 ptf[3].Y = ptf[2].Y + ptf[1].Y - ptf[0].Y;
3127 if (!srcwidth || !srcheight || (ptf[3].X == ptf[0].X && ptf[3].Y == ptf[0].Y))
3128 return Ok;
3130 round_points(pti, ptf, 4);
3131
3132 TRACE("%s %s %s %s\n", wine_dbgstr_point(&pti[0]), wine_dbgstr_point(&pti[1]),
3133 wine_dbgstr_point(&pti[2]), wine_dbgstr_point(&pti[3]));
3134
3135 srcx = units_to_pixels(srcx, srcUnit, image->xres);
3136 srcy = units_to_pixels(srcy, srcUnit, image->yres);
3137 srcwidth = units_to_pixels(srcwidth, srcUnit, image->xres);
3138 srcheight = units_to_pixels(srcheight, srcUnit, image->yres);
3139 TRACE("src pixels: %f,%f %fx%f\n", srcx, srcy, srcwidth, srcheight);
3140
3141 if (image->type == ImageTypeBitmap)
3142 {
3144 BOOL do_resampling = FALSE;
3145 BOOL use_software = FALSE;
3146
3147 TRACE("graphics: %.2fx%.2f dpi, fmt %#x, scale %f, image: %.2fx%.2f dpi, fmt %#x, color %08x\n",
3148 graphics->xres, graphics->yres,
3149 graphics->image && graphics->image->type == ImageTypeBitmap ? ((GpBitmap *)graphics->image)->format : 0,
3150 graphics->scale, image->xres, image->yres, bitmap->format,
3151 imageAttributes ? imageAttributes->outside_color : 0);
3152
3153 if (ptf[1].Y != ptf[0].Y || ptf[2].X != ptf[0].X ||
3154 ptf[1].X - ptf[0].X != srcwidth || ptf[2].Y - ptf[0].Y != srcheight ||
3155 srcx < 0 || srcy < 0 ||
3156 srcx + srcwidth > bitmap->width || srcy + srcheight > bitmap->height)
3157 do_resampling = TRUE;
3158
3159 if (imageAttributes || graphics->alpha_hdc || do_resampling ||
3160 (graphics->image && graphics->image->type == ImageTypeBitmap))
3161 use_software = TRUE;
3162
3163 if (use_software)
3164 {
3165 RECT dst_area;
3167 GpRect src_area;
3168 int i, x, y, src_stride, dst_stride;
3169 GpMatrix dst_to_src;
3170 REAL m11, m12, m21, m22, mdx, mdy;
3171 LPBYTE src_data, dst_data, dst_dyn_data=NULL;
3172 BitmapData lockeddata;
3173 InterpolationMode interpolation = graphics->interpolation;
3174 PixelOffsetMode offset_mode = graphics->pixeloffset;
3175 GpPointF dst_to_src_points[3] = {{0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}};
3176 REAL x_dx, x_dy, y_dx, y_dy;
3177 static const GpImageAttributes defaultImageAttributes = {WrapModeClamp, 0, FALSE};
3178
3179 if (!imageAttributes)
3180 imageAttributes = &defaultImageAttributes;
3181
3182 dst_area.left = dst_area.right = pti[0].x;
3183 dst_area.top = dst_area.bottom = pti[0].y;
3184 for (i=1; i<4; i++)
3185 {
3186 if (dst_area.left > pti[i].x) dst_area.left = pti[i].x;
3187 if (dst_area.right < pti[i].x) dst_area.right = pti[i].x;
3188 if (dst_area.top > pti[i].y) dst_area.top = pti[i].y;
3189 if (dst_area.bottom < pti[i].y) dst_area.bottom = pti[i].y;
3190 }
3191
3193 if (stat != Ok) return stat;
3194
3195 if (graphics_bounds.X > dst_area.left) dst_area.left = floorf(graphics_bounds.X);
3196 if (graphics_bounds.Y > dst_area.top) dst_area.top = floorf(graphics_bounds.Y);
3197 if (graphics_bounds.X + graphics_bounds.Width < dst_area.right) dst_area.right = ceilf(graphics_bounds.X + graphics_bounds.Width);
3198 if (graphics_bounds.Y + graphics_bounds.Height < dst_area.bottom) dst_area.bottom = ceilf(graphics_bounds.Y + graphics_bounds.Height);
3199
3200 TRACE("dst_area: %s\n", wine_dbgstr_rect(&dst_area));
3201
3202 if (IsRectEmpty(&dst_area)) return Ok;
3203
3204 m11 = (ptf[1].X - ptf[0].X) / srcwidth;
3205 m21 = (ptf[2].X - ptf[0].X) / srcheight;
3206 mdx = ptf[0].X - m11 * srcx - m21 * srcy;
3207 m12 = (ptf[1].Y - ptf[0].Y) / srcwidth;
3208 m22 = (ptf[2].Y - ptf[0].Y) / srcheight;
3209 mdy = ptf[0].Y - m12 * srcx - m22 * srcy;
3210
3211 GdipSetMatrixElements(&dst_to_src, m11, m12, m21, m22, mdx, mdy);
3212
3213 stat = GdipInvertMatrix(&dst_to_src);
3214 if (stat != Ok) return stat;
3215
3216 if (do_resampling)
3217 {
3218 get_bitmap_sample_size(interpolation, imageAttributes->wrap,
3219 bitmap, srcx, srcy, srcwidth, srcheight, &src_area);
3220 }
3221 else
3222 {
3223 /* Make sure src_area is equal in size to dst_area. */
3224 src_area.X = srcx + dst_area.left - pti[0].x;
3225 src_area.Y = srcy + dst_area.top - pti[0].y;
3226 src_area.Width = dst_area.right - dst_area.left;
3227 src_area.Height = dst_area.bottom - dst_area.top;
3228 }
3229
3230 TRACE("src_area: %d x %d\n", src_area.Width, src_area.Height);
3231
3232 src_data = heap_alloc_zero(sizeof(ARGB) * src_area.Width * src_area.Height);
3233 if (!src_data)
3234 return OutOfMemory;
3235 src_stride = sizeof(ARGB) * src_area.Width;
3236
3237 /* Read the bits we need from the source bitmap into a compatible buffer. */
3238 lockeddata.Width = src_area.Width;
3239 lockeddata.Height = src_area.Height;
3240 lockeddata.Stride = src_stride;
3241 lockeddata.Scan0 = src_data;
3242 if (!do_resampling && bitmap->format == PixelFormat32bppPARGB)
3243 lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format);
3244 else if (imageAttributes != &defaultImageAttributes)
3245 lockeddata.PixelFormat = PixelFormat32bppARGB;
3246 else
3248
3250 lockeddata.PixelFormat, &lockeddata);
3251
3252 if (stat == Ok)
3253 stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
3254
3255 if (stat != Ok)
3256 {
3257 heap_free(src_data);
3258 return stat;
3259 }
3260
3261 apply_image_attributes(imageAttributes, src_data,
3262 src_area.Width, src_area.Height,
3263 src_stride, ColorAdjustTypeBitmap, lockeddata.PixelFormat);
3264
3265 if (do_resampling)
3266 {
3267 REAL delta_xx, delta_xy, delta_yx, delta_yy;
3268
3269 /* Transform the bits as needed to the destination. */
3270 dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
3271 if (!dst_data)
3272 {
3273 heap_free(src_data);
3274 return OutOfMemory;
3275 }
3276
3277 dst_stride = sizeof(ARGB) * (dst_area.right - dst_area.left);
3278
3279 GdipTransformMatrixPoints(&dst_to_src, dst_to_src_points, 3);
3280
3281 x_dx = dst_to_src_points[1].X - dst_to_src_points[0].X;
3282 x_dy = dst_to_src_points[1].Y - dst_to_src_points[0].Y;
3283 y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
3284 y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
3285
3286 delta_yy = dst_area.top * y_dy;
3287 delta_yx = dst_area.top * y_dx;
3288
3289 for (y=dst_area.top; y<dst_area.bottom; y++)
3290 {
3291 delta_xx = dst_area.left * x_dx;
3292 delta_xy = dst_area.left * x_dy;
3293
3294 for (x=dst_area.left; x<dst_area.right; x++)
3295 {
3296 GpPointF src_pointf;
3297 ARGB *dst_color;
3298
3299 src_pointf.X = dst_to_src_points[0].X + delta_xx + delta_yx;
3300 src_pointf.Y = dst_to_src_points[0].Y + delta_xy + delta_yy;
3301
3302 dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
3303
3304 if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
3305 {
3306 if (lockeddata.PixelFormat != PixelFormat32bppPARGB)
3307 *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
3308 imageAttributes, interpolation, offset_mode);
3309 else
3310 *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
3311 imageAttributes, interpolation, offset_mode);
3312 }
3313 else
3314 *dst_color = 0;
3315
3316 delta_xx += x_dx;
3317 delta_yx += y_dx;
3318 }
3319
3320 delta_xy += x_dy;
3321 delta_yy += y_dy;
3322 }
3323 }
3324 else
3325 {
3326 dst_data = src_data;
3327 dst_stride = src_stride;
3328 }
3329
3330 gdi_transform_acquire(graphics);
3331
3332 stat = alpha_blend_pixels(graphics, dst_area.left, dst_area.top,
3333 dst_data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, dst_stride,
3334 lockeddata.PixelFormat);
3335
3336 gdi_transform_release(graphics);
3337
3338 heap_free(src_data);
3339
3340 heap_free(dst_dyn_data);
3341
3342 return stat;
3343 }
3344 else
3345 {
3346 HDC hdc;
3347 BOOL temp_hdc = FALSE, temp_bitmap = FALSE;
3348 HBITMAP hbitmap, old_hbm=NULL;
3349 HRGN hrgn;
3350 INT save_state;
3351
3352 if (!(bitmap->format == PixelFormat16bppRGB555 ||
3353 bitmap->format == PixelFormat24bppRGB ||
3354 bitmap->format == PixelFormat32bppRGB ||
3355 bitmap->format == PixelFormat32bppPARGB))
3356 {
3357 BITMAPINFOHEADER bih;
3358 BYTE *temp_bits;
3360
3361 /* we can't draw a bitmap of this format directly */
3363 temp_hdc = TRUE;
3364 temp_bitmap = TRUE;
3365
3366 bih.biSize = sizeof(BITMAPINFOHEADER);
3367 bih.biWidth = bitmap->width;
3368 bih.biHeight = -bitmap->height;
3369 bih.biPlanes = 1;
3370 bih.biBitCount = 32;
3371 bih.biCompression = BI_RGB;
3372 bih.biSizeImage = 0;
3373 bih.biXPelsPerMeter = 0;
3374 bih.biYPelsPerMeter = 0;
3375 bih.biClrUsed = 0;
3376 bih.biClrImportant = 0;
3377
3379 (void**)&temp_bits, NULL, 0);
3380
3383 else
3385
3387 bitmap->width*4, temp_bits, dst_format,
3388 bitmap->stride, bitmap->bits, bitmap->format,
3389 bitmap->image.palette);
3390 }
3391 else
3392 {
3393 if (bitmap->hbitmap)
3394 hbitmap = bitmap->hbitmap;
3395 else
3396 {
3398 temp_bitmap = TRUE;
3399 }
3400
3401 hdc = bitmap->hdc;
3402 temp_hdc = (hdc == 0);
3403 }
3404
3405 if (temp_hdc)
3406 {
3407 if (!hdc) hdc = CreateCompatibleDC(0);
3408 old_hbm = SelectObject(hdc, hbitmap);
3409 }
3410
3411 save_state = SaveDC(graphics->hdc);
3412
3413 stat = get_clip_hrgn(graphics, &hrgn);
3414
3415 if (stat == Ok)
3416 {
3417 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
3419 }
3420
3421 gdi_transform_acquire(graphics);
3422
3424 {
3425 gdi_alpha_blend(graphics, pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y,
3426 hdc, srcx, srcy, srcwidth, srcheight);
3427 }
3428 else
3429 {
3430 StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y,
3431 hdc, srcx, srcy, srcwidth, srcheight, SRCCOPY);
3432 }
3433
3434 gdi_transform_release(graphics);
3435
3436 RestoreDC(graphics->hdc, save_state);
3437
3438 if (temp_hdc)
3439 {
3440 SelectObject(hdc, old_hbm);
3441 DeleteDC(hdc);
3442 }
3443
3444 if (temp_bitmap)
3446 }
3447 }
3448 else if (image->type == ImageTypeMetafile && ((GpMetafile*)image)->hemf)
3449 {
3450 GpRectF rc;
3451
3452 rc.X = srcx;
3453 rc.Y = srcy;
3454 rc.Width = srcwidth;
3455 rc.Height = srcheight;
3456
3458 points, count, &rc, srcUnit, play_metafile_proc, image, imageAttributes);
3459 }
3460 else
3461 {
3462 WARN("GpImage with nothing we can draw (metafile in wrong state?)\n");
3463 return InvalidParameter;
3464 }
3465
3466 return Ok;
3467}
3468
3470 GDIPCONST GpPoint *points, INT count, INT srcx, INT srcy, INT srcwidth,
3471 INT srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
3472 DrawImageAbort callback, VOID * callbackData)
3473{
3474 GpPointF pointsF[3];
3475 INT i;
3476
3477 TRACE("(%p, %p, %p, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n", graphics, image, points, count,
3478 srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
3479 callbackData);
3480
3481 if(!points || count!=3)
3482 return InvalidParameter;
3483
3484 for(i = 0; i < count; i++){
3485 pointsF[i].X = (REAL)points[i].X;
3486 pointsF[i].Y = (REAL)points[i].Y;
3487 }
3488
3489 return GdipDrawImagePointsRect(graphics, image, pointsF, count, (REAL)srcx, (REAL)srcy,
3490 (REAL)srcwidth, (REAL)srcheight, srcUnit, imageAttributes,
3491 callback, callbackData);
3492}
3493
3495 REAL dstx, REAL dsty, REAL dstwidth, REAL dstheight, REAL srcx, REAL srcy,
3496 REAL srcwidth, REAL srcheight, GpUnit srcUnit,
3498 VOID * callbackData)
3499{
3500 GpPointF points[3];
3501
3502 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p, %p, %p)\n",
3503 graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
3504 srcwidth, srcheight, srcUnit, imageattr, callback, callbackData);
3505
3506 points[0].X = dstx;
3507 points[0].Y = dsty;
3508 points[1].X = dstx + dstwidth;
3509 points[1].Y = dsty;
3510 points[2].X = dstx;
3511 points[2].Y = dsty + dstheight;
3512
3513 return GdipDrawImagePointsRect(graphics, image, points, 3, srcx, srcy,
3514 srcwidth, srcheight, srcUnit, imageattr, callback, callbackData);
3515}
3516
3518 INT dstx, INT dsty, INT dstwidth, INT dstheight, INT srcx, INT srcy,
3519 INT srcwidth, INT srcheight, GpUnit srcUnit,
3521 VOID * callbackData)
3522{
3523 GpPointF points[3];
3524
3525 TRACE("(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n",
3526 graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
3527 srcwidth, srcheight, srcUnit, imageAttributes, callback, callbackData);
3528
3529 points[0].X = dstx;
3530 points[0].Y = dsty;
3531 points[1].X = dstx + dstwidth;
3532 points[1].Y = dsty;
3533 points[2].X = dstx;
3534 points[2].Y = dsty + dstheight;
3535
3536 return GdipDrawImagePointsRect(graphics, image, points, 3, srcx, srcy,
3537 srcwidth, srcheight, srcUnit, imageAttributes, callback, callbackData);
3538}
3539
3542{
3543 RectF bounds;
3544 GpUnit unit;
3545 GpStatus ret;
3546
3547 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, image, x, y, width, height);
3548
3549 if(!graphics || !image)
3550 return InvalidParameter;
3551
3552 ret = GdipGetImageBounds(image, &bounds, &unit);
3553 if(ret != Ok)
3554 return ret;
3555
3556 return GdipDrawImageRectRect(graphics, image, x, y, width, height,
3557 bounds.X, bounds.Y, bounds.Width, bounds.Height,
3558 unit, NULL, NULL, NULL);
3559}
3560
3562 INT x, INT y, INT width, INT height)
3563{
3564 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, image, x, y, width, height);
3565
3566 return GdipDrawImageRect(graphics, image, (REAL)x, (REAL)y, (REAL)width, (REAL)height);
3567}
3568
3570 REAL y1, REAL x2, REAL y2)
3571{
3572 GpPointF pt[2];
3573
3574 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1, x2, y2);
3575
3576 if (!pen)
3577 return InvalidParameter;
3578
3579 if (pen->unit == UnitPixel && pen->width <= 0.0)
3580 return Ok;
3581
3582 pt[0].X = x1;
3583 pt[0].Y = y1;
3584 pt[1].X = x2;
3585 pt[1].Y = y2;
3586 return GdipDrawLines(graphics, pen, pt, 2);
3587}
3588
3590 INT y1, INT x2, INT y2)
3591{
3592 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x1, y1, x2, y2);
3593
3594 return GdipDrawLine(graphics, pen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
3595}
3596
3599{
3601 GpPath *path;
3602
3603 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
3604
3605 if(!pen || !graphics || (count < 2))
3606 return InvalidParameter;
3607
3608 if(graphics->busy)
3609 return ObjectBusy;
3610
3612 if (status != Ok) return status;
3613
3615 if (status == Ok)
3616 status = GdipDrawPath(graphics, pen, path);
3617
3619 return status;
3620}
3621
3624{
3625 GpStatus retval;
3626 GpPointF *ptf;
3627 int i;
3628
3629 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
3630
3631 ptf = heap_alloc_zero(count * sizeof(GpPointF));
3632 if(!ptf) return OutOfMemory;
3633
3634 for(i = 0; i < count; i ++){
3635 ptf[i].X = (REAL) points[i].X;
3636 ptf[i].Y = (REAL) points[i].Y;
3637 }
3638
3639 retval = GdipDrawLines(graphics, pen, ptf, count);
3640
3641 heap_free(ptf);
3642 return retval;
3643}
3644
3646{
3647 INT save_state;
3648 GpStatus retval;
3649 HRGN hrgn=NULL;
3650
3651 save_state = prepare_dc(graphics, pen);
3652
3653 retval = get_clip_hrgn(graphics, &hrgn);
3654
3655 if (retval != Ok)
3656 goto end;
3657
3658 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
3659
3660 gdi_transform_acquire(graphics);
3661
3662 retval = draw_poly(graphics, pen, path->pathdata.Points,
3663 path->pathdata.Types, path->pathdata.Count, TRUE);
3664
3665 gdi_transform_release(graphics);
3666
3667end:
3668 restore_dc(graphics, save_state);
3670
3671 return retval;
3672}
3673
3675{
3676 GpStatus stat;
3677 GpPath* flat_path;
3679 GpRectF gp_bound_rect;
3680 GpRect gp_output_area;
3681 RECT output_area;
3682 INT output_height, output_width;
3683 DWORD *output_bits, *brush_bits=NULL;
3684 int i;
3685 static const BYTE static_dash_pattern[] = {1,1,1,0,1,0,1,0};
3686 const BYTE *dash_pattern;
3687 INT dash_pattern_size;
3688 BYTE *dyn_dash_pattern = NULL;
3689
3690 stat = GdipClonePath(path, &flat_path);
3691
3692 if (stat != Ok)
3693 return stat;
3694
3696
3697 if (stat == Ok)
3698 {
3701
3702 if (stat == Ok)
3703 stat = GdipFlattenPath(flat_path, transform, 1.0);
3704
3706 }
3707
3708 /* estimate the output size in pixels, can be larger than necessary */
3709 if (stat == Ok)
3710 {
3711 output_area.left = floorf(flat_path->pathdata.Points[0].X);
3712 output_area.right = ceilf(flat_path->pathdata.Points[0].X);
3713 output_area.top = floorf(flat_path->pathdata.Points[0].Y);
3714 output_area.bottom = ceilf(flat_path->pathdata.Points[0].Y);
3715
3716 for (i=1; i<flat_path->pathdata.Count; i++)
3717 {
3718 REAL x, y;
3719 x = flat_path->pathdata.Points[i].X;
3720 y = flat_path->pathdata.Points[i].Y;
3721
3722 if (floorf(x) < output_area.left) output_area.left = floorf(x);
3723 if (floorf(y) < output_area.top) output_area.top = floorf(y);
3724 if (ceilf(x) > output_area.right) output_area.right = ceilf(x);
3725 if (ceilf(y) > output_area.bottom) output_area.bottom = ceilf(y);
3726 }
3727
3728 stat = get_graphics_device_bounds(graphics, &gp_bound_rect);
3729 }
3730
3731 if (stat == Ok)
3732 {
3733 output_area.left = max(output_area.left, floorf(gp_bound_rect.X));
3734 output_area.top = max(output_area.top, floorf(gp_bound_rect.Y));
3735 output_area.right = min(output_area.right, ceilf(gp_bound_rect.X + gp_bound_rect.Width));
3736 output_area.bottom = min(output_area.bottom, ceilf(gp_bound_rect.Y + gp_bound_rect.Height));
3737
3738 output_width = output_area.right - output_area.left + 1;
3739 output_height = output_area.bottom - output_area.top + 1;
3740
3741 if (output_width <= 0 || output_height <= 0)
3742 {
3743 GdipDeletePath(flat_path);
3744 return Ok;
3745 }
3746
3747 gp_output_area.X = output_area.left;
3748 gp_output_area.Y = output_area.top;
3749 gp_output_area.Width = output_width;
3750 gp_output_area.Height = output_height;
3751
3752 output_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD));
3753 if (!output_bits)
3754 stat = OutOfMemory;
3755 }
3756
3757 if (stat == Ok)
3758 {
3759 if (pen->brush->bt != BrushTypeSolidColor)
3760 {
3761 /* allocate and draw brush output */
3762 brush_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD));
3763
3764 if (brush_bits)
3765 {
3766 stat = brush_fill_pixels(graphics, pen->brush, brush_bits,
3767 &gp_output_area, output_width);
3768 }
3769 else
3770 stat = OutOfMemory;
3771 }
3772
3773 if (stat == Ok)
3774 {
3775 /* convert dash pattern to bool array */
3776 switch (pen->dash)
3777 {
3778 case DashStyleCustom:
3779 {
3780 dash_pattern_size = 0;
3781
3782 for (i=0; i < pen->numdashes; i++)
3783 dash_pattern_size += gdip_round(pen->dashes[i]);
3784
3785 if (dash_pattern_size != 0)
3786 {
3787 dash_pattern = dyn_dash_pattern = heap_alloc(dash_pattern_size);
3788
3789 if (dyn_dash_pattern)
3790 {
3791 int j=0;
3792 for (i=0; i < pen->numdashes; i++)
3793 {
3794 int k;
3795 for (k=0; k < gdip_round(pen->dashes[i]); k++)
3796 dyn_dash_pattern[j++] = (i&1)^1;
3797 }
3798 }
3799 else
3800 stat = OutOfMemory;
3801
3802 break;
3803 }
3804 /* else fall through */
3805 }
3806 case DashStyleSolid:
3807 default:
3808 dash_pattern = static_dash_pattern;
3809 dash_pattern_size = 1;
3810 break;
3811 case DashStyleDash:
3812 dash_pattern = static_dash_pattern;
3813 dash_pattern_size = 4;
3814 break;
3815 case DashStyleDot:
3816 dash_pattern = &static_dash_pattern[4];
3817 dash_pattern_size = 2;
3818 break;
3819 case DashStyleDashDot:
3820 dash_pattern = static_dash_pattern;
3821 dash_pattern_size = 6;
3822 break;
3824 dash_pattern = static_dash_pattern;
3825 dash_pattern_size = 8;
3826 break;
3827 }
3828 }
3829
3830 if (stat == Ok)
3831 {
3832 /* trace path */
3833 GpPointF subpath_start = flat_path->pathdata.Points[0];
3834 INT prev_x = INT_MAX, prev_y = INT_MAX;
3835 int dash_pos = dash_pattern_size - 1;
3836
3837 for (i=0; i < flat_path->pathdata.Count; i++)
3838 {
3839 BYTE type, type2;
3840 GpPointF start_point, end_point;
3841 GpPoint start_pointi, end_pointi;
3842
3843 type = flat_path->pathdata.Types[i];
3844 if (i+1 < flat_path->pathdata.Count)
3845 type2 = flat_path->pathdata.Types[i+1];
3846 else
3847 type2 = PathPointTypeStart;
3848
3849 start_point = flat_path->pathdata.Points[i];
3850
3852 subpath_start = start_point;
3853
3855 end_point = subpath_start;
3856 else if ((type2 & PathPointTypePathTypeMask) == PathPointTypeStart)
3857 continue;
3858 else
3859 end_point = flat_path->pathdata.Points[i+1];
3860
3861 start_pointi.X = floorf(start_point.X);
3862 start_pointi.Y = floorf(start_point.Y);
3863 end_pointi.X = floorf(end_point.X);
3864 end_pointi.Y = floorf(end_point.Y);
3865
3866 if(start_pointi.X == end_pointi.X && start_pointi.Y == end_pointi.Y)
3867 continue;
3868
3869 /* draw line segment */
3870 if (abs(start_pointi.Y - end_pointi.Y) > abs(start_pointi.X - end_pointi.X))
3871 {
3872 INT x, y, start_y, end_y, step;
3873
3874 if (start_pointi.Y < end_pointi.Y)
3875 {
3876 step = 1;
3877 start_y = ceilf(start_point.Y) - output_area.top;
3878 end_y = end_pointi.Y - output_area.top;
3879 }
3880 else
3881 {
3882 step = -1;
3883 start_y = start_point.Y - output_area.top;
3884 end_y = ceilf(end_point.Y) - output_area.top;
3885 }
3886
3887 for (y=start_y; y != (end_y+step); y+=step)
3888 {
3889 x = gdip_round( start_point.X +
3890 (end_point.X - start_point.X) * (y + output_area.top - start_point.Y) / (end_point.Y - start_point.Y) )
3891 - output_area.left;
3892
3893 if (x == prev_x && y == prev_y)
3894 continue;
3895
3896 prev_x = x;
3897 prev_y = y;
3898 dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1;
3899
3900 if (!dash_pattern[dash_pos])
3901 continue;
3902
3903 if (x < 0 || x >= output_width || y < 0 || y >= output_height)
3904 continue;
3905
3906 if (brush_bits)
3907 output_bits[x + y*output_width] = brush_bits[x + y*output_width];
3908 else
3909 output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color;
3910 }
3911 }
3912 else
3913 {
3914 INT x, y, start_x, end_x, step;
3915
3916 if (start_pointi.X < end_pointi.X)
3917 {
3918 step = 1;
3919 start_x = ceilf(start_point.X) - output_area.left;
3920 end_x = end_pointi.X - output_area.left;
3921 }
3922 else
3923 {
3924 step = -1;
3925 start_x = start_point.X - output_area.left;
3926 end_x = ceilf(end_point.X) - output_area.left;
3927 }
3928
3929 for (x=start_x; x != (end_x+step); x+=step)
3930 {
3931 y = gdip_round( start_point.Y +
3932 (end_point.Y - start_point.Y) * (x + output_area.left - start_point.X) / (end_point.X - start_point.X) )
3933 - output_area.top;
3934
3935 if (x == prev_x && y == prev_y)
3936 continue;
3937
3938 prev_x = x;
3939 prev_y = y;
3940 dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1;
3941
3942 if (!dash_pattern[dash_pos])
3943 continue;
3944
3945 if (x < 0 || x >= output_width || y < 0 || y >= output_height)
3946 continue;
3947
3948 if (brush_bits)
3949 output_bits[x + y*output_width] = brush_bits[x + y*output_width];
3950 else
3951 output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color;
3952 }
3953 }
3954 }
3955 }
3956
3957 /* draw output image */
3958 if (stat == Ok)
3959 {
3960 gdi_transform_acquire(graphics);
3961
3962 stat = alpha_blend_pixels(graphics, output_area.left, output_area.top,
3963 (BYTE*)output_bits, output_width, output_height, output_width * 4,
3965
3966 gdi_transform_release(graphics);
3967 }
3968
3969 heap_free(brush_bits);
3970 heap_free(dyn_dash_pattern);
3971 heap_free(output_bits);
3972 }
3973
3974 GdipDeletePath(flat_path);
3975
3976 return stat;
3977}
3978
3980{
3981 GpStatus stat;
3982 GpPath *wide_path;
3984 REAL flatness=1.0;
3985
3986 /* Check if the final pen thickness in pixels is too thin. */
3987 if (pen->unit == UnitPixel)
3988 {
3989 if (pen->width < 1.415)
3990 return SOFTWARE_GdipDrawThinPath(graphics, pen, path);
3991 }
3992 else
3993 {
3994 GpPointF points[3] = {{0,0}, {1,0}, {0,1}};
3995
3996 points[1].X = pen->width;
3997 points[2].Y = pen->width;
3998
4001
4002 if (stat != Ok)
4003 return stat;
4004
4005 if (((points[1].X-points[0].X)*(points[1].X-points[0].X) +
4006 (points[1].Y-points[0].Y)*(points[1].Y-points[0].Y) < 2.0001) &&
4007 ((points[2].X-points[0].X)*(points[2].X-points[0].X) +
4008 (points[2].Y-points[0].Y)*(points[2].Y-points[0].Y) < 2.0001))
4009 return SOFTWARE_GdipDrawThinPath(graphics, pen, path);
4010 }
4011
4012 stat = GdipClonePath(path, &wide_path);
4013
4014 if (stat != Ok)
4015 return stat;
4016
4017 if (pen->unit == UnitPixel)
4018 {
4019 /* We have to transform this to device coordinates to get the widths right. */
4021
4022 if (stat == Ok)
4025 }
4026 else
4027 {
4028 /* Set flatness based on the final coordinate space */
4029 GpMatrix t;
4030
4033
4034 if (stat != Ok)
4035 return stat;
4036
4037 flatness = 1.0/sqrt(fmax(
4038 t.matrix[0] * t.matrix[0] + t.matrix[1] * t.matrix[1],
4039 t.matrix[2] * t.matrix[2] + t.matrix[3] * t.matrix[3]));
4040 }
4041
4042 if (stat == Ok)
4043 stat = GdipWidenPath(wide_path, pen, transform, flatness);
4044
4045 if (pen->unit == UnitPixel)
4046 {
4047 /* Transform the path back to world coordinates */
4048 if (stat == Ok)
4050
4051 if (stat == Ok)
4052 stat = GdipTransformPath(wide_path, transform);
4053 }
4054
4055 /* Actually draw the path */
4056 if (stat == Ok)
4057 stat = GdipFillPath(graphics, pen->brush, wide_path);
4058
4060
4061 GdipDeletePath(wide_path);
4062
4063 return stat;
4064}
4065
4067{
4068 GpStatus retval;
4069
4070 TRACE("(%p, %p, %p)\n", graphics, pen, path);
4071
4072 if(!pen || !graphics)
4073 return InvalidParameter;
4074
4075 if(graphics->busy)
4076 return ObjectBusy;
4077
4078 if (path->pathdata.Count == 0)
4079 return Ok;
4080
4081 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4082 retval = METAFILE_DrawPath((GpMetafile*)graphics->image, pen, path);
4083 else if (!graphics->hdc || graphics->alpha_hdc || !brush_can_fill_path(pen->brush, FALSE))
4084 retval = SOFTWARE_GdipDrawPath(graphics, pen, path);
4085 else
4086 retval = GDI32_GdipDrawPath(graphics, pen, path);
4087
4088 return retval;
4089}
4090
4092 REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
4093{
4095 GpPath *path;
4096
4097 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y,
4098 width, height, startAngle, sweepAngle);
4099
4100 if(!graphics || !pen)
4101 return InvalidParameter;
4102
4103 if(graphics->busy)
4104 return ObjectBusy;
4105
4107 if (status != Ok) return status;
4108
4109 status = GdipAddPathPie(path, x, y, width, height, startAngle, sweepAngle);
4110 if (status == Ok)
4111 status = GdipDrawPath(graphics, pen, path);
4112
4114 return status;
4115}
4116
4118 INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
4119{
4120 TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n", graphics, pen, x, y,
4121 width, height, startAngle, sweepAngle);
4122
4123 return GdipDrawPie(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
4124}
4125
4128{
4130 GpPath *path;
4131
4132 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y, width, height);
4133
4134 if(!pen || !graphics)
4135 return InvalidParameter;
4136
4137 if(graphics->busy)
4138 return ObjectBusy;
4139
4141 if (status != Ok) return status;
4142
4144 if (status == Ok)
4145 status = GdipDrawPath(graphics, pen, path);
4146
4148 return status;
4149}
4150
4152 INT y, INT width, INT height)
4153{
4154 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x, y, width, height);
4155
4156 return GdipDrawRectangle(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
4157}
4158
4160 GDIPCONST GpRectF* rects, INT count)
4161{
4163 GpPath *path;
4164
4165 TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
4166
4167 if(!graphics || !pen || !rects || count < 1)
4168 return InvalidParameter;
4169
4170 if(graphics->busy)
4171 return ObjectBusy;
4172
4174 if (status != Ok) return status;
4175
4177 if (status == Ok)
4178 status = GdipDrawPath(graphics, pen, path);
4179
4181 return status;
4182}
4183
4185 GDIPCONST GpRect* rects, INT count)
4186{
4187 GpRectF *rectsF;
4188 GpStatus ret;
4189 INT i;
4190
4191 TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
4192
4193 if(!rects || count<=0)
4194 return InvalidParameter;
4195
4196 rectsF = heap_alloc_zero(sizeof(GpRectF) * count);
4197 if(!rectsF)
4198 return OutOfMemory;
4199
4200 for(i = 0;i < count;i++){
4201 rectsF[i].X = (REAL)rects[i].X;
4202 rectsF[i].Y = (REAL)rects[i].Y;
4203 rectsF[i].Width = (REAL)rects[i].Width;
4204 rectsF[i].Height = (REAL)rects[i].Height;
4205 }
4206
4207 ret = GdipDrawRectangles(graphics, pen, rectsF, count);
4208 heap_free(rectsF);
4209
4210 return ret;
4211}
4212
4215{
4216 GpPath *path;
4218
4219 TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
4220 count, tension, fill);
4221
4222 if(!graphics || !brush || !points)
4223 return InvalidParameter;
4224
4225 if(graphics->busy)
4226 return ObjectBusy;
4227
4228 if(count == 1) /* Do nothing */
4229 return Ok;
4230
4232 if (status != Ok) return status;
4233
4235 if (status == Ok)
4236 status = GdipFillPath(graphics, brush, path);
4237
4239 return status;
4240}
4241
4244{
4245 GpPointF *ptf;
4246 GpStatus stat;
4247 INT i;
4248
4249 TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
4250 count, tension, fill);
4251
4252 if(!points || count == 0)
4253 return InvalidParameter;
4254
4255 if(count == 1) /* Do nothing */
4256 return Ok;
4257
4258 ptf = heap_alloc_zero(sizeof(GpPointF)*count);
4259 if(!ptf)
4260 return OutOfMemory;
4261
4262 for(i = 0;i < count;i++){
4263 ptf[i].X = (REAL)points[i].X;
4264 ptf[i].Y = (REAL)points[i].Y;
4265 }
4266
4267 stat = GdipFillClosedCurve2(graphics, brush, ptf, count, tension, fill);
4268
4269 heap_free(ptf);
4270
4271 return stat;
4272}
4273
4276{
4277 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4278 return GdipFillClosedCurve2(graphics, brush, points, count,
4279 0.5f, FillModeAlternate);
4280}
4281
4284{
4285 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4286 return GdipFillClosedCurve2I(graphics, brush, points, count,
4287 0.5f, FillModeAlternate);
4288}
4289
4292{
4293 GpStatus stat;
4294 GpPath *path;
4295
4296 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
4297
4298 if(!graphics || !brush)
4299 return InvalidParameter;
4300
4301 if(graphics->busy)
4302 return ObjectBusy;
4303
4305
4306 if (stat == Ok)
4307 {
4309
4310 if (stat == Ok)
4311 stat = GdipFillPath(graphics, brush, path);
4312
4314 }
4315
4316 return stat;
4317}
4318
4320 INT y, INT width, INT height)
4321{
4322 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
4323
4324 return GdipFillEllipse(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
4325}
4326
4328{
4329 INT save_state;
4330 GpStatus retval;
4331 HRGN hrgn=NULL;
4332
4333 if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
4334 return NotImplemented;
4335
4336 save_state = SaveDC(graphics->hdc);
4337 EndPath(graphics->hdc);
4338 SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
4339 : WINDING));
4340
4341 retval = get_clip_hrgn(graphics, &hrgn);
4342
4343 if (retval != Ok)
4344 goto end;
4345
4346 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
4347
4348 gdi_transform_acquire(graphics);
4349
4350 BeginPath(graphics->hdc);
4351 retval = draw_poly(graphics, NULL, path->pathdata.Points,
4352 path->pathdata.Types, path->pathdata.Count, FALSE);
4353
4354 if(retval == Ok)
4355 {
4356 EndPath(graphics->hdc);
4357 retval = brush_fill_path(graphics, brush);
4358 }
4359
4360 gdi_transform_release(graphics);
4361
4362end:
4363 RestoreDC(graphics->hdc, save_state);
4365
4366 return retval;
4367}
4368
4370{
4371 GpStatus stat;
4372 GpRegion *rgn;
4373
4374 if (!brush_can_fill_pixels(brush))
4375 return NotImplemented;
4376
4377 /* FIXME: This could probably be done more efficiently without regions. */
4378
4380
4381 if (stat == Ok)
4382 {
4383 stat = GdipFillRegion(graphics, brush, rgn);
4384
4385 GdipDeleteRegion(rgn);
4386 }
4387
4388 return stat;
4389}
4390
4392{
4394
4395 TRACE("(%p, %p, %p)\n", graphics, brush, path);
4396
4397 if(!brush || !graphics || !path)
4398 return InvalidParameter;
4399
4400 if(graphics->busy)
4401 return ObjectBusy;
4402
4403 if (!path->pathdata.Count)
4404 return Ok;
4405
4406 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4407 return METAFILE_FillPath((GpMetafile*)graphics->image, brush, path);
4408
4409 if (!graphics->image && !graphics->alpha_hdc)
4410 stat = GDI32_GdipFillPath(graphics, brush, path);
4411
4412 if (stat == NotImplemented)
4413 stat = SOFTWARE_GdipFillPath(graphics, brush, path);
4414
4415 if (stat == NotImplemented)
4416 {
4417 FIXME("Not implemented for brushtype %i\n", brush->bt);
4418 stat = Ok;
4419 }
4420
4421 return stat;
4422}
4423
4425 REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
4426{
4427 GpStatus stat;
4428 GpPath *path;
4429
4430 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
4431 graphics, brush, x, y, width, height, startAngle, sweepAngle);
4432
4433 if(!graphics || !brush)
4434 return InvalidParameter;
4435
4436 if(graphics->busy)
4437 return ObjectBusy;
4438
4440
4441 if (stat == Ok)
4442 {
4443 stat = GdipAddPathPie(path, x, y, width, height, startAngle, sweepAngle);
4444
4445 if (stat == Ok)
4446 stat = GdipFillPath(graphics, brush, path);
4447
4449 }
4450
4451 return stat;
4452}
4453
4455 INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
4456{
4457 TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n",
4458 graphics, brush, x, y, width, height, startAngle, sweepAngle);
4459
4460 return GdipFillPie(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
4461}
4462
4465{
4466 GpStatus stat;
4467 GpPath *path;
4468
4469 TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
4470
4471 if(!graphics || !brush || !points || !count)
4472 return InvalidParameter;
4473
4474 if(graphics->busy)
4475 return ObjectBusy;
4476
4478
4479 if (stat == Ok)
4480 {
4482
4483 if (stat == Ok)
4484 stat = GdipFillPath(graphics, brush, path);
4485
4487 }
4488
4489 return stat;
4490}
4491
4494{
4495 GpStatus stat;
4496 GpPath *path;
4497
4498 TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
4499
4500 if(!graphics || !brush || !points || !count)
4501 return InvalidParameter;
4502
4503 if(graphics->busy)
4504 return ObjectBusy;
4505
4507
4508 if (stat == Ok)
4509 {
4511
4512 if (stat == Ok)
4513 stat = GdipFillPath(graphics, brush, path);
4514
4516 }
4517
4518 return stat;
4519}
4520
4523{
4524 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4525
4526 return GdipFillPolygon(graphics, brush, points, count, FillModeAlternate);
4527}
4528
4531{
4532 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4533
4534 return GdipFillPolygonI(graphics, brush, points, count, FillModeAlternate);
4535}
4536
4539{
4540 GpRectF rect;
4541
4542 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
4543
4544 rect.X = x;
4545 rect.Y = y;
4546 rect.Width = width;
4547 rect.Height = height;
4548
4549 return GdipFillRectangles(graphics, brush, &rect, 1);
4550}
4551
4553 INT x, INT y, INT width, INT height)
4554{
4555 GpRectF rect;
4556
4557 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
4558
4559 rect.X = (REAL)x;
4560 rect.Y = (REAL)y;
4561 rect.Width = (REAL)width;
4562 rect.Height = (REAL)height;
4563
4564 return GdipFillRectangles(graphics, brush, &rect, 1);
4565}
4566
4568 INT count)
4569{
4571 GpPath *path;
4572
4573 TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
4574
4575 if(!graphics || !brush || !rects || count <= 0)
4576 return InvalidParameter;
4577
4578 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4579 {
4580 status = METAFILE_FillRectangles((GpMetafile*)graphics->image, brush, rects, count);
4581 /* FIXME: Add gdi32 drawing. */
4582 return status;
4583 }
4584
4586 if (status != Ok) return status;
4587
4589 if (status == Ok)
4590 status = GdipFillPath(graphics, brush, path);
4591
4593 return status;
4594}
4595
4597 INT count)
4598{
4599 GpRectF *rectsF;
4600 GpStatus ret;
4601 INT i;
4602
4603 TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
4604
4605 if(!rects || count <= 0)
4606 return InvalidParameter;
4607
4608 rectsF = heap_alloc_zero(sizeof(GpRectF)*count);
4609 if(!rectsF)
4610 return OutOfMemory;
4611
4612 for(i = 0; i < count; i++){
4613 rectsF[i].X = (REAL)rects[i].X;
4614 rectsF[i].Y = (REAL)rects[i].Y;
4615 rectsF[i].Width = (REAL)rects[i].Width;
4616 rectsF[i].Height = (REAL)rects[i].Height;
4617 }
4618
4619 ret = GdipFillRectangles(graphics,brush,rectsF,count);
4620 heap_free(rectsF);
4621
4622 return ret;
4623}
4624
4626 GpRegion* region)
4627{
4628 INT save_state;
4630 HRGN hrgn;
4631 RECT rc;
4632
4633 if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
4634 return NotImplemented;
4635
4636 save_state = SaveDC(graphics->hdc);
4637 EndPath(graphics->hdc);
4638
4639 hrgn = NULL;
4640 status = get_clip_hrgn(graphics, &hrgn);
4641 if (status != Ok)
4642 {
4643 RestoreDC(graphics->hdc, save_state);
4644 return status;
4645 }
4646
4647 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
4649
4650 status = GdipGetRegionHRgn(region, graphics, &hrgn);
4651 if (status != Ok)
4652 {
4653 RestoreDC(graphics->hdc, save_state);
4654 return status;
4655 }
4656
4657 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
4659
4660 if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
4661 {
4662 BeginPath(graphics->hdc);
4663 Rectangle(graphics->hdc, rc.left, rc.top, rc.right, rc.bottom);
4664 EndPath(graphics->hdc);
4665
4666 status = brush_fill_path(graphics, brush);
4667 }
4668
4669 RestoreDC(graphics->hdc, save_state);
4670
4671
4672 return status;
4673}
4674
4676 GpRegion* region)
4677{
4678 GpStatus stat;
4679 GpRegion *temp_region;
4680 GpMatrix world_to_device;
4682 DWORD *pixel_data;
4683 HRGN hregion;
4684 RECT bound_rect;
4685 GpRect gp_bound_rect;
4686
4687 if (!brush_can_fill_pixels(brush))
4688 return NotImplemented;
4689
4690 stat = gdi_transform_acquire(graphics);
4691
4692 if (stat == Ok)
4694
4695 if (stat == Ok)
4696 stat = GdipCloneRegion(region, &temp_region);
4697
4698 if (stat == Ok)
4699 {
4701 CoordinateSpaceWorld, &world_to_device);
4702
4703 if (stat == Ok)
4704 stat = GdipTransformRegion(temp_region, &world_to_device);
4705
4706 if (stat == Ok)
4708
4709 if (stat == Ok)
4710 stat = GdipGetRegionHRgn(temp_region, NULL, &hregion);
4711
4712 GdipDeleteRegion(temp_region);
4713 }
4714
4715 if (stat == Ok && GetRgnBox(hregion, &bound_rect) == NULLREGION)
4716 {
4717 DeleteObject(hregion);
4718 gdi_transform_release(graphics);
4719 return Ok;
4720 }
4721
4722 if (stat == Ok)
4723 {
4724 gp_bound_rect.X = bound_rect.left;
4725 gp_bound_rect.Y = bound_rect.top;
4726 gp_bound_rect.Width = bound_rect.right - bound_rect.left;
4727 gp_bound_rect.Height = bound_rect.bottom - bound_rect.top;
4728
4729 pixel_data = heap_alloc_zero(sizeof(*pixel_data) * gp_bound_rect.Width * gp_bound_rect.Height);
4730 if (!pixel_data)
4731 stat = OutOfMemory;
4732
4733 if (stat == Ok)
4734 {
4735 stat = brush_fill_pixels(graphics, brush, pixel_data,
4736 &gp_bound_rect, gp_bound_rect.Width);
4737
4738 if (stat == Ok)
4739 stat = alpha_blend_pixels_hrgn(graphics, gp_bound_rect.X,
4740 gp_bound_rect.Y, (BYTE*)pixel_data, gp_bound_rect.Width,
4741 gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion,
4743
4744 heap_free(pixel_data);
4745 }
4746
4747 DeleteObject(hregion);
4748 }
4749
4750 gdi_transform_release(graphics);
4751
4752 return stat;
4753}
4754
4755/*****************************************************************************
4756 * GdipFillRegion [GDIPLUS.@]
4757 */
4759 GpRegion* region)
4760{
4762
4763 TRACE("(%p, %p, %p)\n", graphics, brush, region);
4764
4765 if (!(graphics && brush && region))
4766 return InvalidParameter;
4767
4768 if(graphics->busy)
4769 return ObjectBusy;
4770
4771 if (!graphics->image && !graphics->alpha_hdc)
4772 stat = GDI32_GdipFillRegion(graphics, brush, region);
4773
4774 if (stat == NotImplemented)
4775 stat = SOFTWARE_GdipFillRegion(graphics, brush, region);
4776
4777 if (stat == NotImplemented)
4778 {
4779 FIXME("not implemented for brushtype %i\n", brush->bt);
4780 stat = Ok;
4781 }
4782
4783 return stat;
4784}
4785
4787{
4788 TRACE("(%p,%u)\n", graphics, intention);
4789
4790 if(!graphics)
4791 return InvalidParameter;
4792
4793 if(graphics->busy)
4794 return ObjectBusy;
4795
4796 /* We have no internal operation queue, so there's no need to clear it. */
4797
4798 if (graphics->hdc)
4799 GdiFlush();
4800
4801 return Ok;
4802}
4803
4804/*****************************************************************************
4805 * GdipGetClipBounds [GDIPLUS.@]
4806 */
4808{
4810 GpRegion *clip;
4811
4812 TRACE("(%p, %p)\n", graphics, rect);
4813
4814 if(!graphics)
4815 return InvalidParameter;
4816
4817 if(graphics->busy)
4818 return ObjectBusy;
4819
4820 status = GdipCreateRegion(&clip);
4821 if (status != Ok) return status;
4822
4823 status = GdipGetClip(graphics, clip);
4824 if (status == Ok)
4825 status = GdipGetRegionBounds(clip, graphics, rect);
4826
4827 GdipDeleteRegion(clip);
4828 return status;
4829}
4830
4831/*****************************************************************************
4832 * GdipGetClipBoundsI [GDIPLUS.@]
4833 */
4835{
4836 TRACE("(%p, %p)\n", graphics, rect);
4837
4838 if(!graphics)
4839 return InvalidParameter;
4840
4841 if(graphics->busy)
4842 return ObjectBusy;
4843
4844 return GdipGetRegionBoundsI(graphics->clip, graphics, rect);
4845}
4846
4847/* FIXME: Compositing mode is not used anywhere except the getter/setter. */
4850{
4851 TRACE("(%p, %p)\n", graphics, mode);
4852
4853 if(!graphics || !mode)
4854 return InvalidParameter;
4855
4856 if(graphics->busy)
4857 return ObjectBusy;
4858
4859 *mode = graphics->compmode;
4860
4861 return Ok;
4862}
4863
4864/* FIXME: Compositing quality is not used anywhere except the getter/setter. */
4867{
4868 TRACE("(%p, %p)\n", graphics, quality);
4869
4870 if(!graphics || !quality)
4871 return InvalidParameter;
4872
4873 if(graphics->busy)
4874 return ObjectBusy;
4875
4876 *quality = graphics->compqual;
4877
4878 return Ok;
4879}
4880
4881/* FIXME: Interpolation mode is not used anywhere except the getter/setter. */
4884{
4885 TRACE("(%p, %p)\n", graphics, mode);
4886
4887 if(!graphics || !mode)
4888 return InvalidParameter;
4889
4890 if(graphics->busy)
4891 return ObjectBusy;
4892
4893 *mode = graphics->interpolation;
4894
4895 return Ok;
4896}
4897
4898/* FIXME: Need to handle color depths less than 24bpp */
4900{
4901 FIXME("(%p, %p): Passing color unmodified\n", graphics, argb);
4902
4903 if(!graphics || !argb)
4904 return InvalidParameter;
4905
4906 if(graphics->busy)
4907 return ObjectBusy;
4908
4909 return Ok;
4910}
4911
4913{
4914 TRACE("(%p, %p)\n", graphics, scale);
4915
4916 if(!graphics || !scale)
4917 return InvalidParameter;
4918
4919 if(graphics->busy)
4920 return ObjectBusy;
4921
4922 *scale = graphics->scale;
4923
4924 return Ok;
4925}
4926
4928{
4929 TRACE("(%p, %p)\n", graphics, unit);
4930
4931 if(!graphics || !unit)
4932 return InvalidParameter;
4933
4934 if(graphics->busy)
4935 return ObjectBusy;
4936
4937 *unit = graphics->unit;
4938
4939 return Ok;
4940}
4941
4942/* FIXME: Pixel offset mode is not used anywhere except the getter/setter. */
4944 *mode)
4945{
4946 TRACE("(%p, %p)\n", graphics, mode);
4947
4948 if(!graphics || !mode)
4949 return InvalidParameter;
4950
4951 if(graphics->busy)
4952 return ObjectBusy;
4953
4954 *mode = graphics->pixeloffset;
4955
4956 return Ok;
4957}
4958
4959/* FIXME: Smoothing mode is not used anywhere except the getter/setter. */
4961{
4962 TRACE("(%p, %p)\n", graphics, mode);
4963
4964 if(!graphics || !mode)
4965 return InvalidParameter;
4966
4967 if(graphics->busy)
4968 return ObjectBusy;
4969
4970 *mode = graphics->smoothing;
4971
4972 return Ok;
4973}
4974
4976{
4977 TRACE("(%p, %p)\n", graphics, contrast);
4978
4979 if(!graphics || !contrast)
4980 return InvalidParameter;
4981
4982 *contrast = graphics->textcontrast;
4983
4984 return Ok;
4985}
4986
4987/* FIXME: Text rendering hint is not used anywhere except the getter/setter. */
4990{
4991 TRACE("(%p, %p)\n", graphics, hint);
4992
4993 if(!graphics || !hint)
4994 return InvalidParameter;
4995
4996 if(graphics->busy)
4997 return ObjectBusy;
4998
4999 *hint = graphics->texthint;
5000
5001 return Ok;
5002}
5003
5005{
5006 GpRegion *clip_rgn;
5007 GpStatus stat;
5008 GpMatrix device_to_world;
5009
5010 TRACE("(%p, %p)\n", graphics, rect);
5011
5012 if(!graphics || !rect)
5013 return InvalidParameter;
5014
5015 if(graphics->busy)
5016 return ObjectBusy;
5017
5018 /* intersect window and graphics clipping regions */
5019 if((stat = GdipCreateRegion(&clip_rgn)) != Ok)
5020 return stat;
5021
5022 if((stat = get_visible_clip_region(graphics, clip_rgn)) != Ok)
5023 goto cleanup;
5024
5025 /* transform to world coordinates */
5026 if((stat = get_graphics_transform(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &device_to_world)) != Ok)
5027 goto cleanup;
5028
5029 if((stat = GdipTransformRegion(clip_rgn, &device_to_world)) != Ok)
5030 goto cleanup;
5031
5032 /* get bounds of the region */
5033 stat = GdipGetRegionBounds(clip_rgn, graphics, rect);
5034
5035cleanup:
5036 GdipDeleteRegion(clip_rgn);
5037
5038 return stat;
5039}
5040
5042{
5043 GpRectF rectf;
5044 GpStatus stat;
5045
5046 TRACE("(%p, %p)\n", graphics, rect);
5047
5048 if(!graphics || !rect)
5049 return InvalidParameter;
5050
5051 if((stat = GdipGetVisibleClipBounds(graphics, &rectf)) == Ok)
5052 {
5053 rect->X = gdip_round(rectf.X);
5054 rect->Y = gdip_round(rectf.Y);
5055 rect->Width = gdip_round(rectf.Width);
5056 rect->Height = gdip_round(rectf.Height);
5057 }
5058
5059 return stat;
5060}
5061
5063{
5064 TRACE("(%p, %p)\n", graphics, matrix);
5065
5066 if(!graphics || !matrix)
5067 return InvalidParameter;
5068
5069 if(graphics->busy)
5070 return ObjectBusy;
5071
5072 *matrix = graphics->worldtrans;
5073 return Ok;
5074}
5075
5077{
5078 GpSolidFill *brush;
5079 GpStatus stat;
5080 GpRectF wnd_rect;
5081
5082 TRACE("(%p, %x)\n", graphics, color);
5083
5084 if(!graphics)
5085 return InvalidParameter;
5086
5087 if(graphics->busy)
5088 return ObjectBusy;
5089
5090 if (graphics->image && graphics->image->type == ImageTypeMetafile)
5091 return METAFILE_GraphicsClear((GpMetafile*)graphics->image, color);
5092
5093 if((stat = GdipCreateSolidFill(color, &brush)) != Ok)
5094 return stat;
5095
5096 if((stat = GdipGetVisibleClipBounds(graphics, &wnd_rect)) != Ok){
5097 GdipDeleteBrush((GpBrush*)brush);
5098 return stat;
5099 }
5100
5101 GdipFillRectangle(graphics, (GpBrush*)brush, wnd_rect.X, wnd_rect.Y,
5102 wnd_rect.Width, wnd_rect.Height);
5103
5104 GdipDeleteBrush((GpBrush*)brush);
5105
5106 return Ok;
5107}
5108
5110{
5111 TRACE("(%p, %p)\n", graphics, res);
5112
5113 if(!graphics || !res)
5114 return InvalidParameter;
5115
5116 return GdipIsEmptyRegion(graphics->clip, graphics, res);
5117}
5118
5120{
5121 GpStatus stat;
5122 GpRegion* rgn;
5123 GpPointF pt;
5124
5125 TRACE("(%p, %.2f, %.2f, %p)\n", graphics, x, y, result);
5126
5127 if(!graphics || !result)
5128 return InvalidParameter;
5129
5130 if(graphics->busy)
5131 return ObjectBusy;
5132
5133 pt.X = x;
5134 pt.Y = y;
5136 CoordinateSpaceWorld, &pt, 1)) != Ok)
5137 return stat;
5138
5139 if((stat = GdipCreateRegion(&rgn)) != Ok)
5140 return stat;
5141
5142 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
5143 goto cleanup;
5144
5145 stat = GdipIsVisibleRegionPoint(rgn, pt.X, pt.Y, graphics, result);
5146
5147cleanup:
5148 GdipDeleteRegion(rgn);
5149 return stat;
5150}
5151
5153{
5154 return GdipIsVisiblePoint(graphics, (REAL)x, (REAL)y, result);
5155}
5156
5158{
5159 GpStatus stat;
5160 GpRegion* rgn;
5161 GpPointF pts[2];
5162
5163 TRACE("(%p %.2f %.2f %.2f %.2f %p)\n", graphics, x, y, width, height, result);
5164
5165 if(!graphics || !result)
5166 return InvalidParameter;
5167
5168 if(graphics->busy)
5169 return ObjectBusy;
5170
5171 pts[0].X = x;
5172 pts[0].Y = y;
5173 pts[1].X = x + width;
5174 pts[1].Y = y + height;
5175
5177 CoordinateSpaceWorld, pts, 2)) != Ok)
5178 return stat;
5179
5180 pts[1].X -= pts[0].X;
5181 pts[1].Y -= pts[0].Y;
5182
5183 if((stat = GdipCreateRegion(&rgn)) != Ok)
5184 return stat;
5185
5186 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
5187 goto cleanup;
5188
5189 stat = GdipIsVisibleRegionRect(rgn, pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, graphics, result);
5190
5191cleanup:
5192 GdipDeleteRegion(rgn);
5193 return stat;
5194}
5195
5197{
5198 return GdipIsVisibleRect(graphics, (REAL)x, (REAL)y, (REAL)width, (REAL)height, result);
5199}
5200
5203 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip,
5204 gdip_format_string_callback callback, void *user_data)
5205{
5206 WCHAR* stringdup;
5207 int sum = 0, height = 0, fit, fitcpy, i, j, lret, nwidth,
5208 nheight, lineend, lineno = 0;
5209 RectF bounds;
5210 StringAlignment halign;
5211 GpStatus stat = Ok;
5212 SIZE size;
5213 HotkeyPrefix hkprefix;
5214 INT *hotkeyprefix_offsets=NULL;
5215 INT hotkeyprefix_count=0;
5216 INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
5217 BOOL seen_prefix = FALSE;
5218
5219 if(length == -1) length = lstrlenW(string);
5220
5221 stringdup = heap_alloc_zero((length + 1) * sizeof(WCHAR));
5222 if(!stringdup) return OutOfMemory;
5223
5224 if (!format)
5226
5227 nwidth = rect->Width;
5228 nheight = rect->Height;
5229 if (ignore_empty_clip)
5230 {
5231 if (!nwidth) nwidth = INT_MAX;
5232 if (!nheight) nheight = INT_MAX;
5233 }
5234
5235 hkprefix = format->hkprefix;
5236
5237 if (hkprefix == HotkeyPrefixShow)
5238 {
5239 for (i=0; i<length; i++)
5240 {
5241 if (string[i] == '&')
5242 hotkeyprefix_count++;
5243 }
5244 }
5245
5246 if (hotkeyprefix_count)
5247 hotkeyprefix_offsets = heap_alloc_zero(sizeof(INT) * hotkeyprefix_count);
5248
5249 hotkeyprefix_count = 0;
5250
5251 for(i = 0, j = 0; i < length; i++){
5252 /* FIXME: This makes the indexes passed to callback inaccurate. */
5253 if(!isprintW(string[i]) && (string[i] != '\n'))
5254 continue;
5255
5256 /* FIXME: tabs should be handled using tabstops from stringformat */
5257 if (string[i] == '\t')
5258 continue;
5259
5260 if (seen_prefix && hkprefix == HotkeyPrefixShow && string[i] != '&')
5261 hotkeyprefix_offsets[hotkeyprefix_count++] = j;
5262 else if (!seen_prefix && hkprefix != HotkeyPrefixNone && string[i] == '&')
5263 {
5264 seen_prefix = TRUE;
5265 continue;
5266 }
5267
5268 seen_prefix = FALSE;
5269
5270 stringdup[j] = string[i];
5271 j++;
5272 }
5273
5274 length = j;
5275
5276 halign = format->align;
5277
5278 while(sum < length){
5279 GetTextExtentExPointW(hdc, stringdup + sum, length - sum,
5280 nwidth, &fit, NULL, &size);
5281 fitcpy = fit;
5282
5283 if(fit == 0)
5284 break;
5285
5286 for(lret = 0; lret < fit; lret++)
5287 if(*(stringdup + sum + lret) == '\n')
5288 break;
5289
5290 /* Line break code (may look strange, but it imitates windows). */
5291 if(lret < fit)
5292 lineend = fit = lret; /* this is not an off-by-one error */
5293 else if(fit < (length - sum)){
5294 if(*(stringdup + sum + fit) == ' ')
5295 while(*(stringdup + sum + fit) == ' ')
5296 fit++;
5297 else
5298 while(*(stringdup + sum + fit - 1) != ' '){
5299 fit--;
5300
5301 if(*(stringdup + sum + fit) == '\t')
5302 break;
5303
5304 if(fit == 0){
5305 fit = fitcpy;
5306 break;
5307 }
5308 }
5309 lineend = fit;
5310 while(*(stringdup + sum + lineend - 1) == ' ' ||
5311 *(stringdup + sum + lineend - 1) == '\t')
5312 lineend--;
5313 }
5314 else
5315 lineend = fit;
5316
5317 GetTextExtentExPointW(hdc, stringdup + sum, lineend,
5318 nwidth, &j, NULL, &size);
5319
5320 bounds.Width = size.cx;
5321
5322 if(height + size.cy > nheight)
5323 {
5325 break;
5326 bounds.Height = nheight - (height + size.cy);
5327 }
5328 else
5329 bounds.Height = size.cy;
5330
5331 bounds.Y = rect->Y + height;
5332
5333 switch (halign)
5334 {
5336 default:
5337 bounds.X = rect->X;
5338 break;
5340 bounds.X = rect->X + (rect->Width/2) - (bounds.Width/2);
5341 break;
5342 case StringAlignmentFar:
5343 bounds.X = rect->X + rect->Width - bounds.Width;
5344 break;
5345 }
5346
5347 for (hotkeyprefix_end_pos=hotkeyprefix_pos; hotkeyprefix_end_pos<hotkeyprefix_count; hotkeyprefix_end_pos++)
5348 if (hotkeyprefix_offsets[hotkeyprefix_end_pos] >= sum + lineend)
5349 break;
5350
5351 stat = callback(hdc, stringdup, sum, lineend,
5352 font, rect, format, lineno, &bounds,
5353 &hotkeyprefix_offsets[hotkeyprefix_pos],
5354 hotkeyprefix_end_pos-hotkeyprefix_pos, user_data);
5355
5356 if (stat != Ok)
5357 break;
5358
5359 sum += fit + (lret < fitcpy ? 1 : 0);
5360 height += size.cy;
5361 lineno++;
5362
5363 hotkeyprefix_pos = hotkeyprefix_end_pos;
5364
5365 if(height > nheight)
5366 break;
5367
5368 /* Stop if this was a linewrap (but not if it was a linebreak). */
5369 if ((lret == fitcpy) && (format->attr & StringFormatFlagsNoWrap))
5370 break;
5371 }
5372
5373 heap_free(stringdup);
5374 heap_free(hotkeyprefix_offsets);
5375
5376 return stat;
5377}
5378
5382};
5383
5387 INT lineno, const RectF *bounds, INT *underlined_indexes,
5388 INT underlined_index_count, void *user_data)
5389{
5390 int i;
5391 GpStatus stat = Ok;
5392 struct measure_ranges_args *args = user_data;
5393
5394 for (i=0; i<format->range_count; i++)
5395 {
5396 INT range_start = max(index, format->character_ranges[i].First);
5397 INT range_end = min(index+length, format->character_ranges[i].First+format->character_ranges[i].Length);
5398 if (range_start < range_end)
5399 {
5400 GpRectF range_rect;
5401 SIZE range_size;
5402
5403 range_rect.Y = bounds->Y / args->rel_height;
5404 range_rect.Height = bounds->Height / args->rel_height;
5405
5406 GetTextExtentExPointW(hdc, string + index, range_start - index,
5407 INT_MAX, NULL, NULL, &range_size);
5408 range_rect.X = (bounds->X + range_size.cx) / args->rel_width;
5409
5410 GetTextExtentExPointW(hdc, string + index, range_end - index,
5411 INT_MAX, NULL, NULL, &range_size);
5412 range_rect.Width = (bounds->X + range_size.cx) / args->rel_width - range_rect.X;
5413
5414 stat = GdipCombineRegionRect(args->regions[i], &range_rect, CombineModeUnion);
5415 if (stat != Ok)
5416 break;
5417 }
5418 }
5419
5420 return stat;
5421}
5422
5426 INT regionCount, GpRegion** regions)
5427{
5428 GpStatus stat;
5429 int i;
5430 HFONT gdifont, oldfont;
5432 HDC hdc, temp_hdc=NULL;
5433 GpPointF pt[3];
5434 RectF scaled_rect;
5435 REAL margin_x;
5436
5437 TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_wn(string, length),
5438 length, font, debugstr_rectf(layoutRect), stringFormat, regionCount, regions);
5439
5440 if (!(graphics && string && font && layoutRect && stringFormat && regions))
5441 return InvalidParameter;
5442
5443 if (regionCount < stringFormat->range_count)
5444 return InvalidParameter;
5445
5446 if(!graphics->hdc)
5447 {
5448 hdc = temp_hdc = CreateCompatibleDC(0);
5449 if (!temp_hdc) return OutOfMemory;
5450 }
5451 else
5452 hdc = graphics->hdc;
5453
5454 if (stringFormat->attr)
5455 TRACE("may be ignoring some format flags: attr %x\n", stringFormat->attr);
5456
5457 pt[0].X = 0.0;
5458 pt[0].Y = 0.0;
5459 pt[1].X = 1.0;
5460 pt[1].Y = 0.0;
5461 pt[2].X = 0.0;
5462 pt[2].Y = 1.0;
5464 args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5465 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5466 args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5467 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5468
5469 margin_x = stringFormat->generic_typographic ? 0.0 : font->emSize / 6.0;
5470 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5471
5472 scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width;
5473 scaled_rect.Y = layoutRect->Y * args.rel_height;
5474 scaled_rect.Width = layoutRect->Width * args.rel_width;
5475 scaled_rect.Height = layoutRect->Height * args.rel_height;
5476
5477 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5478 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5479
5480 get_font_hfont(graphics, font, stringFormat, &gdifont, NULL);
5481 oldfont = SelectObject(hdc, gdifont);
5482
5483 for (i=0; i<stringFormat->range_count; i++)
5484 {
5486 if (stat != Ok)
5487 return stat;
5488 }
5489
5490 args.regions = regions;
5491
5492 gdi_transform_acquire(graphics);
5493
5494 stat = gdip_format_string(hdc, string, length, font, &scaled_rect, stringFormat,
5496
5497 gdi_transform_release(graphics);
5498
5499 SelectObject(hdc, oldfont);
5500 DeleteObject(gdifont);
5501
5502 if (temp_hdc)
5503 DeleteDC(temp_hdc);
5504
5505 return stat;
5506}
5507
5513};
5514
5518 INT lineno, const RectF *bounds, INT *underlined_indexes,
5519 INT underlined_index_count, void *user_data)
5520{
5521 struct measure_string_args *args = user_data;
5522 REAL new_width, new_height;
5523
5524 new_width = bounds->Width / args->rel_width;
5525 new_height = (bounds->Height + bounds->Y) / args->rel_height - args->bounds->Y;
5526
5527 if (new_width > args->bounds->Width)
5528 args->bounds->Width = new_width;
5529
5530 if (new_height > args->bounds->Height)
5531 args->bounds->Height = new_height;
5532
5533 if (args->codepointsfitted)
5534 *args->codepointsfitted = index + length;
5535
5536 if (args->linesfilled)
5537 (*args->linesfilled)++;
5538
5539 return Ok;
5540}
5541
5542/* Find the smallest rectangle that bounds the text when it is printed in rect
5543 * according to the format options listed in format. If rect has 0 width and
5544 * height, then just find the smallest rectangle that bounds the text when it's
5545 * printed at location (rect->X, rect-Y). */
5550{
5551 HFONT oldfont, gdifont;
5553 HDC temp_hdc=NULL, hdc;
5554 GpPointF pt[3];
5555 RectF scaled_rect;
5556 REAL margin_x;
5557 INT lines, glyphs;
5558
5559 TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics,
5562
5563 if(!graphics || !string || !font || !rect || !bounds)
5564 return InvalidParameter;
5565
5566 if(!graphics->hdc)
5567 {
5568 hdc = temp_hdc = CreateCompatibleDC(0);
5569 if (!temp_hdc) return OutOfMemory;
5570 }
5571 else
5572 hdc = graphics->hdc;
5573
5574 if(linesfilled) *linesfilled = 0;
5576
5577 if(format)
5578 TRACE("may be ignoring some format flags: attr %x\n", format->attr);
5579
5580 pt[0].X = 0.0;
5581 pt[0].Y = 0.0;
5582 pt[1].X = 1.0;
5583 pt[1].Y = 0.0;
5584 pt[2].X = 0.0;
5585 pt[2].Y = 1.0;
5587 args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5588 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5589 args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5590 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5591
5592 margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
5593 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5594
5595 scaled_rect.X = (rect->X + margin_x) * args.rel_width;
5596 scaled_rect.Y = rect->Y * args.rel_height;
5597 scaled_rect.Width = rect->Width * args.rel_width;
5598 scaled_rect.Height = rect->Height * args.rel_height;
5599 if (scaled_rect.Width >= 0.5)
5600 {
5601 scaled_rect.Width -= margin_x * 2.0 * args.rel_width;
5602 if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
5603 }
5604
5605 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5606 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5607
5608 get_font_hfont(graphics, font, format, &gdifont, NULL);
5609 oldfont = SelectObject(hdc, gdifont);
5610
5611 bounds->X = rect->X;
5612 bounds->Y = rect->Y;
5613 bounds->Width = 0.0;
5614 bounds->Height = 0.0;
5615
5616 args.bounds = bounds;
5617 args.codepointsfitted = &glyphs;
5618 args.linesfilled = &lines;
5619 lines = glyphs = 0;
5620
5621 gdi_transform_acquire(graphics);
5622
5623 gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
5625
5626 gdi_transform_release(graphics);
5627
5630
5631 if (lines)
5632 bounds->Width += margin_x * 2.0;
5633
5634 SelectObject(hdc, oldfont);
5635 DeleteObject(gdifont);
5636
5637 if (temp_hdc)
5638 DeleteDC(temp_hdc);
5639
5640 return Ok;
5641}
5642
5647};
5648
5652 INT lineno, const RectF *bounds, INT *underlined_indexes,
5653 INT underlined_index_count, void *user_data)
5654{
5655 struct draw_string_args *args = user_data;
5656 PointF position;
5657 GpStatus stat;
5658
5659 position.X = args->x + bounds->X / args->rel_width;
5660 position.Y = args->y + bounds->Y / args->rel_height + args->ascent;
5661
5662 stat = draw_driver_string(args->graphics, &string[index], length, font, format,
5663 args->brush, &position,
5665
5666 if (stat == Ok && underlined_index_count)
5667 {
5669 REAL underline_y, underline_height;
5670 int i;
5671
5672 GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
5673
5674 underline_height = otm.otmsUnderscoreSize / args->rel_height;
5675 underline_y = position.Y - otm.otmsUnderscorePosition / args->rel_height - underline_height / 2;
5676
5677 for (i=0; i<underlined_index_count; i++)
5678 {
5680 SIZE text_size;
5681 INT ofs = underlined_indexes[i] - index;
5682
5683 GetTextExtentExPointW(hdc, string + index, ofs, INT_MAX, NULL, NULL, &text_size);
5684 start_x = text_size.cx / args->rel_width;
5685
5686 GetTextExtentExPointW(hdc, string + index, ofs+1, INT_MAX, NULL, NULL, &text_size);
5687 end_x = text_size.cx / args->rel_width;
5688
5689 GdipFillRectangle(args->graphics, (GpBrush*)args->brush, position.X+start_x, underline_y, end_x-start_x, underline_height);
5690 }
5691 }
5692
5693 return stat;
5694}
5695
5699{
5700 HRGN rgn = NULL;
5701 HFONT gdifont;
5702 GpPointF pt[3], rectcpy[4];
5703 POINT corners[4];
5704 REAL rel_width, rel_height, margin_x;
5705 INT save_state, format_flags = 0;
5706 REAL offsety = 0.0;
5707 struct draw_string_args args;
5708 RectF scaled_rect;
5709 HDC hdc, temp_hdc=NULL;
5710 TEXTMETRICW textmetric;
5711
5712 TRACE("(%p, %s, %i, %p, %s, %p, %p)\n", graphics, debugstr_wn(string, length),
5714
5715 if(!graphics || !string || !font || !brush || !rect)
5716 return InvalidParameter;
5717
5718 if(graphics->hdc)
5719 {
5720 hdc = graphics->hdc;
5721 }
5722 else
5723 {
5724 hdc = temp_hdc = CreateCompatibleDC(0);
5725 }
5726
5727 if(format){
5728 TRACE("may be ignoring some format flags: attr %x\n", format->attr);
5729
5730 format_flags = format->attr;
5731
5732 /* Should be no need to explicitly test for StringAlignmentNear as
5733 * that is default behavior if no alignment is passed. */
5734 if(format->line_align != StringAlignmentNear){
5735 RectF bounds, in_rect = *rect;
5736 in_rect.Height = 0.0; /* avoid height clipping */
5737 GdipMeasureString(graphics, string, length, font, &in_rect, format, &bounds, 0, 0);
5738
5739 TRACE("bounds %s\n", debugstr_rectf(&bounds));
5740
5741 if(format->line_align == StringAlignmentCenter)
5742 offsety = (rect->Height - bounds.Height) / 2;
5743 else if(format->line_align == StringAlignmentFar)
5744 offsety = (rect->Height - bounds.Height);
5745 }
5746 TRACE("line align %d, offsety %f\n", format->line_align, offsety);
5747 }
5748
5749 save_state = SaveDC(hdc);
5750
5751 pt[0].X = 0.0;
5752 pt[0].Y = 0.0;
5753 pt[1].X = 1.0;
5754 pt[1].Y = 0.0;
5755 pt[2].X = 0.0;
5756 pt[2].Y = 1.0;
5758 rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5759 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5760 rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5761 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5762
5763 rectcpy[3].X = rectcpy[0].X = rect->X;
5764 rectcpy[1].Y = rectcpy[0].Y = rect->Y;
5765 rectcpy[2].X = rectcpy[1].X = rect->X + rect->Width;
5766 rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
5768 round_points(corners, rectcpy, 4);
5769
5770 margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
5771 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5772
5773 scaled_rect.X = margin_x * rel_width;
5774 scaled_rect.Y = 0.0;
5775 scaled_rect.Width = rel_width * rect->Width;
5776 scaled_rect.Height = rel_height * rect->Height;
5777 if (scaled_rect.Width >= 0.5)
5778 {
5779 scaled_rect.Width -= margin_x * 2.0 * rel_width;
5780 if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
5781 }
5782
5783 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5784 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5785
5786 if (!(format_flags & StringFormatFlagsNoClip) &&
5787 scaled_rect.Width != 1 << 23 && scaled_rect.Height != 1 << 23 &&
5788 rect->Width > 0.0 && rect->Height > 0.0)
5789 {
5790 /* FIXME: If only the width or only the height is 0, we should probably still clip */
5791 rgn = CreatePolygonRgn(corners, 4, ALTERNATE);
5792 SelectClipRgn(hdc, rgn);
5793 }
5794
5795 get_font_hfont(graphics, font, format, &gdifont, NULL);
5796 SelectObject(hdc, gdifont);
5797
5798 args.graphics = graphics;
5799 args.brush = brush;
5800
5801 args.x = rect->X;
5802 args.y = rect->Y + offsety;
5803
5804 args.rel_width = rel_width;
5805 args.rel_height = rel_height;
5806
5808
5809 GetTextMetricsW(hdc, &textmetric);
5810 args.ascent = textmetric.tmAscent / rel_height;
5811
5812 gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
5814
5816
5817 DeleteObject(rgn);
5818 DeleteObject(gdifont);
5819
5820 RestoreDC(hdc, save_state);
5821
5822 DeleteDC(temp_hdc);
5823
5824 return Ok;
5825}
5826
5828{
5829 TRACE("(%p)\n", graphics);
5830
5831 if(!graphics)
5832 return InvalidParameter;
5833
5834 if(graphics->busy)
5835 return ObjectBusy;
5836
5837 return GdipSetInfinite(graphics->clip);
5838}
5839
5841{
5842 GpStatus stat;
5843
5844 TRACE("(%p)\n", graphics);
5845
5846 if(!graphics)
5847 return InvalidParameter;
5848
5849 if(graphics->busy)
5850 return ObjectBusy;
5851
5854
5855 if (stat != Ok)
5856 return stat;
5857 }
5858
5859 return GdipSetMatrixElements(&graphics->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
5860}
5861
5864{
5865 GpStatus stat;
5866
5867 TRACE("(%p, %.2f, %d)\n", graphics, angle, order);
5868
5869 if(!graphics)
5870 return InvalidParameter;
5871
5872 if(graphics->busy)
5873 return ObjectBusy;
5874
5877
5878 if (stat != Ok)
5879 return stat;
5880 }
5881
5883}
5884
5887{
5889 GpStatus sts;
5890
5891 if(!graphics || !state)
5892 return InvalidParameter;
5893
5895 if(sts != Ok)
5896 return sts;
5897
5899 *state = graphics->contid = container->contid;
5900
5902 if (type == BEGIN_CONTAINER)
5904 else
5906 }
5907
5908 return Ok;
5909}
5910
5912{
5913 TRACE("(%p, %p)\n", graphics, state);
5915}
5916
5919{
5920 TRACE("(%p, %p)\n", graphics, state);
5922}
5923
5925{
5928 GpStatus stat;
5929 GpRectF scaled_srcrect;
5930 REAL scale_x, scale_y;
5931
5932 TRACE("(%p, %s, %s, %d, %p)\n", graphics, debugstr_rectf(dstrect), debugstr_rectf(srcrect), unit, state);
5933
5934 if(!graphics || !dstrect || !srcrect || unit < UnitPixel || unit > UnitMillimeter || !state)
5935 return InvalidParameter;
5936
5938 if(stat != Ok)
5939 return stat;
5940
5942 *state = graphics->contid = container->contid;
5943
5944 scale_x = units_to_pixels(1.0, unit, graphics->xres);
5945 scale_y = units_to_pixels(1.0, unit, graphics->yres);
5946
5947 scaled_srcrect.X = scale_x * srcrect->X;
5948 scaled_srcrect.Y = scale_y * srcrect->Y;
5949 scaled_srcrect.Width = scale_x * srcrect->Width;
5950 scaled_srcrect.Height = scale_y * srcrect->Height;
5951
5952 transform.matrix[0] = dstrect->Width / scaled_srcrect.Width;
5953 transform.matrix[1] = 0.0;
5954 transform.matrix[2] = 0.0;
5955 transform.matrix[3] = dstrect->Height / scaled_srcrect.Height;
5956 transform.matrix[4] = dstrect->X - scaled_srcrect.X;
5957 transform.matrix[5] = dstrect->Y - scaled_srcrect.Y;
5958
5960
5962 METAFILE_BeginContainer((GpMetafile*)graphics->image, dstrect, srcrect, unit, container->contid);
5963 }
5964
5965 return Ok;
5966}
5967
5969{
5970 GpRectF dstrectf, srcrectf;
5971
5972 TRACE("(%p, %p, %p, %d, %p)\n", graphics, dstrect, srcrect, unit, state);
5973
5974 if (!dstrect || !srcrect)
5975 return InvalidParameter;
5976
5977 dstrectf.X = dstrect->X;
5978 dstrectf.Y = dstrect->Y;
5979 dstrectf.Width = dstrect->Width;
5980 dstrectf.Height = dstrect->Height;
5981
5982 srcrectf.X = srcrect->X;
5983 srcrectf.Y = srcrect->Y;
5984 srcrectf.Width = srcrect->Width;
5985 srcrectf.Height = srcrect->Height;
5986
5987 return GdipBeginContainer(graphics, &dstrectf, &srcrectf, unit, state);
5988}
5989
5991{
5992 FIXME("(%p, %d, %p): stub\n", graphics, sizeData, data);
5993 return NotImplemented;
5994}
5995
5998{
5999 GpStatus sts;
6000 GraphicsContainerItem *container, *container2;
6001
6002 if(!graphics)
6003 return InvalidParameter;
6004
6006 if(container->contid == state && container->type == type)
6007 break;
6008 }
6009
6010 /* did not find a matching container */
6012 return Ok;
6013
6015 if(sts != Ok)
6016 return sts;
6017
6018 /* remove all of the containers on top of the found container */
6020 if(container->contid == state)
6021 break;
6024 }
6025
6028
6030 if (type == BEGIN_CONTAINER)
6032 else
6034 }
6035
6036 return Ok;
6037}
6038
6040{
6041 TRACE("(%p, %x)\n", graphics, state);
6043}
6044
6046{
6047 TRACE("(%p, %x)\n", graphics, state);
6049}
6050
6053{
6054 GpStatus stat;
6055
6056 TRACE("(%p, %.2f, %.2f, %d)\n", graphics, sx, sy, order);
6057
6058 if(!graphics)
6059 return InvalidParameter;
6060
6061 if(graphics->busy)
6062 return ObjectBusy;
6063
6066
6067 if (stat != Ok)
6068 return stat;
6069 }
6070
6071 return GdipScaleMatrix(&graphics->worldtrans, sx, sy, order);
6072}
6073
6076{
6077 TRACE("(%p, %p, %d)\n", graphics, srcgraphics, mode);
6078
6079 if(!graphics || !srcgraphics)
6080 return InvalidParameter;
6081
6082 return GdipCombineRegionRegion(graphics->clip, srcgraphics->clip, mode);
6083}
6084
6087{
6088 TRACE("(%p, %d)\n", graphics, mode);
6089
6090 if(!graphics)
6091 return InvalidParameter;
6092
6093 if(graphics->busy)
6094 return ObjectBusy;
6095
6096 if(graphics->compmode == mode)
6097 return Ok;
6098
6100 {
6101 GpStatus stat;
6102
6105 if(stat != Ok)
6106 return stat;
6107 }
6108
6110
6111 return Ok;
6112}
6113
6116{
6117 TRACE("(%p, %d)\n", graphics, quality);
6118
6119 if(!graphics)
6120 return InvalidParameter;
6121
6122 if(graphics->busy)
6123 return ObjectBusy;
6124
6125 if(graphics->compqual == quality)
6126 return Ok;
6127
6129 {
6130 GpStatus stat;
6131
6134 if(stat != Ok)
6135 return stat;
6136 }
6137
6139
6140 return Ok;
6141}
6142
6145{
6146 TRACE("(%p, %d)\n", graphics, mode);
6147
6149 return InvalidParameter;
6150
6151 if(graphics->busy)
6152 return ObjectBusy;
6153
6156
6159
6160 if (mode == graphics->interpolation)
6161 return Ok;
6162
6164 {
6165 GpStatus stat;
6166
6169 if (stat != Ok)
6170 return stat;
6171 }
6172
6174
6175 return Ok;
6176}
6177
6179{
6180 GpStatus stat;
6181
6182 TRACE("(%p, %.2f)\n", graphics, scale);
6183
6184 if(!graphics || (scale <= 0.0))
6185 return InvalidParameter;
6186
6187 if(graphics->busy)
6188 return ObjectBusy;
6189
6191 {
6193 if (stat != Ok)
6194 return stat;
6195 }
6196
6197 graphics->scale = scale;
6198
6199 return Ok;
6200}
6201
6203{
6204 GpStatus stat;
6205
6206 TRACE("(%p, %d)\n", graphics, unit);
6207
6208 if(!graphics)
6209 return InvalidParameter;
6210
6211 if(graphics->busy)
6212 return ObjectBusy;
6213
6214 if(unit == UnitWorld)
6215 return InvalidParameter;
6216
6218 {
6220 if (stat != Ok)
6221 return stat;
6222 }
6223
6224 graphics->unit = unit;
6225
6226 return Ok;
6227}
6228
6230 mode)
6231{
6232 TRACE("(%p, %d)\n", graphics, mode);
6233
6234 if(!graphics)
6235 return InvalidParameter;
6236
6237 if(graphics->busy)
6238 return ObjectBusy;
6239
6240 if(graphics->pixeloffset == mode)
6241 return Ok;
6242
6244 {
6245 GpStatus stat;
6246
6249 if(stat != Ok)
6250 return stat;
6251 }
6252
6254
6255 return Ok;
6256}
6257
6259{
6260 static int calls;
6261
6262 TRACE("(%p,%i,%i)\n", graphics, x, y);
6263
6264 if (!(calls++))
6265 FIXME("value is unused in rendering\n");
6266
6267 if (!graphics)
6268 return InvalidParameter;
6269
6270 graphics->origin_x = x;
6271 graphics->origin_y = y;
6272
6273 return Ok;
6274}
6275
6277{
6278 TRACE("(%p,%p,%p)\n", graphics, x, y);
6279
6280 if (!graphics || !x || !y)
6281 return InvalidParameter;
6282
6283 *x = graphics->origin_x;
6284 *y = graphics->origin_y;
6285
6286 return Ok;
6287}
6288
6290{
6291 TRACE("(%p, %d)\n", graphics, mode);
6292
6293 if(!graphics)
6294 return InvalidParameter;
6295
6296 if(graphics->busy)
6297 return ObjectBusy;
6298
6299 if(graphics->smoothing == mode)
6300 return Ok;
6301
6303 GpStatus stat;
6304 BOOL antialias = (mode != SmoothingModeDefault &&
6306
6308 EmfPlusRecordTypeSetAntiAliasMode, (mode << 1) + antialias);
6309 if(stat != Ok)
6310 return stat;
6311 }
6312
6314
6315 return Ok;
6316}
6317
6319{
6320 TRACE("(%p, %d)\n", graphics, contrast);
6321
6322 if(!graphics)
6323 return InvalidParameter;
6324
6325 graphics->textcontrast = contrast;
6326
6327 return Ok;
6328}
6329
6332{
6333 TRACE("(%p, %d)\n", graphics, hint);
6334
6336 return InvalidParameter;
6337
6338 if(graphics->busy)
6339 return ObjectBusy;
6340
6341 if(graphics->texthint == hint)
6342 return Ok;
6343
6345 GpStatus stat;
6346
6349 if(stat != Ok)
6350 return stat;
6351 }
6352
6354
6355 return Ok;
6356}
6357
6359{
6360 GpStatus stat;
6361
6362 TRACE("(%p, %p)\n", graphics, matrix);
6363
6364 if(!graphics || !matrix)
6365 return InvalidParameter;
6366
6367 if(graphics->busy)
6368 return ObjectBusy;
6369
6370 TRACE("%f,%f,%f,%f,%f,%f\n",
6371 matrix->matrix[0], matrix->matrix[1], matrix->matrix[2],
6372 matrix->matrix[3], matrix->matrix[4], matrix->matrix[5]);
6373
6376
6377 if (stat != Ok)
6378 return stat;
6379 }
6380
6382
6383 return Ok;
6384}
6385
6388{
6389 GpStatus stat;
6390
6391 TRACE("(%p, %.2f, %.2f, %d)\n", graphics, dx, dy, order);
6392
6393 if(!graphics)
6394 return InvalidParameter;
6395
6396 if(graphics->busy)
6397 return ObjectBusy;
6398
6401
6402 if (stat != Ok)
6403 return stat;
6404 }
6405
6407}
6408
6409/*****************************************************************************
6410 * GdipSetClipHrgn [GDIPLUS.@]
6411 */
6413{
6414 GpRegion *region;
6417
6418 TRACE("(%p, %p, %d)\n", graphics, hrgn, mode);
6419
6420 if(!graphics)
6421 return InvalidParameter;
6422
6423 if(graphics->busy)
6424 return ObjectBusy;
6425
6426 /* hrgn is in gdi32 device units */
6427 status = GdipCreateRegionHrgn(hrgn, &region);
6428
6429 if (status == Ok)
6430 {
6432
6433 if (status == Ok)
6435
6436 if (status == Ok)
6438
6439 GdipDeleteRegion(region);
6440 }
6441 return status;
6442}
6443
6445{
6447 GpPath *clip_path;
6448
6449 TRACE("(%p, %p, %d)\n", graphics, path, mode);
6450
6451 if(!graphics)
6452 return InvalidParameter;
6453
6454 if(graphics->busy)
6455 return ObjectBusy;
6456
6457 status = GdipClonePath(path, &clip_path);
6458 if (status == Ok)
6459 {
6460 GpMatrix world_to_device;
6461
6463 CoordinateSpaceWorld, &world_to_device);
6464 status = GdipTransformPath(clip_path, &world_to_device);
6465 if (status == Ok)
6467
6468 GdipDeletePath(clip_path);
6469 }
6470 return status;
6471}
6472
6476{
6478 GpRectF rect;
6479 GpRegion *region;
6480
6481 TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %d)\n", graphics, x, y, width, height, mode);
6482
6483 if(!graphics)
6484 return InvalidParameter;
6485
6486 if(graphics->busy)
6487 return ObjectBusy;
6488
6490 {
6492 if (status != Ok)
6493 return status;
6494 }
6495
6496 rect.X = x;
6497 rect.Y = y;
6498 rect.Width = width;
6499 rect.Height = height;
6500 status = GdipCreateRegionRect(&rect, &region);
6501 if (status == Ok)
6502 {
6503 GpMatrix world_to_device;
6504 BOOL identity;
6505
6507 status = GdipIsMatrixIdentity(&world_to_device, &identity);
6508 if (status == Ok && !identity)
6509 status = GdipTransformRegion(region, &world_to_device);
6510 if (status == Ok)
6512
6513 GdipDeleteRegion(region);
6514 }
6515 return status;
6516}
6517
6521{
6522 TRACE("(%p, %d, %d, %d, %d, %d)\n", graphics, x, y, width, height, mode);
6523
6524 if(!graphics)
6525 return InvalidParameter;
6526
6527 if(graphics->busy)
6528 return ObjectBusy;
6529
6531}
6532
6535{
6537 GpRegion *clip;
6538
6539 TRACE("(%p, %p, %d)\n", graphics, region, mode);
6540
6541 if(!graphics || !region)
6542 return InvalidParameter;
6543
6544 if(graphics->busy)
6545 return ObjectBusy;
6546
6548 {
6550 if (status != Ok)
6551 return status;
6552 }
6553
6554 status = GdipCloneRegion(region, &clip);
6555 if (status == Ok)
6556 {
6557 GpMatrix world_to_device;
6558 BOOL identity;
6559
6561 status = GdipIsMatrixIdentity(&world_to_device, &identity);
6562 if (status == Ok && !identity)
6563 status = GdipTransformRegion(clip, &world_to_device);
6564 if (status == Ok)
6566
6567 GdipDeleteRegion(clip);
6568 }
6569 return status;
6570}
6571
6573 INT count)
6574{
6576 GpPath* path;
6577
6578 TRACE("(%p, %p, %d)\n", graphics, points, count);
6579
6580 if(!graphics || !pen || count<=0)
6581 return InvalidParameter;
6582
6583 if(graphics->busy)
6584 return ObjectBusy;
6585
6587 if (status != Ok) return status;
6588
6590 if (status == Ok)
6592
6594
6595 return status;
6596}
6597
6599 INT count)
6600{
6601 GpStatus ret;
6602 GpPointF *ptf;
6603 INT i;
6604
6605 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
6606
6607 if(count<=0) return InvalidParameter;
6608 ptf = heap_alloc_zero(sizeof(GpPointF) * count);
6609
6610 for(i = 0;i < count; i++){
6611 ptf[i].X = (REAL)points[i].X;
6612 ptf[i].Y = (REAL)points[i].Y;
6613 }
6614
6615 ret = GdipDrawPolygon(graphics,pen,ptf,count);
6616 heap_free(ptf);
6617
6618 return ret;
6619}
6620
6622{
6623 TRACE("(%p, %p)\n", graphics, dpi);
6624
6625 if(!graphics || !dpi)
6626 return InvalidParameter;
6627
6628 if(graphics->busy)
6629 return ObjectBusy;
6630
6631 *dpi = graphics->xres;
6632 return Ok;
6633}
6634
6636{
6637 TRACE("(%p, %p)\n", graphics, dpi);
6638
6639 if(!graphics || !dpi)
6640 return InvalidParameter;
6641
6642 if(graphics->busy)
6643 return ObjectBusy;
6644
6645 *dpi = graphics->yres;
6646 return Ok;
6647}
6648
6651{
6652 GpMatrix m;
6653 GpStatus ret;
6654
6655 TRACE("(%p, %p, %d)\n", graphics, matrix, order);
6656
6657 if(!graphics || !matrix)
6658 return InvalidParameter;
6659
6660 if(graphics->busy)
6661 return ObjectBusy;
6662
6665
6666 if (ret != Ok)
6667 return ret;
6668 }
6669
6671
6673 if(ret == Ok)
6675
6676 return ret;
6677}
6678
6679/* Color used to fill bitmaps so we can tell which parts have been drawn over by gdi32. */
6680static const COLORREF DC_BACKGROUND_KEY = 0x0c0b0d;
6681
6683{
6685
6686 TRACE("(%p, %p)\n", graphics, hdc);
6687
6688 if(!graphics || !hdc)
6689 return InvalidParameter;
6690
6691 if(graphics->busy)
6692 return ObjectBusy;
6693
6695 {
6697 }
6698 else if (!graphics->hdc ||
6700 {
6701 /* Create a fake HDC and fill it with a constant color. */
6702 HDC temp_hdc;
6704 GpRectF bounds;
6705 BITMAPINFOHEADER bmih;
6706 int i;
6707
6708 stat = get_graphics_bounds(graphics, &bounds);
6709 if (stat != Ok)
6710 return stat;
6711
6714
6715 bmih.biSize = sizeof(bmih);
6718 bmih.biPlanes = 1;
6719 bmih.biBitCount = 32;
6720 bmih.biCompression = BI_RGB;
6721 bmih.biSizeImage = 0;
6722 bmih.biXPelsPerMeter = 0;
6723 bmih.biYPelsPerMeter = 0;
6724 bmih.biClrUsed = 0;
6725 bmih.biClrImportant = 0;
6726
6728 (void**)&graphics->temp_bits, NULL, 0);
6729 if (!hbitmap)
6730 return GenericError;
6731
6732 temp_hdc = CreateCompatibleDC(0);
6733 if (!temp_hdc)
6734 {
6736 return GenericError;
6737 }
6738
6741
6742 SelectObject(temp_hdc, hbitmap);
6743
6745 *hdc = graphics->temp_hdc = temp_hdc;
6746 }
6747 else
6748 {
6749 *hdc = graphics->hdc;
6750 }
6751
6752 if (stat == Ok)
6753 graphics->busy = TRUE;
6754
6755 return stat;
6756}
6757
6759{
6761
6762 TRACE("(%p, %p)\n", graphics, hdc);
6763
6764 if(!graphics || !hdc || !graphics->busy)
6765 return InvalidParameter;
6766
6768 {
6770 }
6771 else if (graphics->temp_hdc == hdc)
6772 {
6773 DWORD* pos;
6774 int i;
6775
6776 /* Find the pixels that have changed, and mark them as opaque. */
6779 {
6780 if (*pos != DC_BACKGROUND_KEY)
6781 {
6782 *pos |= 0xff000000;
6783 }
6784 pos++;
6785 }
6786
6787 /* Write the changed pixels to the real target. */
6791
6792 /* Clean up. */
6797 }
6798 else if (hdc != graphics->hdc)
6799 {
6801 }
6802
6803 if (stat == Ok)
6804 graphics->busy = FALSE;
6805
6806 return stat;
6807}
6808
6810{
6811 GpRegion *clip;
6813 GpMatrix device_to_world;
6814
6815 TRACE("(%p, %p)\n", graphics, region);
6816
6817 if(!graphics || !region)
6818 return InvalidParameter;
6819
6820 if(graphics->busy)
6821 return ObjectBusy;
6822
6823 if((status = GdipCloneRegion(graphics->clip, &clip)) != Ok)
6824 return status;
6825
6827 status = GdipTransformRegion(clip, &device_to_world);
6828 if (status != Ok)
6829 {
6830 GdipDeleteRegion(clip);
6831 return status;
6832 }
6833
6834 /* free everything except root node and header */
6835 delete_element(&region->node);
6836 memcpy(region, clip, sizeof(GpRegion));
6837 heap_free(clip);
6838
6839 return Ok;
6840}
6841
6843{
6845 {
6851 }
6853 return Ok;
6854}
6855
6857{
6859 {
6860 ERR("called without matching gdi_transform_acquire\n");
6861 return GenericError;
6862 }
6864 {
6866 }
6868 return Ok;
6869}
6870
6872 GpCoordinateSpace src_space, GpMatrix *matrix)
6873{
6874 GpStatus stat = Ok;
6875 REAL scale_x, scale_y;
6876
6877 GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
6878
6879 if (dst_space != src_space)
6880 {
6881 scale_x = units_to_pixels(1.0, graphics->unit, graphics->xres);
6882 scale_y = units_to_pixels(1.0, graphics->unit, graphics->yres);
6883
6884 if(graphics->unit != UnitDisplay)
6885 {
6886 scale_x *= graphics->scale;
6887 scale_y *= graphics->scale;
6888 }
6889
6890 if (dst_space < src_space)
6891 {
6892 /* transform towards world space */
6893 switch ((int)src_space)
6894 {
6896 {
6897 GpMatrix gdixform;
6898 gdixform = graphics->gdi_transform;
6899 stat = GdipInvertMatrix(&gdixform);
6900 if (stat != Ok)
6901 break;
6903 if (dst_space == CoordinateSpaceDevice)
6904 break;
6905 /* else fall-through */
6906 }
6908 GdipScaleMatrix(matrix, 1.0/scale_x, 1.0/scale_y, MatrixOrderAppend);
6909 if (dst_space == CoordinateSpacePage)
6910 break;
6911 /* else fall-through */
6913 {
6914 GpMatrix inverted_transform = graphics->worldtrans;
6915 stat = GdipInvertMatrix(&inverted_transform);
6916 if (stat == Ok)
6917 GdipMultiplyMatrix(matrix, &inverted_transform, MatrixOrderAppend);
6918 break;
6919 }
6920 }
6921 }
6922 else
6923 {
6924 /* transform towards device space */
6925 switch ((int)src_space)
6926 {
6929 if (dst_space == CoordinateSpacePage)
6930 break;
6931 /* else fall-through */
6933 GdipScaleMatrix(matrix, scale_x, scale_y, MatrixOrderAppend);
6934 if (dst_space == CoordinateSpaceDevice)
6935 break;
6936 /* else fall-through */
6938 {
6940 break;
6941 }
6942 }
6943 }
6944 }
6945 return stat;
6946}
6947
6950{
6952 GpStatus stat;
6953
6954 stat = get_graphics_transform(graphics, dst_space, src_space, &matrix);
6955 if (stat != Ok) return stat;
6956
6958}
6959
6962{
6963 if(!graphics || !points || count <= 0 ||
6964 dst_space < 0 || dst_space > CoordinateSpaceDevice ||
6965 src_space < 0 || src_space > CoordinateSpaceDevice)
6966 return InvalidParameter;
6967
6968 if(graphics->busy)
6969 return ObjectBusy;
6970
6971 TRACE("(%p, %d, %d, %p, %d)\n", graphics, dst_space, src_space, points, count);
6972
6973 if (src_space == dst_space) return Ok;
6974
6975 return gdip_transform_points(graphics, dst_space, src_space, points, count);
6976}
6977
6980{
6981 GpPointF *pointsF;
6982 GpStatus ret;
6983 INT i;
6984
6985 TRACE("(%p, %d, %d, %p, %d)\n", graphics, dst_space, src_space, points, count);
6986
6987 if(count <= 0)
6988 return InvalidParameter;
6989
6990 pointsF = heap_alloc_zero(sizeof(GpPointF) * count);
6991 if(!pointsF)
6992 return OutOfMemory;
6993
6994 for(i = 0; i < count; i++){
6995 pointsF[i].X = (REAL)points[i].X;
6996 pointsF[i].Y = (REAL)points[i].Y;
6997 }
6998
6999 ret = GdipTransformPoints(graphics, dst_space, src_space, pointsF, count);
7000
7001 if(ret == Ok)
7002 for(i = 0; i < count; i++){
7003 points[i].X = gdip_round(pointsF[i].X);
7004 points[i].Y = gdip_round(pointsF[i].Y);
7005 }
7006 heap_free(pointsF);
7007
7008 return ret;
7009}
7010
7012{
7013 static int calls;
7014
7015 TRACE("\n");
7016
7017 if (!calls++)
7018 FIXME("stub\n");
7019
7020 return NULL;
7021}
7022
7023/*****************************************************************************
7024 * GdipTranslateClip [GDIPLUS.@]
7025 */
7027{
7028 TRACE("(%p, %.2f, %.2f)\n", graphics, dx, dy);
7029
7030 if(!graphics)
7031 return InvalidParameter;
7032
7033 if(graphics->busy)
7034 return ObjectBusy;
7035
7037}
7038
7039/*****************************************************************************
7040 * GdipTranslateClipI [GDIPLUS.@]
7041 */
7043{
7044 TRACE("(%p, %d, %d)\n", graphics, dx, dy);
7045
7046 if(!graphics)
7047 return InvalidParameter;
7048
7049 if(graphics->busy)
7050 return ObjectBusy;
7051
7053}
7054
7055
7056/*****************************************************************************
7057 * GdipMeasureDriverString [GDIPLUS.@]
7058 */
7060 GDIPCONST GpFont *font, GDIPCONST PointF *positions,
7061 INT flags, GDIPCONST GpMatrix *matrix, RectF *boundingBox)
7062{
7063 static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
7064 HFONT hfont;
7065 HDC hdc;
7066 REAL min_x, min_y, max_x, max_y, x, y;
7067 int i;
7068 TEXTMETRICW textmetric;
7069 const WORD *glyph_indices;
7070 WORD *dynamic_glyph_indices=NULL;
7071 REAL rel_width, rel_height, ascent, descent;
7072 GpPointF pt[3];
7073
7074 TRACE("(%p %p %d %p %p %d %p %p)\n", graphics, text, length, font, positions, flags, matrix, boundingBox);
7075
7076 if (!graphics || !text || !font || !positions || !boundingBox)
7077 return InvalidParameter;
7078
7079 if (length == -1)
7080 length = strlenW(text);
7081
7082 if (length == 0)
7083 {
7084 boundingBox->X = 0.0;
7085 boundingBox->Y = 0.0;
7086 boundingBox->Width = 0.0;
7087 boundingBox->Height = 0.0;
7088 }
7089
7090 if (flags & unsupported_flags)
7091 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7092
7094
7097
7098 GetTextMetricsW(hdc, &textmetric);
7099
7100 pt[0].X = 0.0;
7101 pt[0].Y = 0.0;
7102 pt[1].X = 1.0;
7103 pt[1].Y = 0.0;
7104 pt[2].X = 0.0;
7105 pt[2].Y = 1.0;
7106 if (matrix)
7107 {
7108 GpMatrix xform = *matrix;
7109 GdipTransformMatrixPoints(&xform, pt, 3);
7110 }
7112 rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
7113 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
7114 rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
7115 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
7116
7118 {
7119 glyph_indices = dynamic_glyph_indices = heap_alloc_zero(sizeof(WORD) * length);
7120 if (!glyph_indices)
7121 {
7122 DeleteDC(hdc);
7124 return OutOfMemory;
7125 }
7126
7127 GetGlyphIndicesW(hdc, text, length, dynamic_glyph_indices, 0);
7128 }
7129 else
7130 glyph_indices = text;
7131
7132 min_x = max_x = x = positions[0].X;
7133 min_y = max_y = y = positions[0].Y;
7134
7135 ascent = textmetric.tmAscent / rel_height;
7136 descent = textmetric.tmDescent / rel_height;
7137
7138 for (i=0; i<length; i++)
7139 {
7140 int char_width;
7141 ABC abc;
7142
7144 {
7145 x = positions[i].X;
7146 y = positions[i].Y;
7147 }
7148
7149 GetCharABCWidthsW(hdc, glyph_indices[i], glyph_indices[i], &abc);
7150 char_width = abc.abcA + abc.abcB + abc.abcC;
7151
7152 if (min_y > y - ascent) min_y = y - ascent;
7153 if (max_y < y + descent) max_y = y + descent;
7154 if (min_x > x) min_x = x;
7155
7156 x += char_width / rel_width;
7157
7158 if (max_x < x) max_x = x;
7159 }
7160
7161 heap_free(dynamic_glyph_indices);
7162 DeleteDC(hdc);
7164
7165 boundingBox->X = min_x;
7166 boundingBox->Y = min_y;
7167 boundingBox->Width = max_x - min_x;
7168 boundingBox->Height = max_y - min_y;
7169
7170 return Ok;
7171}
7172
7175 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7177{
7178 static const INT unsupported_flags = ~(DriverStringOptionsRealizedAdvance|DriverStringOptionsCmapLookup);
7179 INT save_state;
7180 GpPointF pt;
7181 HFONT hfont;
7182 UINT eto_flags=0;
7184 HRGN hrgn;
7185
7186 if (flags & unsupported_flags)
7187 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7188
7190 eto_flags |= ETO_GLYPH_INDEX;
7191
7192 save_state = SaveDC(graphics->hdc);
7195
7197
7198 if (status == Ok)
7199 {
7202 }
7203
7204 pt = positions[0];
7206
7209
7211
7213
7215
7217
7218 RestoreDC(graphics->hdc, save_state);
7219
7221
7222 return Ok;
7223}
7224
7227 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7229{
7230 static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
7231 GpStatus stat;
7232 PointF *real_positions, real_position;
7233 POINT *pti;
7234 HFONT hfont;
7235 HDC hdc;
7236 int min_x=INT_MAX, min_y=INT_MAX, max_x=INT_MIN, max_y=INT_MIN, i, x, y;
7237 DWORD max_glyphsize=0;
7238 GLYPHMETRICS glyphmetrics;
7239 static const MAT2 identity = {{0,1}, {0,0}, {0,0}, {0,1}};
7240 BYTE *glyph_mask;
7241 BYTE *text_mask;
7242 int text_mask_stride;
7243 BYTE *pixel_data;
7244 int pixel_data_stride;
7245 GpRect pixel_area;
7246 UINT ggo_flags = GGO_GRAY8_BITMAP;
7247
7248 if (length <= 0)
7249 return Ok;
7250
7252 ggo_flags |= GGO_GLYPH_INDEX;
7253
7254 if (flags & unsupported_flags)
7255 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7256
7257 pti = heap_alloc_zero(sizeof(POINT) * length);
7258 if (!pti)
7259 return OutOfMemory;
7260
7262 {
7263 real_position = positions[0];
7264
7266 round_points(pti, &real_position, 1);
7267 }
7268 else
7269 {
7270 real_positions = heap_alloc_zero(sizeof(PointF) * length);
7271 if (!real_positions)
7272 {
7273 heap_free(pti);
7274 return OutOfMemory;
7275 }
7276
7277 memcpy(real_positions, positions, sizeof(PointF) * length);
7278
7280 round_points(pti, real_positions, length);
7281
7282 heap_free(real_positions);
7283 }
7284
7286
7289
7290 /* Get the boundaries of the text to be drawn */
7291 for (i=0; i<length; i++)
7292 {
7293 DWORD glyphsize;
7294 int left, top, right, bottom;
7295
7296 glyphsize = GetGlyphOutlineW(hdc, text[i], ggo_flags,
7297 &glyphmetrics, 0, NULL, &identity);
7298
7299 if (glyphsize == GDI_ERROR)
7300 {
7301 ERR("GetGlyphOutlineW failed\n");
7302 heap_free(pti);
7303 DeleteDC(hdc);
7305 return GenericError;
7306 }
7307
7308 if (glyphsize > max_glyphsize)
7309 max_glyphsize = glyphsize;
7310
7311 if (glyphsize != 0)
7312 {
7313 left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
7314 top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
7315 right = pti[i].x + glyphmetrics.gmptGlyphOrigin.x + glyphmetrics.gmBlackBoxX;
7316 bottom = pti[i].y - glyphmetrics.gmptGlyphOrigin.y + glyphmetrics.gmBlackBoxY;
7317
7318 if (left < min_x) min_x = left;
7319 if (top < min_y) min_y = top;
7320 if (right > max_x) max_x = right;
7321 if (bottom > max_y) max_y = bottom;
7322 }
7323
7325 {
7326 pti[i+1].x = pti[i].x + glyphmetrics.gmCellIncX;
7327 pti[i+1].y = pti[i].y + glyphmetrics.gmCellIncY;
7328 }
7329 }
7330
7331 if (max_glyphsize == 0)
7332 /* Nothing to draw. */
7333 return Ok;
7334
7335 glyph_mask = heap_alloc_zero(max_glyphsize);
7336 text_mask = heap_alloc_zero((max_x - min_x) * (max_y - min_y));
7337 text_mask_stride = max_x - min_x;
7338
7339 if (!(glyph_mask && text_mask))
7340 {
7341 heap_free(glyph_mask);
7342 heap_free(text_mask);
7343 heap_free(pti);
7344 DeleteDC(hdc);
7346 return OutOfMemory;
7347 }
7348
7349 /* Generate a mask for the text */
7350 for (i=0; i<length; i++)
7351 {
7352 DWORD ret;
7353 int left, top, stride;
7354
7355 ret = GetGlyphOutlineW(hdc, text[i], ggo_flags,
7356 &glyphmetrics, max_glyphsize, glyph_mask, &identity);
7357
7358 if (ret == GDI_ERROR || ret == 0)
7359 continue; /* empty glyph */
7360
7361 left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
7362 top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
7363 stride = (glyphmetrics.gmBlackBoxX + 3) & (~3);
7364
7365 for (y=0; y<glyphmetrics.gmBlackBoxY; y++)
7366 {
7367 BYTE *glyph_val = glyph_mask + y * stride;
7368 BYTE *text_val = text_mask + (left - min_x) + (top - min_y + y) * text_mask_stride;
7369 for (x=0; x<glyphmetrics.gmBlackBoxX; x++)
7370 {
7371 *text_val = min(64, *text_val + *glyph_val);
7372 glyph_val++;
7373 text_val++;
7374 }
7375 }
7376 }
7377
7378 heap_free(pti);
7379 DeleteDC(hdc);
7381 heap_free(glyph_mask);
7382
7383 /* get the brush data */
7384 pixel_data = heap_alloc_zero(4 * (max_x - min_x) * (max_y - min_y));
7385 if (!pixel_data)
7386 {
7387 heap_free(text_mask);
7388 return OutOfMemory;
7389 }
7390
7391 pixel_area.X = min_x;
7392 pixel_area.Y = min_y;
7393 pixel_area.Width = max_x - min_x;
7394 pixel_area.Height = max_y - min_y;
7395 pixel_data_stride = pixel_area.Width * 4;
7396
7397 stat = brush_fill_pixels(graphics, (GpBrush*)brush, (DWORD*)pixel_data, &pixel_area, pixel_area.Width);
7398 if (stat != Ok)
7399 {
7400 heap_free(text_mask);
7401 heap_free(pixel_data);
7402 return stat;
7403 }
7404
7405 /* multiply the brush data by the mask */
7406 for (y=0; y<pixel_area.Height; y++)
7407 {
7408 BYTE *text_val = text_mask + text_mask_stride * y;
7409 BYTE *pixel_val = pixel_data + pixel_data_stride * y + 3;
7410 for (x=0; x<pixel_area.Width; x++)
7411 {
7412 *pixel_val = (*pixel_val) * (*text_val) / 64;
7413 text_val++;
7414 pixel_val+=4;
7415 }
7416 }
7417
7418 heap_free(text_mask);
7419
7421
7422 /* draw the result */
7423 stat = alpha_blend_pixels(graphics, min_x, min_y, pixel_data, pixel_area.Width,
7424 pixel_area.Height, pixel_data_stride, PixelFormat32bppARGB);
7425
7427
7428 heap_free(pixel_data);
7429
7430 return stat;
7431}
7432
7435 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7437{
7439
7440 if (length == -1)
7441 length = strlenW(text);
7442
7443 if (graphics->hdc && !graphics->alpha_hdc &&
7446 (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
7448 brush, positions, flags, matrix);
7449 if (stat == NotImplemented)
7451 brush, positions, flags, matrix);
7452 return stat;
7453}
7454
7455/*****************************************************************************
7456 * GdipDrawDriverString [GDIPLUS.@]
7457 */
7460 GDIPCONST PointF *positions, INT flags,
7462{
7463 TRACE("(%p %s %p %p %p %d %p)\n", graphics, debugstr_wn(text, length), font, brush, positions, flags, matrix);
7464
7465 if (!graphics || !text || !font || !brush || !positions)
7466 return InvalidParameter;
7467
7469 brush, positions, flags, matrix);
7470}
7471
7472/*****************************************************************************
7473 * GdipIsVisibleClipEmpty [GDIPLUS.@]
7474 */
7476{
7477 GpStatus stat;
7478 GpRegion* rgn;
7479
7480 TRACE("(%p, %p)\n", graphics, res);
7481
7482 if((stat = GdipCreateRegion(&rgn)) != Ok)
7483 return stat;
7484
7485 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
7486 goto cleanup;
7487
7489
7490cleanup:
7491 GdipDeleteRegion(rgn);
7492 return stat;
7493}
7494
7496{
7497 static int calls;
7498
7499 TRACE("(%p) stub\n", graphics);
7500
7501 if(!(calls++))
7502 FIXME("not implemented\n");
7503
7504 return NotImplemented;
7505}
7506
7508{
7509 TRACE("(%p, %p)\n", graphics, pabort);
7510
7511 if (!graphics)
7512 return InvalidParameter;
7513
7514 if (pabort)
7515 FIXME("Abort callback is not supported.\n");
7516
7517 return Ok;
7518}
static HFONT hfont
static HRGN hrgn
static HBITMAP hbitmap
static POBJECT_TYPE GetObjectType(IN PCWSTR TypeName)
Definition: ObTypes.c:15
unsigned short UINT16
_STLP_MOVE_TO_STD_NAMESPACE void fill(_ForwardIter __first, _ForwardIter __last, const _Tp &__val)
Definition: _algobase.h:449
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
_STLP_DECLSPEC complex< float > _STLP_CALL sqrt(const complex< float > &)
Definition: complex.cpp:188
#define stat
Definition: acwin.h:99
static int start_x
Definition: maze.c:118
static int start_y
Definition: maze.c:118
static int state
Definition: maze.c:121
static int end_x
Definition: maze.c:118
static int end_y
Definition: maze.c:118
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static const char * wine_dbgstr_point(const POINT *ppt)
Definition: atltest.h:138
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
int rev
Definition: sort.c:17
#define WINDING
Definition: constants.h:279
#define ALTERNATE
Definition: constants.h:278
#define index(s, c)
Definition: various.h:29
static const WCHAR stringFormat[]
Definition: wordpad.c:55
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
HBITMAP hbmp
Definition: list.h:37
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
float REAL
Definition: types.h:41
#define Y(I)
#define m22
#define m11
#define m12
#define m21
static GLboolean is_identity(const GLfloat m[16])
Definition: matrix.c:402
#define GENERIC_READ
Definition: compat.h:135
#define CALLBACK
Definition: compat.h:35
#define lstrlenW
Definition: compat.h:750
GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
Definition: brush.c:994
GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
Definition: brush.c:262
GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
Definition: brush.c:757
static INT prepare_dc(GpGraphics *graphics, GpPen *pen)
Definition: graphics.c:244
static GpStatus brush_fill_path(GpGraphics *graphics, GpBrush *brush)
Definition: graphics.c:1159
GpStatus WINGDIPAPI GdipGetDpiX(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:6621
static int positive_ceilf(float f)
Definition: graphics.c:982
GpStatus WINGDIPAPI GdipDrawCurve(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:2814
GpStatus WINGDIPAPI GdipDrawImageRectRect(GpGraphics *graphics, GpImage *image, REAL dstx, REAL dsty, REAL dstwidth, REAL dstheight, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageattr, DrawImageAbort callback, VOID *callbackData)
Definition: graphics.c:3494
GpStatus WINGDIPAPI GdipDrawClosedCurve(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:2744
static ARGB sample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, UINT height, INT x, INT y, GDIPCONST GpImageAttributes *attributes)
Definition: graphics.c:936
static GpStatus draw_driver_string(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix)
Definition: graphics.c:7433
GpStatus WINGDIPAPI GdipDrawImagePointsRectI(GpGraphics *graphics, GpImage *image, GDIPCONST GpPoint *points, INT count, INT srcx, INT srcy, INT srcwidth, INT srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageAttributes, DrawImageAbort callback, VOID *callbackData)
Definition: graphics.c:3469
GpStatus WINGDIPAPI GdipFillClosedCurve(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:4274
GpStatus WINGDIPAPI GdipSetClipGraphics(GpGraphics *graphics, GpGraphics *srcgraphics, CombineMode mode)
Definition: graphics.c:6074
#define MAX_ITERS
Definition: graphics.c:68
static GpStatus free_gdi_logbrush(LOGBRUSH *lb)
Definition: graphics.c:220
HPALETTE WINGDIPAPI GdipCreateHalftonePalette(void)
Definition: graphics.c:7011
GpStatus gdip_format_string(HDC hdc, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip, gdip_format_string_callback callback, void *user_data)
Definition: graphics.c:5201
GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, INT y)
Definition: graphics.c:2985
GpStatus WINGDIPAPI GdipFillRectangles(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpRectF *rects, INT count)
Definition: graphics.c:4567
GpStatus WINGDIPAPI GdipDrawBezierI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1, INT x2, INT y2, INT x3, INT y3, INT x4, INT y4)
Definition: graphics.c:2679
GpStatus WINGDIPAPI GdipComment(GpGraphics *graphics, UINT sizeData, GDIPCONST BYTE *data)
Definition: graphics.c:5990
GpStatus WINGDIPAPI GdipFillPolygon2I(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:4529
static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush, GpRegion *region)
Definition: graphics.c:4675
GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, GraphicsContainer *state)
Definition: graphics.c:5924
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
Definition: graphics.c:2395
GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR *filename, UINT access, IStream **stream)
Definition: graphics.c:2558
GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphics.c:2878
GpStatus WINGDIPAPI GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, INT width, INT height)
Definition: graphics.c:4552
GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix)
Definition: graphics.c:6871
GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics *graphics, TextRenderingHint *hint)
Definition: graphics.c:4988
GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height)
Definition: graphics.c:2960
static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *path)
Definition: graphics.c:4327
GpStatus WINGDIPAPI GdipDrawImagePoints(GpGraphics *graphics, GpImage *image, GDIPCONST GpPointF *dstpoints, INT count)
Definition: graphics.c:3027
GpStatus WINGDIPAPI GdipDrawImageRectI(GpGraphics *graphics, GpImage *image, INT x, INT y, INT width, INT height)
Definition: graphics.c:3561
static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned int flags, unsigned int dataSize, const unsigned char *pStr, void *userdata)
Definition: graphics.c:3064
GpStatus WINGDIPAPI GdipDrawCurve3(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count, INT offset, INT numberOfSegments, REAL tension)
Definition: graphics.c:2905
GpStatus WINGDIPAPI GdipFillRegion(GpGraphics *graphics, GpBrush *brush, GpRegion *region)
Definition: graphics.c:4758
GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count, GpFillMode fillMode)
Definition: graphics.c:4492
GpStatus WINGDIPAPI GdipGraphicsSetAbort(GpGraphics *graphics, GdiplusAbort *pabort)
Definition: graphics.c:7507
static volatile LONG g_priv_contid
Definition: graphics.c:58
GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:6635
GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics *graphics, GDIPCONST GpRect *dstrect, GDIPCONST GpRect *srcrect, GpUnit unit, GraphicsContainer *state)
Definition: graphics.c:5968
GpStatus WINGDIPAPI GdipGetNearestColor(GpGraphics *graphics, ARGB *argb)
Definition: graphics.c:4899
GpStatus WINGDIPAPI GdipDrawLine(GpGraphics *graphics, GpPen *pen, REAL x1, REAL y1, REAL x2, REAL y2)
Definition: graphics.c:3569
GpStatus WINGDIPAPI GdipDrawBeziersI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:2713
GpStatus WINGDIPAPI GdipSetClipHrgn(GpGraphics *graphics, HRGN hrgn, CombineMode mode)
Definition: graphics.c:6412
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
static GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:3674
GpStatus WINGDIPAPI GdipFlush(GpGraphics *graphics, GpFlushIntention intention)
Definition: graphics.c:4786
GpStatus WINGDIPAPI GdipFillRectanglesI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpRect *rects, INT count)
Definition: graphics.c:4596
GpStatus WINGDIPAPI GdipTranslateClip(GpGraphics *graphics, REAL dx, REAL dy)
Definition: graphics.c:7026
GpStatus WINGDIPAPI GdipResetPageTransform(GpGraphics *graphics)
Definition: graphics.c:7495
GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx, REAL sy, GpMatrixOrder order)
Definition: graphics.c:6051
static void delete_container(GraphicsContainerItem *container)
Definition: graphics.c:2156
static const COLORREF DC_BACKGROUND_KEY
Definition: graphics.c:6680
static GpStatus begin_container(GpGraphics *graphics, GraphicsContainerType type, GraphicsContainer *state)
Definition: graphics.c:5885
static GpStatus alpha_blend_hdc_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
Definition: graphics.c:419
GpStatus WINGDIPAPI GdipFillClosedCurve2I(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count, REAL tension, GpFillMode fill)
Definition: graphics.c:4242
GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, GpMatrixOrder order)
Definition: graphics.c:5862
GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:4290
static HBRUSH create_gdi_brush(const GpBrush *brush)
Definition: graphics.c:231
GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region)
Definition: graphics.c:6809
GpStatus WINGDIPAPI GdipTranslateWorldTransform(GpGraphics *graphics, REAL dx, REAL dy, GpMatrixOrder order)
Definition: graphics.c:6386
static GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:3645
GpStatus WINGDIPAPI GdipSetCompositingMode(GpGraphics *graphics, CompositingMode mode)
Definition: graphics.c:6085
GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count)
Definition: graphics.c:6948
GpStatus WINGDIPAPI GdipTranslateClipI(GpGraphics *graphics, INT dx, INT dy)
Definition: graphics.c:7042
GpStatus WINGDIPAPI GdipFillClosedCurve2(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count, REAL tension, GpFillMode fill)
Definition: graphics.c:4213
GpStatus WINGDIPAPI GdipDrawPolygonI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:6598
GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **graphics)
Definition: graphics.c:2416
GpStatus WINGDIPAPI GdipDrawPie(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4091
GpStatus WINGDIPAPI GdipDrawPolygon(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:6572
GpStatus WINGDIPAPI GdipResetClip(GpGraphics *graphics)
Definition: graphics.c:5827
GpStatus WINGDIPAPI GdipGetSmoothingMode(GpGraphics *graphics, SmoothingMode *mode)
Definition: graphics.c:4960
static ARGB blend_line_gradient(GpLineGradient *brush, REAL position)
Definition: graphics.c:591
GpStatus WINGDIPAPI GdipGetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode *mode)
Definition: graphics.c:4943
static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, InterpolationMode interpolation, PixelOffsetMode offset_mode)
Definition: graphics.c:1056
GpStatus WINGDIPAPI GdipDrawLines(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:3597
GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics)
Definition: graphics.c:2484
static GpStatus create_gdi_logbrush(const GpBrush *brush, LOGBRUSH *lb)
Definition: graphics.c:184
GpStatus WINGDIPAPI GdipGetTextContrast(GpGraphics *graphics, UINT *contrast)
Definition: graphics.c:4975
static void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, HFONT *hfont, GDIPCONST GpMatrix *matrix)
Definition: graphics.c:2337
static GpStatus draw_string_callback(HDC hdc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *user_data)
Definition: graphics.c:5649
GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc)
Definition: graphics.c:6682
static BOOL brush_can_fill_path(GpBrush *brush, BOOL is_fill)
Definition: graphics.c:1131
static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix)
Definition: graphics.c:7225
GpStatus WINGDIPAPI GdipGetPageScale(GpGraphics *graphics, REAL *scale)
Definition: graphics.c:4912
GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color)
Definition: graphics.c:5076
static GpStatus get_visible_clip_region(GpGraphics *graphics, GpRegion *rgn)
Definition: graphics.c:2276
GpStatus WINGDIPAPI GdipSetClipRectI(GpGraphics *graphics, INT x, INT y, INT width, INT height, CombineMode mode)
Definition: graphics.c:6518
static ARGB transform_color(ARGB color, int matrix[5][5])
Definition: graphics.c:670
static BOOL color_is_gray(ARGB color)
Definition: graphics.c:698
GpStatus WINGDIPAPI GdipDrawBeziers(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:2688
GpStatus WINGDIPAPI GdipDrawRectangles(GpGraphics *graphics, GpPen *pen, GDIPCONST GpRectF *rects, INT count)
Definition: graphics.c:4159
GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4424
static GpStatus SOFTWARE_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *path)
Definition: graphics.c:4369
GpStatus WINGDIPAPI GdipSetTextRenderingHint(GpGraphics *graphics, TextRenderingHint hint)
Definition: graphics.c:6330
static void get_gdi_transform(GpGraphics *graphics, GpMatrix *matrix)
Definition: graphics.c:2402
GpStatus WINGDIPAPI GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix)
Definition: graphics.c:7458
void get_log_fontW(const GpFont *font, GpGraphics *graphics, LOGFONTW *lf)
Definition: graphics.c:2305
GpStatus WINGDIPAPI GdipDrawImagePointRect(GpGraphics *graphics, GpImage *image, REAL x, REAL y, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpUnit srcUnit)
Definition: graphics.c:2993
static void get_bitmap_sample_size(InterpolationMode interpolation, WrapMode wrap, GpBitmap *bitmap, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpRect *rect)
Definition: graphics.c:870
GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, RectF *bounds, INT *codepointsfitted, INT *linesfilled)
Definition: graphics.c:5546
GpStatus WINGDIPAPI GdipGetClipBounds(GpGraphics *graphics, GpRectF *rect)
Definition: graphics.c:4807
GpStatus WINGDIPAPI GdipGetCompositingMode(GpGraphics *graphics, CompositingMode *mode)
Definition: graphics.c:4848
GpStatus WINGDIPAPI GdipSetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
Definition: graphics.c:6358
GpStatus WINGDIPAPI GdipDrawClosedCurveI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:2752
GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics *graphics, GpPen *pen, REAL x1, REAL y1, REAL x2, REAL y2, REAL x3, REAL y3, REAL x4, REAL y4)
Definition: graphics.c:2654
GpStatus WINGDIPAPI GdipGetCompositingQuality(GpGraphics *graphics, CompositingQuality *quality)
Definition: graphics.c:4865
GpStatus WINGDIPAPI GdipDrawRectanglesI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpRect *rects, INT count)
Definition: graphics.c:4184
GpStatus WINGDIPAPI GdipDrawImageRectRectI(GpGraphics *graphics, GpImage *image, INT dstx, INT dsty, INT dstwidth, INT dstheight, INT srcx, INT srcy, INT srcwidth, INT srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageAttributes, DrawImageAbort callback, VOID *callbackData)
Definition: graphics.c:3517
GpStatus WINGDIPAPI GdipFillPolygon2(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:4521
GpStatus WINGDIPAPI GdipGetVisibleClipBoundsI(GpGraphics *graphics, GpRect *rect)
Definition: graphics.c:5041
GpStatus WINGDIPAPI GdipTransformPointsI(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPoint *points, INT count)
Definition: graphics.c:6978
GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region, CombineMode mode)
Definition: graphics.c:6533
static void restore_dc(GpGraphics *graphics, INT state)
Definition: graphics.c:310
static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width, UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes, InterpolationMode interpolation, PixelOffsetMode offset_mode)
Definition: graphics.c:987
GpStatus WINGDIPAPI GdipIsVisiblePoint(GpGraphics *graphics, REAL x, REAL y, BOOL *result)
Definition: graphics.c:5119
GpStatus WINGDIPAPI GdipDrawCurveI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:2822
GpStatus WINGDIPAPI GdipFillClosedCurveI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:4282
GpStatus gdi_transform_acquire(GpGraphics *graphics)
Definition: graphics.c:6842
GpStatus WINGDIPAPI GdipMultiplyWorldTransform(GpGraphics *graphics, GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
Definition: graphics.c:6649
GpStatus WINGDIPAPI GdipGetRenderingOrigin(GpGraphics *graphics, INT *x, INT *y)
Definition: graphics.c:6276
static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush, DWORD *argb_pixels, GpRect *fill_area, UINT cdwStride)
Definition: graphics.c:1239
GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y, REAL width, REAL height, CombineMode mode)
Definition: graphics.c:6473
static GpStatus get_graphics_bounds(GpGraphics *graphics, GpRectF *rect)
Definition: graphics.c:2239
static void shorten_bezier_amt(GpPointF *pt, REAL amt, BOOL rev)
Definition: graphics.c:1923
GpStatus WINGDIPAPI GdipGetVisibleClipBounds(GpGraphics *graphics, GpRectF *rect)
Definition: graphics.c:5004
#define ANCHOR_WIDTH
Definition: graphics.c:67
static GpStatus draw_poly(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *pt, GDIPCONST BYTE *types, INT count, BOOL caps)
Definition: graphics.c:1960
GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1, INT x2, INT y2)
Definition: graphics.c:3589
GpStatus WINGDIPAPI GdipDrawLinesI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:3622
GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics *graphics, INT x, INT y, BOOL *result)
Definition: graphics.c:5152
GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix, RectF *boundingBox)
Definition: graphics.c:7059
static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride, const PixelFormat fmt)
Definition: graphics.c:392
GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics *graphics, GraphicsState *state)
Definition: graphics.c:5911
static GpStatus GDI32_GdipFillRegion(GpGraphics *graphics, GpBrush *brush, GpRegion *region)
Definition: graphics.c:4625
GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:4066
static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length, GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix)
Definition: graphics.c:7173
#define GDIP_CONTID_STEP
Definition: graphics.c:57
static GpStatus init_container(GraphicsContainerItem **container, GDIPCONST GpGraphics *graphics, GraphicsContainerType type)
Definition: graphics.c:2122
static ARGB blend_colors_premult(ARGB start, ARGB end, REAL position)
Definition: graphics.c:561
static void round_points(POINT *pti, GpPointF *ptf, INT count)
Definition: graphics.c:316
GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsContainer state)
Definition: graphics.c:6039
static BOOL round_color_matrix(const ColorMatrix *matrix, int values[5][5])
Definition: graphics.c:653
static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL size, const GpCustomLineCap *custom, REAL x1, REAL y1, REAL x2, REAL y2)
Definition: graphics.c:1659
GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics *graphics, BOOL *res)
Definition: graphics.c:5109
GpStatus gdi_transform_release(GpGraphics *graphics)
Definition: graphics.c:6856
GpStatus trace_path(GpGraphics *graphics, GpPath *path)
Definition: graphics.c:2087
static GpStatus alpha_blend_pixels_hrgn(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride, HRGN hregion, PixelFormat fmt)
Definition: graphics.c:461
GpStatus WINGDIPAPI GdipSetCompositingQuality(GpGraphics *graphics, CompositingQuality quality)
Definition: graphics.c:6114
static void shorten_line_percent(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL percent)
Definition: graphics.c:1878
GpStatus WINGDIPAPI GdipSetInterpolationMode(GpGraphics *graphics, InterpolationMode mode)
Definition: graphics.c:6143
static BYTE convert_path_point_type(BYTE type)
Definition: graphics.c:76
GpStatus WINGDIPAPI GdipIsVisibleRect(GpGraphics *graphics, REAL x, REAL y, REAL width, REAL height, BOOL *result)
Definition: graphics.c:5157
GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image, GDIPCONST GpPointF *points, INT count, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageAttributes, DrawImageAbort callback, VOID *callbackData)
Definition: graphics.c:3071
GpStatus WINGDIPAPI GdipIsVisibleClipEmpty(GpGraphics *graphics, BOOL *res)
Definition: graphics.c:7475
GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:2935
static GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:3979
GpStatus WINGDIPAPI GdipGetInterpolationMode(GpGraphics *graphics, InterpolationMode *mode)
Definition: graphics.c:4882
#define fmax
Definition: graphics.c:64
GpStatus WINGDIPAPI GdipDrawRectangle(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:4126
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
Definition: graphics.c:571
GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *path)
Definition: graphics.c:4391
static HBITMAP create_hatch_bitmap(const GpHatch *hatch)
Definition: graphics.c:139
GraphicsContainerType
Definition: graphics.c:2098
@ SAVE_GRAPHICS
Definition: graphics.c:2100
@ BEGIN_CONTAINER
Definition: graphics.c:2099
static COLORREF get_gdi_brush_color(const GpBrush *brush)
Definition: graphics.c:101
GpStatus WINGDIPAPI GdipFillRectangle(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:4537
static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
Definition: graphics.c:351
GpStatus WINGDIPAPI GdipFillPolygon(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count, GpFillMode fillMode)
Definition: graphics.c:4463
GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *stringFormat, INT regionCount, GpRegion **regions)
Definition: graphics.c:5423
GpStatus WINGDIPAPI GdipDrawPieI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4117
GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT width, INT height, BOOL *result)
Definition: graphics.c:5196
static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y)
Definition: graphics.c:1125
GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics)
Definition: graphics.c:2551
GpStatus WINGDIPAPI GdipDrawClosedCurve2(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphics.c:2760
GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics *graphics, HDC hdc)
Definition: graphics.c:6758
struct _GraphicsContainerItem GraphicsContainerItem
GpStatus WINGDIPAPI GdipSetRenderingOrigin(GpGraphics *graphics, INT x, INT y)
Definition: graphics.c:6258
GpStatus WINGDIPAPI GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics)
Definition: graphics.c:2529
GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphics.c:2850
GpStatus WINGDIPAPI GdipDrawImagePointsI(GpGraphics *graphics, GpImage *image, GDIPCONST GpPoint *dstpoints, INT count)
Definition: graphics.c:3044
GpStatus WINGDIPAPI GdipDrawArc(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:2619
static void gdi_alpha_blend(GpGraphics *graphics, INT dst_x, INT dst_y, INT dst_width, INT dst_height, HDC hdc, INT src_x, INT src_y, INT src_width, INT src_height)
Definition: graphics.c:326
GpStatus WINGDIPAPI GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:2645
GpStatus WINGDIPAPI GdipDrawImagePointRectI(GpGraphics *graphics, GpImage *image, INT x, INT y, INT srcx, INT srcy, INT srcwidth, INT srcheight, GpUnit srcUnit)
Definition: graphics.c:3020
static GpStatus restore_container(GpGraphics *graphics, GDIPCONST GraphicsContainerItem *container)
Definition: graphics.c:2162
GpStatus WINGDIPAPI GdipGetClipBoundsI(GpGraphics *graphics, GpRect *rect)
Definition: graphics.c:4834
GpStatus WINGDIPAPI GdipTransformPoints(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count)
Definition: graphics.c:6960
GpStatus WINGDIPAPI GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4454
GpStatus WINGDIPAPI GdipSetClipPath(GpGraphics *graphics, GpPath *path, CombineMode mode)
Definition: graphics.c:6444
GpStatus WINGDIPAPI GdipDrawImageRect(GpGraphics *graphics, GpImage *image, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:3540
GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush)
Definition: graphics.c:5696
GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state)
Definition: graphics.c:6045
static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride, PixelFormat fmt)
Definition: graphics.c:554
PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data, UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt)
Definition: graphics.c:710
GpStatus WINGDIPAPI GdipSetPageUnit(GpGraphics *graphics, GpUnit unit)
Definition: graphics.c:6202
GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height)
Definition: graphics.c:4151
GpStatus WINGDIPAPI GdipGetPageUnit(GpGraphics *graphics, GpUnit *unit)
Definition: graphics.c:4927
GpStatus WINGDIPAPI GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode mode)
Definition: graphics.c:6289
static GpStatus get_graphics_device_bounds(GpGraphics *graphics, GpRectF *rect)
Definition: graphics.c:2192
#define GDIP_GET_NEW_CONTID_FOR(pGpGraphics)
Definition: graphics.c:59
static GpStatus measure_string_callback(HDC hdc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *user_data)
Definition: graphics.c:5515
GpStatus WINGDIPAPI GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, INT width, INT height)
Definition: graphics.c:4319
GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
Definition: graphics.c:5062
static BOOL brush_can_fill_pixels(GpBrush *brush)
Definition: graphics.c:1224
static void shorten_line_amt(REAL x1, REAL y1, REAL *x2, REAL *y2, REAL amt)
Definition: graphics.c:1897
GpStatus WINGDIPAPI GdipSetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode mode)
Definition: graphics.c:6229
GpStatus WINGDIPAPI GdipSetTextContrast(GpGraphics *graphics, UINT contrast)
Definition: graphics.c:6318
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y)
Definition: graphics.c:2969
GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics)
Definition: graphics.c:5840
GpStatus WINGDIPAPI GdipDrawClosedCurve2I(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count, REAL tension)
Definition: graphics.c:2786
GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics *graphics, REAL scale)
Definition: graphics.c:6178
GpStatus WINGDIPAPI GdipDrawCurve3I(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count, INT offset, INT numberOfSegments, REAL tension)
Definition: graphics.c:2918
static GpStatus measure_ranges_callback(HDC hdc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *user_data)
Definition: graphics.c:5384
static GpStatus end_container(GpGraphics *graphics, GraphicsContainerType type, GraphicsContainer state)
Definition: graphics.c:5996
GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state)
Definition: graphics.c:5917
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathPie(GpPath *path, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:776
GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle)
Definition: graphicspath.c:195
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y, REAL width, REAL height)
GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:623
GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix *matrix, REAL flatness)
GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:844
GpStatus WINGDIPAPI GdipClonePath(GpPath *path, GpPath **clone)
GpStatus WINGDIPAPI GdipTransformPath(GpPath *path, GpMatrix *matrix)
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix, REAL flatness)
GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath *path, GDIPCONST GpPointF *points, INT count)
Definition: graphicspath.c:290
GpStatus WINGDIPAPI GdipAddPathRectangles(GpPath *path, GDIPCONST GpRectF *rects, INT count)
GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath *path, GDIPCONST GpPoint *points, INT count)
Definition: graphicspath.c:870
GpStatus WINGDIPAPI GdipAddPathCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:480
GpStatus WINGDIPAPI GdipAddPathEllipse(GpPath *path, REAL x, REAL y, REAL width, REAL height)
Definition: graphicspath.c:583
GpStatus WINGDIPAPI GdipAddPathClosedCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count, REAL tension)
Definition: graphicspath.c:362
GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
Definition: image.c:2390
GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height)
Definition: image.c:2287
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap *bitmap, GDIPCONST GpRect *rect, UINT flags, PixelFormat format, BitmapData *lockeddata)
Definition: image.c:1030
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap *bitmap, INT x, INT y, ARGB *color)
Definition: image.c:288
GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap *bitmap, INT x, INT y, ARGB color)
Definition: image.c:494
GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap *bitmap, HBITMAP *hbmReturn, ARGB background)
Definition: image.c:1479
GpStatus WINGDIPAPI GdipGetImageBounds(GpImage *image, GpRectF *srcRect, GpUnit *srcUnit)
Definition: image.c:2196
GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap *bitmap, BitmapData *lockeddata)
Definition: image.c:1176
GpStatus WINGDIPAPI GdipScaleMatrix(GpMatrix *matrix, REAL scaleX, REAL scaleY, GpMatrixOrder order)
Definition: matrix.c:289
GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GDIPCONST GpMatrix *matrix2, GpMatrixOrder order)
Definition: matrix.c:240
GpStatus WINGDIPAPI GdipTranslateMatrix(GpMatrix *matrix, REAL offsetX, REAL offsetY, GpMatrixOrder order)
Definition: matrix.c:418
GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy)
Definition: matrix.c:316
GpStatus WINGDIPAPI GdipRotateMatrix(GpMatrix *matrix, REAL angle, GpMatrixOrder order)
Definition: matrix.c:258
GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result)
Definition: matrix.c:512
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
Definition: matrix.c:160
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:363
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
Definition: matrix.c:140
GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
Definition: matrix.c:185
GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile, EmfPlusRecordType recordType, UINT flags, UINT dataSize, GDIPCONST BYTE *data)
Definition: metafile.c:2461
GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics, GDIPCONST GpMetafile *metafile, GDIPCONST GpPointF *destPoints, INT count, GDIPCONST GpRectF *srcRect, Unit srcUnit, EnumerateMetafileProc callback, VOID *callbackData, GDIPCONST GpImageAttributes *imageAttributes)
Definition: metafile.c:3435
GpStatus WINGDIPAPI GdipIsVisibleRegionRect(GpRegion *region, REAL x, REAL y, REAL w, REAL h, GpGraphics *graphics, BOOL *res)
Definition: region.c:1277
GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode)
Definition: region.c:232
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
Definition: region.c:1204
GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region)
Definition: region.c:1374
GpStatus WINGDIPAPI GdipSetEmpty(GpRegion *region)
Definition: region.c:1359
GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:1194
GpStatus WINGDIPAPI GdipGetRegionBoundsI(GpRegion *region, GpGraphics *graphics, GpRect *rect)
Definition: region.c:629
GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *region, GpMatrix *matrix)
Definition: region.c:1480
GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect, GpRegion **region)
Definition: region.c:459
GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion *region, REAL x, REAL y, GpGraphics *graphics, BOOL *res)
Definition: region.c:1320
GpStatus WINGDIPAPI GdipTranslateRegion(GpRegion *region, REAL dx, REAL dy)
Definition: region.c:1520
GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
Definition: region.c:390
GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect, CombineMode mode)
Definition: region.c:278
GpStatus WINGDIPAPI GdipCreateRegionHrgn(HRGN hrgn, GpRegion **region)
Definition: region.c:506
GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2, CombineMode mode)
Definition: region.c:346
GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics, GpRectF *rect)
Definition: region.c:587
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
Definition: region.c:425
GpStatus WINGDIPAPI GdipDeleteRegion(GpRegion *region)
Definition: region.c:571
GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
Definition: region.c:211
const GpStringFormat default_drawstring_format
Definition: stringformat.c:35
static void cleanup(void)
Definition: main.c:1335
const WCHAR * text
Definition: package.c:1799
HRESULT WINAPI SHCreateStreamOnFileW(LPCWSTR lpszPath, DWORD dwMode, IStream **lppStream)
Definition: istream.c:484
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define pt(x, y)
Definition: drawing.c:79
#define BI_RGB
Definition: precomp.h:47
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
#define wrap(journal, var)
Definition: recovery.c:207
#define ULONG_PTR
Definition: config.h:101
POINTL point
Definition: edittest.c:50
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
GpStatus hresult_to_status(HRESULT res)
Definition: gdiplus.c:312
void delete_element(region_element *element)
Definition: gdiplus.c:455
void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride)
Definition: gdiplus.c:435
const char * debugstr_rectf(const RectF *rc)
Definition: gdiplus.c:476
REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
Definition: gdiplus.c:372
const char * debugstr_pointf(const PointF *pt)
Definition: gdiplus.c:482
COLORREF ARGB2COLORREF(ARGB color)
Definition: gdiplus.c:259
REAL gdiplus_atan2(REAL dy, REAL dx)
Definition: gdiplus.c:304
HBITMAP ARGB2BMP(ARGB color)
Definition: gdiplus.c:272
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
Definition: gdiplus.c:327
GpStatus METAFILE_SetPageTransform(GpMetafile *metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN
Definition: metafile.c:1214
GpStatus(* gdip_format_string_callback)(HDC hdc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *user_data)
GpStatus METAFILE_MultiplyWorldTransform(GpMetafile *metafile, GDIPCONST GpMatrix *matrix, MatrixOrder order) DECLSPEC_HIDDEN
Definition: metafile.c:1284
GpStatus METAFILE_GraphicsDeleted(GpMetafile *metafile) DECLSPEC_HIDDEN
Definition: metafile.c:1500
GpStatus METAFILE_ScaleWorldTransform(GpMetafile *metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN
Definition: metafile.c:1260
GpStatus METAFILE_RotateWorldTransform(GpMetafile *metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN
Definition: metafile.c:1307
static ARGB color_over(ARGB bg, ARGB fg)
static INT gdip_round(REAL x)
@ IMAGEATTR_NOOP_UNDEFINED
@ IMAGEATTR_NOOP_SET
#define WineCoordinateSpaceGdiDevice
GpStatus METAFILE_SetClipRect(GpMetafile *metafile, REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN
Definition: metafile.c:1141
GpStatus METAFILE_SaveGraphics(GpMetafile *metafile, DWORD StackIndex) DECLSPEC_HIDDEN
Definition: metafile.c:1446
GpStatus METAFILE_GetDC(GpMetafile *metafile, HDC *hdc) DECLSPEC_HIDDEN
Definition: metafile.c:927
GpStatus METAFILE_ReleaseDC(GpMetafile *metafile, HDC hdc) DECLSPEC_HIDDEN
Definition: metafile.c:1492
GpStatus METAFILE_GraphicsClear(GpMetafile *metafile, ARGB color) DECLSPEC_HIDDEN
Definition: metafile.c:949
GpStatus METAFILE_SetClipRegion(GpMetafile *metafile, GpRegion *region, CombineMode mode) DECLSPEC_HIDDEN
Definition: metafile.c:1189
GpStatus METAFILE_RestoreGraphics(GpMetafile *metafile, DWORD StackIndex) DECLSPEC_HIDDEN
Definition: metafile.c:1469
GpStatus METAFILE_BeginContainerNoParams(GpMetafile *metafile, DWORD StackIndex) DECLSPEC_HIDDEN
Definition: metafile.c:1400
GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN
Definition: metafile.c:4269
#define MAX_DASHLEN
GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN
Definition: metafile.c:4476
GpStatus METAFILE_SetWorldTransform(GpMetafile *metafile, GDIPCONST GpMatrix *transform) DECLSPEC_HIDDEN
Definition: metafile.c:1237
GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN
Definition: metafile.c:4505
GpStatus METAFILE_BeginContainer(GpMetafile *metafile, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN
Definition: metafile.c:1376
GpStatus METAFILE_TranslateWorldTransform(GpMetafile *metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN
Definition: metafile.c:1330
GpStatus METAFILE_ResetWorldTransform(GpMetafile *metafile) DECLSPEC_HIDDEN
Definition: metafile.c:1354
GpStatus METAFILE_DrawImagePointsRect(GpMetafile *metafile, GpImage *image, GDIPCONST GpPointF *points, INT count, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageAttributes, DrawImageAbort callback, VOID *callbackData) DECLSPEC_HIDDEN
Definition: metafile.c:4190
static ARGB color_over_fgpremult(ARGB bg, ARGB fg)
GpStatus METAFILE_FillRectangles(GpMetafile *metafile, GpBrush *brush, GDIPCONST GpRectF *rects, INT count) DECLSPEC_HIDDEN
Definition: metafile.c:1051
GpStatus convert_pixels(INT width, INT height, INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN
Definition: image.c:562
GpStatus METAFILE_EndContainer(GpMetafile *metafile, DWORD StackIndex) DECLSPEC_HIDDEN
Definition: metafile.c:1423
ColorAdjustType
@ ColorAdjustTypeBitmap
@ ColorAdjustTypeDefault
@ ColorMatrixFlagsAltGray
@ ColorMatrixFlagsDefault
SmoothingMode
Definition: gdiplusenums.h:121
@ SmoothingModeNone
Definition: gdiplusenums.h:126
@ SmoothingModeDefault
Definition: gdiplusenums.h:123
@ SmoothingModeHighSpeed
Definition: gdiplusenums.h:124
CompositingMode
Definition: gdiplusenums.h:248
@ CompositingModeSourceOver
Definition: gdiplusenums.h:249
StringAlignment
Definition: gdiplusenums.h:264
@ StringAlignmentCenter
Definition: gdiplusenums.h:266
@ StringAlignmentNear
Definition: gdiplusenums.h:265
@ StringAlignmentFar
Definition: gdiplusenums.h:267
@ ImageTypeBitmap
Definition: gdiplusenums.h:195
@ ImageTypeMetafile
Definition: gdiplusenums.h:196
CombineMode
Definition: gdiplusenums.h:350
@ CombineModeUnion
Definition: gdiplusenums.h:353
@ CombineModeReplace
Definition: gdiplusenums.h:351
@ CombineModeIntersect
Definition: gdiplusenums.h:352
EmfPlusRecordType
Definition: gdiplusenums.h:455
@ EmfPlusRecordTypeSetCompositingQuality
Definition: gdiplusenums.h:695
@ EmfPlusRecordTypeSetPixelOffsetMode
Definition: gdiplusenums.h:693
@ EmfPlusRecordTypeSetCompositingMode
Definition: gdiplusenums.h:694
@ EmfPlusRecordTypeSetInterpolationMode
Definition: gdiplusenums.h:692
@ EmfPlusRecordTypeSetAntiAliasMode
Definition: gdiplusenums.h:689
@ EmfPlusRecordTypeSetTextRenderingHint
Definition: gdiplusenums.h:690
@ CustomLineCapTypeAdjustableArrow
Definition: gdiplusenums.h:79
PixelOffsetMode
Definition: gdiplusenums.h:160
@ PixelOffsetModeHighSpeed
Definition: gdiplusenums.h:163
@ PixelOffsetModeHalf
Definition: gdiplusenums.h:166
@ PixelOffsetModeDefault
Definition: gdiplusenums.h:162
@ PixelOffsetModeHighQuality
Definition: gdiplusenums.h:164
@ PixelOffsetModeNone
Definition: gdiplusenums.h:165
LineCap
Definition: gdiplusenums.h:60
@ LineCapTriangle
Definition: gdiplusenums.h:64
@ LineCapCustom
Definition: gdiplusenums.h:72
@ LineCapArrowAnchor
Definition: gdiplusenums.h:70
@ LineCapNoAnchor
Definition: gdiplusenums.h:66
@ LineCapSquare
Definition: gdiplusenums.h:62
@ LineCapSquareAnchor
Definition: gdiplusenums.h:67
@ LineCapRound
Definition: gdiplusenums.h:63
@ LineCapRoundAnchor
Definition: gdiplusenums.h:68
@ LineCapFlat
Definition: gdiplusenums.h:61
@ LineCapDiamondAnchor
Definition: gdiplusenums.h:69
UINT GraphicsContainer
Definition: gdiplusenums.h:23
FillMode
Definition: gdiplusenums.h:54
@ FillModeAlternate
Definition: gdiplusenums.h:55
@ DashStyleSolid
Definition: gdiplusenums.h:178
@ DashStyleDot
Definition: gdiplusenums.h:180
@ DashStyleDashDot
Definition: gdiplusenums.h:181
@ DashStyleCustom
Definition: gdiplusenums.h:183
@ DashStyleDash
Definition: gdiplusenums.h:179
@ DashStyleDashDotDot
Definition: gdiplusenums.h:182
CompositingQuality
Definition: gdiplusenums.h:131
@ CompositingQualityDefault
Definition: gdiplusenums.h:133
WrapMode
Definition: gdiplusenums.h:206
@ WrapModeTileFlipY
Definition: gdiplusenums.h:209
@ WrapModeTile
Definition: gdiplusenums.h:207
@ WrapModeTileFlipX
Definition: gdiplusenums.h:208
@ WrapModeClamp
Definition: gdiplusenums.h:211
MatrixOrder
Definition: gdiplusenums.h:187
@ MatrixOrderAppend
Definition: gdiplusenums.h:189
@ MatrixOrderPrepend
Definition: gdiplusenums.h:188
TextRenderingHint
Definition: gdiplusenums.h:254
@ TextRenderingHintClearTypeGridFit
Definition: gdiplusenums.h:260
HotkeyPrefix
Definition: gdiplusenums.h:312
@ HotkeyPrefixShow
Definition: gdiplusenums.h:314
@ HotkeyPrefixNone
Definition: gdiplusenums.h:313
Unit
Definition: gdiplusenums.h:26
@ UnitMillimeter
Definition: gdiplusenums.h:33
@ UnitDisplay
Definition: gdiplusenums.h:28
@ UnitWorld
Definition: gdiplusenums.h:27
@ UnitPixel
Definition: gdiplusenums.h:29
FlushIntention
Definition: gdiplusenums.h:360
@ StringFormatFlagsLineLimit
Definition: gdiplusenums.h:287
@ StringFormatFlagsNoWrap
Definition: gdiplusenums.h:286
@ StringFormatFlagsNoClip
Definition: gdiplusenums.h:288
@ DriverStringOptionsRealizedAdvance
Definition: gdiplusenums.h:49
@ DriverStringOptionsCmapLookup
Definition: gdiplusenums.h:47
@ PathPointTypePathTypeMask
Definition: gdiplusenums.h:87
@ PathPointTypeBezier
Definition: gdiplusenums.h:86
@ PathPointTypeLine
Definition: gdiplusenums.h:85
@ PathPointTypeCloseSubpath
Definition: gdiplusenums.h:90
@ PathPointTypeStart
Definition: gdiplusenums.h:84
UINT GraphicsState
Definition: gdiplusenums.h:22
CoordinateSpace
Definition: gdiplusenums.h:366
@ CoordinateSpaceDevice
Definition: gdiplusenums.h:369
@ CoordinateSpaceWorld
Definition: gdiplusenums.h:367
@ CoordinateSpacePage
Definition: gdiplusenums.h:368
@ BrushTypeHatchFill
Definition: gdiplusenums.h:39
@ BrushTypeLinearGradient
Definition: gdiplusenums.h:42
@ BrushTypeTextureFill
Definition: gdiplusenums.h:40
@ BrushTypeSolidColor
Definition: gdiplusenums.h:38
@ BrushTypePathGradient
Definition: gdiplusenums.h:41
InterpolationMode
Definition: gdiplusenums.h:141
@ InterpolationModeHighQualityBicubic
Definition: gdiplusenums.h:150
@ InterpolationModeBicubic
Definition: gdiplusenums.h:147
@ InterpolationModeHighQualityBilinear
Definition: gdiplusenums.h:149
@ InterpolationModeInvalid
Definition: gdiplusenums.h:142
@ InterpolationModeHighQuality
Definition: gdiplusenums.h:145
@ InterpolationModeDefault
Definition: gdiplusenums.h:143
@ InterpolationModeBilinear
Definition: gdiplusenums.h:146
@ InterpolationModeNearestNeighbor
Definition: gdiplusenums.h:148
@ InterpolationModeLowQuality
Definition: gdiplusenums.h:144
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
@ ImageLockModeUserInputBuf
@ ImageLockModeRead
DWORD ARGB
#define PixelFormat32bppPARGB
#define PixelFormat32bppRGB
#define PixelFormat16bppRGB555
INT PixelFormat
#define PixelFormatPAlpha
#define PixelFormat24bppRGB
#define PixelFormat32bppARGB
#define PixelFormatAlpha
ImageAbort DrawImageAbort
Definition: gdiplustypes.h:56
struct GdiplusAbort GdiplusAbort
Definition: gdiplustypes.h:58
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
@ ObjectBusy
Definition: gdiplustypes.h:30
@ InvalidParameter
Definition: gdiplustypes.h:28
@ OutOfMemory
Definition: gdiplustypes.h:29
@ NotImplemented
Definition: gdiplustypes.h:32
@ GenericError
Definition: gdiplustypes.h:27
GLuint start
Definition: gl.h:1545
GLclampf green
Definition: gl.h:1740
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLeglImageOES image
Definition: gl.h:2204
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLclampf GLclampf blue
Definition: gl.h:1740
GLdouble GLdouble t
Definition: gl.h:2047
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLsizei stride
Definition: glext.h:5848
GLuint res
Definition: glext.h:9613
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLenum src
Definition: glext.h:6340
GLuint color
Definition: glext.h:6243
GLuint index
Definition: glext.h:6031
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLint * range
Definition: glext.h:7539
GLsizei GLsizei GLfloat distance
Definition: glext.h:11755
GLuint GLenum matrix
Definition: glext.h:9407
GLenum mode
Definition: glext.h:6217
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLint left
Definition: glext.h:7726
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLint GLint bottom
Definition: glext.h:7726
const GLint * first
Definition: glext.h:5794
GLboolean GLboolean g
Definition: glext.h:6204
GLfloat angle
Definition: glext.h:10853
GLenum GLsizei dataSize
Definition: glext.h:11123
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLenum cap
Definition: glext.h:9639
GLsizei const GLfloat * points
Definition: glext.h:8112
GLenum fillMode
Definition: glext.h:11728
GLintptr offset
Definition: glext.h:5920
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define INT_MIN
Definition: limits.h:39
#define INT_MAX
Definition: limits.h:40
_Check_return_ float __cdecl powf(_In_ float b, _In_ float e)
Definition: math.h:232
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
_Check_return_ float __cdecl fmodf(_In_ float x, _In_ float y)
Definition: math.h:228
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
#define bits
Definition: infblock.c:15
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
int quality
Definition: jpeglib.h:992
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
#define red
Definition: linetest.c:67
#define M_PI
Definition: macros.h:263
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define for
Definition: utility.h:88
BITMAP bmp
Definition: alphablend.c:62
BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst, HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFunction)
#define AC_SRC_ALPHA
Definition: alphablend.c:9
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static int font_height(HFONT hFont)
Definition: combo.c:612
static HDC
Definition: imagelist.c:92
static IPrintDialogCallback callback
Definition: printdlg.c:326
static const char * dst_format
Definition: dib.c:1133
static const RECT graphics_bounds[]
Definition: dib.c:1061
static UINT UINT LPWORD LPABC abc
Definition: font.c:44
static UINT UINT LPWORD glyphs
Definition: font.c:44
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static const BYTE dib[]
Definition: ole2.c:201
#define M_PI_2
Definition: port.h:185
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
#define ceilf(x)
Definition: mymath.h:62
#define floorf(x)
Definition: mymath.h:65
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_FAILIFTHERE
Definition: objbase.h:928
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:922
#define STGM_WRITE
Definition: objbase.h:918
#define STGM_READ
Definition: objbase.h:917
#define OBJ_BITMAP
Definition: objidl.idl:1415
#define OBJ_MEMDC
Definition: objidl.idl:1418
long LONG
Definition: pedump.c:60
png_const_structrp png_const_inforp int * unit
Definition: png.h:2159
#define INT
Definition: polytest.cpp:20
BOOL Polygon(CONST PPOINT UnsafePoints, int Count, int polyFillMode)
Definition: polytest.cpp:730
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
static unsigned __int64 next
Definition: rand_nt.c:6
#define strlenW(s)
Definition: unicode.h:28
#define isprintW
Definition: unicode.h:62
#define strcpyW(d, s)
Definition: unicode.h:29
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
#define M_PI_4
Definition: port.h:153
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
LONG biYPelsPerMeter
Definition: amvideo.idl:38
DWORD biCompression
Definition: amvideo.idl:35
DWORD biClrImportant
Definition: amvideo.idl:40
LONG biXPelsPerMeter
Definition: amvideo.idl:37
DWORD biSizeImage
Definition: amvideo.idl:36
PixelFormat PixelFormat
GpCustomLineCap cap
GpBrushType bt
GpPathData pathdata
CustomLineCapType type
int temp_hbitmap_width
BYTE * temp_bits
INT gdi_transform_acquire_count
PixelOffsetMode pixeloffset
SmoothingMode smoothing
int temp_hbitmap_height
GpMatrix worldtrans
struct list containers
GpImage * image
InterpolationMode interpolation
GraphicsContainer contid
HBITMAP temp_hbitmap
CompositingQuality compqual
TextRenderingHint texthint
ImageType image_type
INT gdi_transform_save
GpMatrix gdi_transform
CompositingMode compmode
GpRegion * clip
GpHatchStyle hatchstyle
struct color_key colorkeys[ColorAdjustTypeCount]
REAL gamma[ColorAdjustTypeCount]
struct color_matrix colormatrices[ColorAdjustTypeCount]
enum imageattr_noop noop[ColorAdjustTypeCount]
BOOL gamma_enabled[ColorAdjustTypeCount]
struct color_remap_table colorremaptables[ColorAdjustTypeCount]
ImageType type
GpPathData pathdata
GpDashStyle dash
GpLineCap startcap
INT numdashes
REAL * dashes
GpCustomLineCap * customend
GpLineCap endcap
UINT style
GpBrush * brush
GpUnit unit
REAL width
GpCustomLineCap * customstart
region_element node
BYTE lfOutPrecision
Definition: dimm.idl:68
BYTE lfStrikeOut
Definition: dimm.idl:66
BYTE lfItalic
Definition: dimm.idl:64
LONG lfHeight
Definition: dimm.idl:59
LONG lfWeight
Definition: dimm.idl:63
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
LONG lfOrientation
Definition: dimm.idl:62
LONG lfWidth
Definition: dimm.idl:60
BYTE lfUnderline
Definition: dimm.idl:65
BYTE lfClipPrecision
Definition: dimm.idl:69
LONG lfEscapement
Definition: dimm.idl:61
BYTE lfCharSet
Definition: dimm.idl:67
BYTE lfQuality
Definition: dimm.idl:70
BYTE lfPitchAndFamily
Definition: dimm.idl:71
PointF * Points
Definition: gdiplustypes.h:655
BYTE * Types
Definition: gdiplustypes.h:656
REAL Y
Definition: gdiplustypes.h:649
REAL X
Definition: gdiplustypes.h:648
REAL Height
Definition: gdiplustypes.h:664
REAL X
Definition: gdiplustypes.h:661
REAL Width
Definition: gdiplustypes.h:663
REAL Y
Definition: gdiplustypes.h:662
INT Width
Definition: gdiplustypes.h:671
INT Height
Definition: gdiplustypes.h:672
INT X
Definition: gdiplustypes.h:669
INT Y
Definition: gdiplustypes.h:670
Definition: wingdi.h:1410
int abcA
Definition: wingdi.h:1411
UINT abcB
Definition: wingdi.h:1412
int abcC
Definition: wingdi.h:1413
Definition: bl.h:1331
BYTE BlendOp
Definition: wingdi.h:2759
BYTE BlendFlags
Definition: wingdi.h:2760
BYTE AlphaFormat
Definition: wingdi.h:2762
BYTE SourceConstantAlpha
Definition: wingdi.h:2761
short gmCellIncX
Definition: wingdi.h:2445
UINT gmBlackBoxY
Definition: wingdi.h:2443
UINT gmBlackBoxX
Definition: wingdi.h:2442
short gmCellIncY
Definition: wingdi.h:2446
POINT gmptGlyphOrigin
Definition: wingdi.h:2444
CompositingQuality compqual
Definition: graphics.c:2109
TextRenderingHint texthint
Definition: graphics.c:2112
PixelOffsetMode pixeloffset
Definition: graphics.c:2115
CompositingMode compmode
Definition: graphics.c:2111
SmoothingMode smoothing
Definition: graphics.c:2108
GraphicsContainer contid
Definition: graphics.c:2105
GraphicsContainerType type
Definition: graphics.c:2106
InterpolationMode interpolation
Definition: graphics.c:2110
Definition: wingdi.h:2472
int otmsUnderscorePosition
Definition: wingdi.h:2540
RGNDATAHEADER rdh
Definition: axextend.idl:399
char Buffer[1]
Definition: axextend.idl:400
LONG cx
Definition: kdterminal.h:27
FLOAT eDy
Definition: wingdi.h:1726
FLOAT eM11
Definition: wingdi.h:1721
FLOAT eM21
Definition: wingdi.h:1723
FLOAT eM22
Definition: wingdi.h:1724
FLOAT eM12
Definition: wingdi.h:1722
FLOAT eDx
Definition: wingdi.h:1725
Definition: match.c:390
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
uint32 height
Definition: uimain.c:92
ColorMatrix graymatrix
ColorMatrixFlags flags
ColorMatrix colormatrix
struct list entry
Definition: metafile.c:154
GpRegion * clip
Definition: metafile.c:161
enum container_type type
Definition: metafile.c:156
GDIPCONST GpBrush * brush
Definition: graphics.c:5645
GpGraphics * graphics
Definition: graphics.c:5644
Definition: dsound.c:943
Definition: copy.c:22
Definition: parser.c:49
GpRegion ** regions
Definition: graphics.c:5380
Definition: stat.h:55
Definition: ps.c:97
Definition: parse.h:23
UINT lbStyle
Definition: wingdi.h:1747
ULONG_PTR lbHatch
Definition: wingdi.h:1749
COLORREF lbColor
Definition: wingdi.h:1748
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
LONG tmAveCharWidth
Definition: wingdi.h:2388
LONG tmAscent
Definition: wingdi.h:2384
LONG tmDescent
Definition: wingdi.h:2385
Definition: cmds.c:130
#define max(a, b)
Definition: svc.c:63
eMaj lines
Definition: tritemp.h:206
unsigned char * LPBYTE
Definition: typedefs.h:53
float FLOAT
Definition: typedefs.h:69
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_In_ HFONT _Out_ PUINT Height
Definition: font.h:88
DWORD hint
Definition: vfdcmd.c:88
int ret
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
#define dpi
Definition: sysparams.c:23
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
DWORD COLORREF
Definition: windef.h:300
int WINAPI SetMapMode(_In_ HDC, _In_ int)
#define GM_COMPATIBLE
Definition: wingdi.h:864
HBRUSH WINAPI CreateBrushIndirect(_In_ const LOGBRUSH *plb)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
#define HORZRES
Definition: wingdi.h:716
HGDIOBJ WINAPI GetStockObject(_In_ int)
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
BOOL WINAPI Ellipse(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
DWORD WINAPI GetGlyphIndicesW(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpstr, _In_ int c, _Out_writes_(c) LPWORD pgi, _In_ DWORD fl)
int WINAPI GetClipBox(_In_ HDC, _Out_ LPRECT)
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
int WINAPI SetGraphicsMode(_In_ HDC, _In_ int)
Definition: dc.c:1226
#define DT_RASPRINTER
Definition: wingdi.h:709
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
HPEN WINAPI ExtCreatePen(_In_ DWORD iPenStyle, _In_ DWORD cWidth, _In_ const LOGBRUSH *plbrush, _In_ DWORD cStyle, _In_reads_opt_(cStyle) const DWORD *pstyle)
BOOL WINAPI SetWindowOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:532
#define BS_PATTERN
Definition: wingdi.h:1090
#define DEFAULT_QUALITY
Definition: wingdi.h:436
#define NULLREGION
Definition: wingdi.h:361
#define LOGPIXELSY
Definition: wingdi.h:719
UINT WINAPI SetTextAlign(_In_ HDC, _In_ UINT)
Definition: text.c:883
HRGN WINAPI CreatePolygonRgn(_In_reads_(cPoint) const POINT *pptl, _In_ int cPoint, _In_ int iMode)
#define AC_SRC_OVER
Definition: wingdi.h:1369
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
BOOL WINAPI GdiFlush(void)
Definition: misc.c:44
BOOL WINAPI SelectClipPath(_In_ HDC, _In_ int)
BOOL WINAPI SetViewportOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:655
#define TA_LEFT
Definition: wingdi.h:932
#define PS_GEOMETRIC
Definition: wingdi.h:583
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI FillPath(_In_ HDC)
BOOL WINAPI GetTransform(HDC, DWORD, XFORM *)
int WINAPI GetClipRgn(_In_ HDC, _In_ HRGN)
#define PT_LINETO
Definition: wingdi.h:885
int WINAPI CombineRgn(_In_opt_ HRGN hrgnDest, _In_opt_ HRGN hrgnSrc1, _In_opt_ HRGN hrgnSrc2, _In_ int fnCombineMode)
#define TRANSPARENT
Definition: wingdi.h:950
#define RGN_COPY
Definition: wingdi.h:357
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define RGN_AND
Definition: wingdi.h:356
BOOL WINAPI RestoreDC(_In_ HDC, _In_ int)
#define SRCCOPY
Definition: wingdi.h:333
#define VERTRES
Definition: wingdi.h:717
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:415
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCWSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
#define GGO_GLYPH_INDEX
Definition: wingdi.h:855
#define NULL_PEN
Definition: wingdi.h:904
#define GDI_ERROR
Definition: wingdi.h:1309
#define PT_CLOSEFIGURE
Definition: wingdi.h:887
#define MM_TEXT
Definition: wingdi.h:873
#define GGO_GRAY8_BITMAP
Definition: wingdi.h:854
#define PT_MOVETO
Definition: wingdi.h:884
BOOL WINAPI StrokeAndFillPath(_In_ HDC)
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:426
UINT WINAPI GetOutlineTextMetricsW(_In_ HDC hdc, _In_ UINT cjCopy, _Out_writes_bytes_opt_(cjCopy) LPOUTLINETEXTMETRICW potm)
BOOL WINAPI GetTextExtentExPointW(_In_ HDC hdc, _In_reads_(cchString) LPCWSTR lpszString, _In_ int cchString, _In_ int nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
#define LOGPIXELSX
Definition: wingdi.h:718
#define PT_BEZIERTO
Definition: wingdi.h:886
#define TA_BASELINE
Definition: wingdi.h:928
BOOL WINAPI Rectangle(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
DWORD WINAPI GetRegionData(_In_ HRGN hrgn, _In_ DWORD nCount, _Out_writes_bytes_to_opt_(nCount, return) LPRGNDATA lpRgnData)
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL WINAPI DeleteDC(_In_ HDC)
BOOL WINAPI PolyDraw(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_reads_(cpt) const BYTE *aj, _In_ int cpt)
int WINAPI SelectClipRgn(_In_ HDC, _In_opt_ HRGN)
BOOL WINAPI EndPath(_In_ HDC)
#define PS_JOIN_MITER
Definition: wingdi.h:598
BOOL WINAPI BeginPath(_In_ HDC hdc)
#define BS_SOLID
Definition: wingdi.h:1086
DWORD WINAPI GetGlyphOutlineW(_In_ HDC hdc, _In_ UINT uChar, _In_ UINT fuFormat, _Out_ LPGLYPHMETRICS lpgm, _In_ DWORD cjBuffer, _Out_writes_bytes_opt_(cjBuffer) LPVOID pvBuffer, _In_ CONST MAT2 *lpmat2)
#define PS_SOLID
Definition: wingdi.h:586
int WINAPI SaveDC(_In_ HDC)
int WINAPI ExtSelectClipRgn(_In_ HDC, _In_opt_ HRGN, _In_ int)
int WINAPI GetRgnBox(_In_ HRGN, _Out_ LPRECT)
#define TECHNOLOGY
Definition: wingdi.h:706
#define PS_ENDCAP_FLAT
Definition: wingdi.h:596
BOOL WINAPI GetCharABCWidthsW(_In_ HDC hdc, _In_ UINT wFirst, _In_ UINT wLast, _Out_writes_(wLast - wFirst+1) LPABC lpABC)
BOOL WINAPI Pie(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int)
int WINAPI SetPolyFillMode(_In_ HDC, _In_ int)
Definition: dc.c:1167
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HWND WINAPI WindowFromDC(_In_ HDC hDC)
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HDC WINAPI GetDC(_In_opt_ HWND)
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193