ReactOS 0.4.16-dev-981-g80eb313
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{
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{
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#ifdef __REACTOS__ // CORE-19456
3268 DOUBLE delta_xx, delta_xy, delta_yx, delta_yy;
3269#else
3270 REAL delta_xx, delta_xy, delta_yx, delta_yy;
3271#endif
3272
3273 /* Transform the bits as needed to the destination. */
3274 dst_data = dst_dyn_data = heap_alloc_zero(sizeof(ARGB) * (dst_area.right - dst_area.left) * (dst_area.bottom - dst_area.top));
3275 if (!dst_data)
3276 {
3277 heap_free(src_data);
3278 return OutOfMemory;
3279 }
3280
3281 dst_stride = sizeof(ARGB) * (dst_area.right - dst_area.left);
3282
3283 GdipTransformMatrixPoints(&dst_to_src, dst_to_src_points, 3);
3284
3285 x_dx = dst_to_src_points[1].X - dst_to_src_points[0].X;
3286 x_dy = dst_to_src_points[1].Y - dst_to_src_points[0].Y;
3287 y_dx = dst_to_src_points[2].X - dst_to_src_points[0].X;
3288 y_dy = dst_to_src_points[2].Y - dst_to_src_points[0].Y;
3289
3290 delta_yy = dst_area.top * y_dy;
3291 delta_yx = dst_area.top * y_dx;
3292
3293 for (y=dst_area.top; y<dst_area.bottom; y++)
3294 {
3295 delta_xx = dst_area.left * x_dx;
3296 delta_xy = dst_area.left * x_dy;
3297
3298 for (x=dst_area.left; x<dst_area.right; x++)
3299 {
3300 GpPointF src_pointf;
3301 ARGB *dst_color;
3302
3303 src_pointf.X = dst_to_src_points[0].X + delta_xx + delta_yx;
3304 src_pointf.Y = dst_to_src_points[0].Y + delta_xy + delta_yy;
3305
3306 dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
3307
3308 if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
3309 {
3310 if (lockeddata.PixelFormat != PixelFormat32bppPARGB)
3311 *dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
3312 imageAttributes, interpolation, offset_mode);
3313 else
3314 *dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
3315 imageAttributes, interpolation, offset_mode);
3316 }
3317 else
3318 *dst_color = 0;
3319
3320 delta_xx += x_dx;
3321 delta_yx += y_dx;
3322 }
3323
3324 delta_xy += x_dy;
3325 delta_yy += y_dy;
3326 }
3327 }
3328 else
3329 {
3330 dst_data = src_data;
3331 dst_stride = src_stride;
3332 }
3333
3334 gdi_transform_acquire(graphics);
3335
3336 stat = alpha_blend_pixels(graphics, dst_area.left, dst_area.top,
3337 dst_data, dst_area.right - dst_area.left, dst_area.bottom - dst_area.top, dst_stride,
3338 lockeddata.PixelFormat);
3339
3340 gdi_transform_release(graphics);
3341
3342 heap_free(src_data);
3343
3344 heap_free(dst_dyn_data);
3345
3346 return stat;
3347 }
3348 else
3349 {
3350 HDC hdc;
3351 BOOL temp_hdc = FALSE, temp_bitmap = FALSE;
3352 HBITMAP hbitmap, old_hbm=NULL;
3353 HRGN hrgn;
3354 INT save_state;
3355
3356 if (!(bitmap->format == PixelFormat16bppRGB555 ||
3357 bitmap->format == PixelFormat24bppRGB ||
3358 bitmap->format == PixelFormat32bppRGB ||
3359 bitmap->format == PixelFormat32bppPARGB))
3360 {
3361 BITMAPINFOHEADER bih;
3362 BYTE *temp_bits;
3364
3365 /* we can't draw a bitmap of this format directly */
3367 temp_hdc = TRUE;
3368 temp_bitmap = TRUE;
3369
3370 bih.biSize = sizeof(BITMAPINFOHEADER);
3371 bih.biWidth = bitmap->width;
3372 bih.biHeight = -bitmap->height;
3373 bih.biPlanes = 1;
3374 bih.biBitCount = 32;
3375 bih.biCompression = BI_RGB;
3376 bih.biSizeImage = 0;
3377 bih.biXPelsPerMeter = 0;
3378 bih.biYPelsPerMeter = 0;
3379 bih.biClrUsed = 0;
3380 bih.biClrImportant = 0;
3381
3383 (void**)&temp_bits, NULL, 0);
3384
3387 else
3389
3391 bitmap->width*4, temp_bits, dst_format,
3392 bitmap->stride, bitmap->bits, bitmap->format,
3393 bitmap->image.palette);
3394 }
3395 else
3396 {
3397 if (bitmap->hbitmap)
3398 hbitmap = bitmap->hbitmap;
3399 else
3400 {
3402 temp_bitmap = TRUE;
3403 }
3404
3405 hdc = bitmap->hdc;
3406 temp_hdc = (hdc == 0);
3407 }
3408
3409 if (temp_hdc)
3410 {
3411 if (!hdc) hdc = CreateCompatibleDC(0);
3412 old_hbm = SelectObject(hdc, hbitmap);
3413 }
3414
3415 save_state = SaveDC(graphics->hdc);
3416
3417 stat = get_clip_hrgn(graphics, &hrgn);
3418
3419 if (stat == Ok)
3420 {
3421 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
3423 }
3424
3425 gdi_transform_acquire(graphics);
3426
3428 {
3429 gdi_alpha_blend(graphics, pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y,
3430 hdc, srcx, srcy, srcwidth, srcheight);
3431 }
3432 else
3433 {
3434 StretchBlt(graphics->hdc, pti[0].x, pti[0].y, pti[1].x-pti[0].x, pti[2].y-pti[0].y,
3435 hdc, srcx, srcy, srcwidth, srcheight, SRCCOPY);
3436 }
3437
3438 gdi_transform_release(graphics);
3439
3440 RestoreDC(graphics->hdc, save_state);
3441
3442 if (temp_hdc)
3443 {
3444 SelectObject(hdc, old_hbm);
3445 DeleteDC(hdc);
3446 }
3447
3448 if (temp_bitmap)
3450 }
3451 }
3452 else if (image->type == ImageTypeMetafile && ((GpMetafile*)image)->hemf)
3453 {
3454 GpRectF rc;
3455
3456 rc.X = srcx;
3457 rc.Y = srcy;
3458 rc.Width = srcwidth;
3459 rc.Height = srcheight;
3460
3462 points, count, &rc, srcUnit, play_metafile_proc, image, imageAttributes);
3463 }
3464 else
3465 {
3466 WARN("GpImage with nothing we can draw (metafile in wrong state?)\n");
3467 return InvalidParameter;
3468 }
3469
3470 return Ok;
3471}
3472
3474 GDIPCONST GpPoint *points, INT count, INT srcx, INT srcy, INT srcwidth,
3475 INT srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
3476 DrawImageAbort callback, VOID * callbackData)
3477{
3478 GpPointF pointsF[3];
3479 INT i;
3480
3481 TRACE("(%p, %p, %p, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n", graphics, image, points, count,
3482 srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
3483 callbackData);
3484
3485 if(!points || count!=3)
3486 return InvalidParameter;
3487
3488 for(i = 0; i < count; i++){
3489 pointsF[i].X = (REAL)points[i].X;
3490 pointsF[i].Y = (REAL)points[i].Y;
3491 }
3492
3493 return GdipDrawImagePointsRect(graphics, image, pointsF, count, (REAL)srcx, (REAL)srcy,
3494 (REAL)srcwidth, (REAL)srcheight, srcUnit, imageAttributes,
3495 callback, callbackData);
3496}
3497
3499 REAL dstx, REAL dsty, REAL dstwidth, REAL dstheight, REAL srcx, REAL srcy,
3500 REAL srcwidth, REAL srcheight, GpUnit srcUnit,
3502 VOID * callbackData)
3503{
3504 GpPointF points[3];
3505
3506 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p, %p, %p)\n",
3507 graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
3508 srcwidth, srcheight, srcUnit, imageattr, callback, callbackData);
3509
3510 points[0].X = dstx;
3511 points[0].Y = dsty;
3512 points[1].X = dstx + dstwidth;
3513 points[1].Y = dsty;
3514 points[2].X = dstx;
3515 points[2].Y = dsty + dstheight;
3516
3517 return GdipDrawImagePointsRect(graphics, image, points, 3, srcx, srcy,
3518 srcwidth, srcheight, srcUnit, imageattr, callback, callbackData);
3519}
3520
3522 INT dstx, INT dsty, INT dstwidth, INT dstheight, INT srcx, INT srcy,
3523 INT srcwidth, INT srcheight, GpUnit srcUnit,
3525 VOID * callbackData)
3526{
3527 GpPointF points[3];
3528
3529 TRACE("(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n",
3530 graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
3531 srcwidth, srcheight, srcUnit, imageAttributes, callback, callbackData);
3532
3533 points[0].X = dstx;
3534 points[0].Y = dsty;
3535 points[1].X = dstx + dstwidth;
3536 points[1].Y = dsty;
3537 points[2].X = dstx;
3538 points[2].Y = dsty + dstheight;
3539
3540 return GdipDrawImagePointsRect(graphics, image, points, 3, srcx, srcy,
3541 srcwidth, srcheight, srcUnit, imageAttributes, callback, callbackData);
3542}
3543
3546{
3547 RectF bounds;
3548 GpUnit unit;
3549 GpStatus ret;
3550
3551 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, image, x, y, width, height);
3552
3553 if(!graphics || !image)
3554 return InvalidParameter;
3555
3556 ret = GdipGetImageBounds(image, &bounds, &unit);
3557 if(ret != Ok)
3558 return ret;
3559
3560 return GdipDrawImageRectRect(graphics, image, x, y, width, height,
3561 bounds.X, bounds.Y, bounds.Width, bounds.Height,
3562 unit, NULL, NULL, NULL);
3563}
3564
3566 INT x, INT y, INT width, INT height)
3567{
3568 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, image, x, y, width, height);
3569
3570 return GdipDrawImageRect(graphics, image, (REAL)x, (REAL)y, (REAL)width, (REAL)height);
3571}
3572
3574 REAL y1, REAL x2, REAL y2)
3575{
3576 GpPointF pt[2];
3577
3578 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1, x2, y2);
3579
3580 if (!pen)
3581 return InvalidParameter;
3582
3583 if (pen->unit == UnitPixel && pen->width <= 0.0)
3584 return Ok;
3585
3586 pt[0].X = x1;
3587 pt[0].Y = y1;
3588 pt[1].X = x2;
3589 pt[1].Y = y2;
3590 return GdipDrawLines(graphics, pen, pt, 2);
3591}
3592
3594 INT y1, INT x2, INT y2)
3595{
3596 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x1, y1, x2, y2);
3597
3598 return GdipDrawLine(graphics, pen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
3599}
3600
3603{
3605 GpPath *path;
3606
3607 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
3608
3609 if(!pen || !graphics || (count < 2))
3610 return InvalidParameter;
3611
3612 if(graphics->busy)
3613 return ObjectBusy;
3614
3616 if (status != Ok) return status;
3617
3619 if (status == Ok)
3620 status = GdipDrawPath(graphics, pen, path);
3621
3623 return status;
3624}
3625
3628{
3630 GpPointF *ptf;
3631 int i;
3632
3633 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
3634
3635 ptf = heap_alloc_zero(count * sizeof(GpPointF));
3636 if(!ptf) return OutOfMemory;
3637
3638 for(i = 0; i < count; i ++){
3639 ptf[i].X = (REAL) points[i].X;
3640 ptf[i].Y = (REAL) points[i].Y;
3641 }
3642
3643 retval = GdipDrawLines(graphics, pen, ptf, count);
3644
3645 heap_free(ptf);
3646 return retval;
3647}
3648
3650{
3651 INT save_state;
3653 HRGN hrgn=NULL;
3654
3655 save_state = prepare_dc(graphics, pen);
3656
3657 retval = get_clip_hrgn(graphics, &hrgn);
3658
3659 if (retval != Ok)
3660 goto end;
3661
3662 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
3663
3664 gdi_transform_acquire(graphics);
3665
3666 retval = draw_poly(graphics, pen, path->pathdata.Points,
3667 path->pathdata.Types, path->pathdata.Count, TRUE);
3668
3669 gdi_transform_release(graphics);
3670
3671end:
3672 restore_dc(graphics, save_state);
3674
3675 return retval;
3676}
3677
3679{
3680 GpStatus stat;
3681 GpPath* flat_path;
3683 GpRectF gp_bound_rect;
3684 GpRect gp_output_area;
3685 RECT output_area;
3686 INT output_height, output_width;
3687 DWORD *output_bits, *brush_bits=NULL;
3688 int i;
3689 static const BYTE static_dash_pattern[] = {1,1,1,0,1,0,1,0};
3690 const BYTE *dash_pattern;
3691 INT dash_pattern_size;
3692 BYTE *dyn_dash_pattern = NULL;
3693
3694 stat = GdipClonePath(path, &flat_path);
3695
3696 if (stat != Ok)
3697 return stat;
3698
3700
3701 if (stat == Ok)
3702 {
3705
3706 if (stat == Ok)
3707 stat = GdipFlattenPath(flat_path, transform, 1.0);
3708
3710 }
3711
3712 /* estimate the output size in pixels, can be larger than necessary */
3713 if (stat == Ok)
3714 {
3715 output_area.left = floorf(flat_path->pathdata.Points[0].X);
3716 output_area.right = ceilf(flat_path->pathdata.Points[0].X);
3717 output_area.top = floorf(flat_path->pathdata.Points[0].Y);
3718 output_area.bottom = ceilf(flat_path->pathdata.Points[0].Y);
3719
3720 for (i=1; i<flat_path->pathdata.Count; i++)
3721 {
3722 REAL x, y;
3723 x = flat_path->pathdata.Points[i].X;
3724 y = flat_path->pathdata.Points[i].Y;
3725
3726 if (floorf(x) < output_area.left) output_area.left = floorf(x);
3727 if (floorf(y) < output_area.top) output_area.top = floorf(y);
3728 if (ceilf(x) > output_area.right) output_area.right = ceilf(x);
3729 if (ceilf(y) > output_area.bottom) output_area.bottom = ceilf(y);
3730 }
3731
3732 stat = get_graphics_device_bounds(graphics, &gp_bound_rect);
3733 }
3734
3735 if (stat == Ok)
3736 {
3737 output_area.left = max(output_area.left, floorf(gp_bound_rect.X));
3738 output_area.top = max(output_area.top, floorf(gp_bound_rect.Y));
3739 output_area.right = min(output_area.right, ceilf(gp_bound_rect.X + gp_bound_rect.Width));
3740 output_area.bottom = min(output_area.bottom, ceilf(gp_bound_rect.Y + gp_bound_rect.Height));
3741
3742 output_width = output_area.right - output_area.left + 1;
3743 output_height = output_area.bottom - output_area.top + 1;
3744
3745 if (output_width <= 0 || output_height <= 0)
3746 {
3747 GdipDeletePath(flat_path);
3748 return Ok;
3749 }
3750
3751 gp_output_area.X = output_area.left;
3752 gp_output_area.Y = output_area.top;
3753 gp_output_area.Width = output_width;
3754 gp_output_area.Height = output_height;
3755
3756 output_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD));
3757 if (!output_bits)
3758 stat = OutOfMemory;
3759 }
3760
3761 if (stat == Ok)
3762 {
3763 if (pen->brush->bt != BrushTypeSolidColor)
3764 {
3765 /* allocate and draw brush output */
3766 brush_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD));
3767
3768 if (brush_bits)
3769 {
3770 stat = brush_fill_pixels(graphics, pen->brush, brush_bits,
3771 &gp_output_area, output_width);
3772 }
3773 else
3774 stat = OutOfMemory;
3775 }
3776
3777 if (stat == Ok)
3778 {
3779 /* convert dash pattern to bool array */
3780 switch (pen->dash)
3781 {
3782 case DashStyleCustom:
3783 {
3784 dash_pattern_size = 0;
3785
3786 for (i=0; i < pen->numdashes; i++)
3787 dash_pattern_size += gdip_round(pen->dashes[i]);
3788
3789 if (dash_pattern_size != 0)
3790 {
3791 dash_pattern = dyn_dash_pattern = heap_alloc(dash_pattern_size);
3792
3793 if (dyn_dash_pattern)
3794 {
3795 int j=0;
3796 for (i=0; i < pen->numdashes; i++)
3797 {
3798 int k;
3799 for (k=0; k < gdip_round(pen->dashes[i]); k++)
3800 dyn_dash_pattern[j++] = (i&1)^1;
3801 }
3802 }
3803 else
3804 stat = OutOfMemory;
3805
3806 break;
3807 }
3808 /* else fall through */
3809 }
3810 case DashStyleSolid:
3811 default:
3812 dash_pattern = static_dash_pattern;
3813 dash_pattern_size = 1;
3814 break;
3815 case DashStyleDash:
3816 dash_pattern = static_dash_pattern;
3817 dash_pattern_size = 4;
3818 break;
3819 case DashStyleDot:
3820 dash_pattern = &static_dash_pattern[4];
3821 dash_pattern_size = 2;
3822 break;
3823 case DashStyleDashDot:
3824 dash_pattern = static_dash_pattern;
3825 dash_pattern_size = 6;
3826 break;
3828 dash_pattern = static_dash_pattern;
3829 dash_pattern_size = 8;
3830 break;
3831 }
3832 }
3833
3834 if (stat == Ok)
3835 {
3836 /* trace path */
3837 GpPointF subpath_start = flat_path->pathdata.Points[0];
3838 INT prev_x = INT_MAX, prev_y = INT_MAX;
3839 int dash_pos = dash_pattern_size - 1;
3840
3841 for (i=0; i < flat_path->pathdata.Count; i++)
3842 {
3843 BYTE type, type2;
3844 GpPointF start_point, end_point;
3845 GpPoint start_pointi, end_pointi;
3846
3847 type = flat_path->pathdata.Types[i];
3848 if (i+1 < flat_path->pathdata.Count)
3849 type2 = flat_path->pathdata.Types[i+1];
3850 else
3851 type2 = PathPointTypeStart;
3852
3853 start_point = flat_path->pathdata.Points[i];
3854
3856 subpath_start = start_point;
3857
3859 end_point = subpath_start;
3860 else if ((type2 & PathPointTypePathTypeMask) == PathPointTypeStart)
3861 continue;
3862 else
3863 end_point = flat_path->pathdata.Points[i+1];
3864
3865 start_pointi.X = floorf(start_point.X);
3866 start_pointi.Y = floorf(start_point.Y);
3867 end_pointi.X = floorf(end_point.X);
3868 end_pointi.Y = floorf(end_point.Y);
3869
3870 if(start_pointi.X == end_pointi.X && start_pointi.Y == end_pointi.Y)
3871 continue;
3872
3873 /* draw line segment */
3874 if (abs(start_pointi.Y - end_pointi.Y) > abs(start_pointi.X - end_pointi.X))
3875 {
3876 INT x, y, start_y, end_y, step;
3877
3878 if (start_pointi.Y < end_pointi.Y)
3879 {
3880 step = 1;
3881 start_y = ceilf(start_point.Y) - output_area.top;
3882 end_y = end_pointi.Y - output_area.top;
3883 }
3884 else
3885 {
3886 step = -1;
3887 start_y = start_point.Y - output_area.top;
3888 end_y = ceilf(end_point.Y) - output_area.top;
3889 }
3890
3891 for (y=start_y; y != (end_y+step); y+=step)
3892 {
3893 x = gdip_round( start_point.X +
3894 (end_point.X - start_point.X) * (y + output_area.top - start_point.Y) / (end_point.Y - start_point.Y) )
3895 - output_area.left;
3896
3897 if (x == prev_x && y == prev_y)
3898 continue;
3899
3900 prev_x = x;
3901 prev_y = y;
3902 dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1;
3903
3904 if (!dash_pattern[dash_pos])
3905 continue;
3906
3907 if (x < 0 || x >= output_width || y < 0 || y >= output_height)
3908 continue;
3909
3910 if (brush_bits)
3911 output_bits[x + y*output_width] = brush_bits[x + y*output_width];
3912 else
3913 output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color;
3914 }
3915 }
3916 else
3917 {
3918 INT x, y, start_x, end_x, step;
3919
3920 if (start_pointi.X < end_pointi.X)
3921 {
3922 step = 1;
3923 start_x = ceilf(start_point.X) - output_area.left;
3924 end_x = end_pointi.X - output_area.left;
3925 }
3926 else
3927 {
3928 step = -1;
3929 start_x = start_point.X - output_area.left;
3930 end_x = ceilf(end_point.X) - output_area.left;
3931 }
3932
3933 for (x=start_x; x != (end_x+step); x+=step)
3934 {
3935 y = gdip_round( start_point.Y +
3936 (end_point.Y - start_point.Y) * (x + output_area.left - start_point.X) / (end_point.X - start_point.X) )
3937 - output_area.top;
3938
3939 if (x == prev_x && y == prev_y)
3940 continue;
3941
3942 prev_x = x;
3943 prev_y = y;
3944 dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1;
3945
3946 if (!dash_pattern[dash_pos])
3947 continue;
3948
3949 if (x < 0 || x >= output_width || y < 0 || y >= output_height)
3950 continue;
3951
3952 if (brush_bits)
3953 output_bits[x + y*output_width] = brush_bits[x + y*output_width];
3954 else
3955 output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color;
3956 }
3957 }
3958 }
3959 }
3960
3961 /* draw output image */
3962 if (stat == Ok)
3963 {
3964 gdi_transform_acquire(graphics);
3965
3966 stat = alpha_blend_pixels(graphics, output_area.left, output_area.top,
3967 (BYTE*)output_bits, output_width, output_height, output_width * 4,
3969
3970 gdi_transform_release(graphics);
3971 }
3972
3973 heap_free(brush_bits);
3974 heap_free(dyn_dash_pattern);
3975 heap_free(output_bits);
3976 }
3977
3978 GdipDeletePath(flat_path);
3979
3980 return stat;
3981}
3982
3984{
3985 GpStatus stat;
3986 GpPath *wide_path;
3988 REAL flatness=1.0;
3989
3990 /* Check if the final pen thickness in pixels is too thin. */
3991 if (pen->unit == UnitPixel)
3992 {
3993 if (pen->width < 1.415)
3994 return SOFTWARE_GdipDrawThinPath(graphics, pen, path);
3995 }
3996 else
3997 {
3998 GpPointF points[3] = {{0,0}, {1,0}, {0,1}};
3999
4000 points[1].X = pen->width;
4001 points[2].Y = pen->width;
4002
4005
4006 if (stat != Ok)
4007 return stat;
4008
4009 if (((points[1].X-points[0].X)*(points[1].X-points[0].X) +
4010 (points[1].Y-points[0].Y)*(points[1].Y-points[0].Y) < 2.0001) &&
4011 ((points[2].X-points[0].X)*(points[2].X-points[0].X) +
4012 (points[2].Y-points[0].Y)*(points[2].Y-points[0].Y) < 2.0001))
4013 return SOFTWARE_GdipDrawThinPath(graphics, pen, path);
4014 }
4015
4016 stat = GdipClonePath(path, &wide_path);
4017
4018 if (stat != Ok)
4019 return stat;
4020
4021 if (pen->unit == UnitPixel)
4022 {
4023 /* We have to transform this to device coordinates to get the widths right. */
4025
4026 if (stat == Ok)
4029 }
4030 else
4031 {
4032 /* Set flatness based on the final coordinate space */
4033 GpMatrix t;
4034
4037
4038 if (stat != Ok)
4039 return stat;
4040
4041 flatness = 1.0/sqrt(fmax(
4042 t.matrix[0] * t.matrix[0] + t.matrix[1] * t.matrix[1],
4043 t.matrix[2] * t.matrix[2] + t.matrix[3] * t.matrix[3]));
4044 }
4045
4046 if (stat == Ok)
4047 stat = GdipWidenPath(wide_path, pen, transform, flatness);
4048
4049 if (pen->unit == UnitPixel)
4050 {
4051 /* Transform the path back to world coordinates */
4052 if (stat == Ok)
4054
4055 if (stat == Ok)
4056 stat = GdipTransformPath(wide_path, transform);
4057 }
4058
4059 /* Actually draw the path */
4060 if (stat == Ok)
4061 stat = GdipFillPath(graphics, pen->brush, wide_path);
4062
4064
4065 GdipDeletePath(wide_path);
4066
4067 return stat;
4068}
4069
4071{
4073
4074 TRACE("(%p, %p, %p)\n", graphics, pen, path);
4075
4076 if(!pen || !graphics)
4077 return InvalidParameter;
4078
4079 if(graphics->busy)
4080 return ObjectBusy;
4081
4082 if (path->pathdata.Count == 0)
4083 return Ok;
4084
4085 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4086 retval = METAFILE_DrawPath((GpMetafile*)graphics->image, pen, path);
4087 else if (!graphics->hdc || graphics->alpha_hdc || !brush_can_fill_path(pen->brush, FALSE))
4088 retval = SOFTWARE_GdipDrawPath(graphics, pen, path);
4089 else
4090 retval = GDI32_GdipDrawPath(graphics, pen, path);
4091
4092 return retval;
4093}
4094
4096 REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
4097{
4099 GpPath *path;
4100
4101 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y,
4102 width, height, startAngle, sweepAngle);
4103
4104 if(!graphics || !pen)
4105 return InvalidParameter;
4106
4107 if(graphics->busy)
4108 return ObjectBusy;
4109
4111 if (status != Ok) return status;
4112
4113 status = GdipAddPathPie(path, x, y, width, height, startAngle, sweepAngle);
4114 if (status == Ok)
4115 status = GdipDrawPath(graphics, pen, path);
4116
4118 return status;
4119}
4120
4122 INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
4123{
4124 TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n", graphics, pen, x, y,
4125 width, height, startAngle, sweepAngle);
4126
4127 return GdipDrawPie(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
4128}
4129
4132{
4134 GpPath *path;
4135
4136 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y, width, height);
4137
4138 if(!pen || !graphics)
4139 return InvalidParameter;
4140
4141 if(graphics->busy)
4142 return ObjectBusy;
4143
4145 if (status != Ok) return status;
4146
4148 if (status == Ok)
4149 status = GdipDrawPath(graphics, pen, path);
4150
4152 return status;
4153}
4154
4156 INT y, INT width, INT height)
4157{
4158 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x, y, width, height);
4159
4160 return GdipDrawRectangle(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
4161}
4162
4164 GDIPCONST GpRectF* rects, INT count)
4165{
4167 GpPath *path;
4168
4169 TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
4170
4171 if(!graphics || !pen || !rects || count < 1)
4172 return InvalidParameter;
4173
4174 if(graphics->busy)
4175 return ObjectBusy;
4176
4178 if (status != Ok) return status;
4179
4181 if (status == Ok)
4182 status = GdipDrawPath(graphics, pen, path);
4183
4185 return status;
4186}
4187
4189 GDIPCONST GpRect* rects, INT count)
4190{
4191 GpRectF *rectsF;
4192 GpStatus ret;
4193 INT i;
4194
4195 TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
4196
4197 if(!rects || count<=0)
4198 return InvalidParameter;
4199
4200 rectsF = heap_alloc_zero(sizeof(GpRectF) * count);
4201 if(!rectsF)
4202 return OutOfMemory;
4203
4204 for(i = 0;i < count;i++){
4205 rectsF[i].X = (REAL)rects[i].X;
4206 rectsF[i].Y = (REAL)rects[i].Y;
4207 rectsF[i].Width = (REAL)rects[i].Width;
4208 rectsF[i].Height = (REAL)rects[i].Height;
4209 }
4210
4211 ret = GdipDrawRectangles(graphics, pen, rectsF, count);
4212 heap_free(rectsF);
4213
4214 return ret;
4215}
4216
4219{
4220 GpPath *path;
4222
4223 TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
4224 count, tension, fill);
4225
4226 if(!graphics || !brush || !points)
4227 return InvalidParameter;
4228
4229 if(graphics->busy)
4230 return ObjectBusy;
4231
4232 if(count == 1) /* Do nothing */
4233 return Ok;
4234
4236 if (status != Ok) return status;
4237
4239 if (status == Ok)
4240 status = GdipFillPath(graphics, brush, path);
4241
4243 return status;
4244}
4245
4248{
4249 GpPointF *ptf;
4250 GpStatus stat;
4251 INT i;
4252
4253 TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
4254 count, tension, fill);
4255
4256 if(!points || count == 0)
4257 return InvalidParameter;
4258
4259 if(count == 1) /* Do nothing */
4260 return Ok;
4261
4262 ptf = heap_alloc_zero(sizeof(GpPointF)*count);
4263 if(!ptf)
4264 return OutOfMemory;
4265
4266 for(i = 0;i < count;i++){
4267 ptf[i].X = (REAL)points[i].X;
4268 ptf[i].Y = (REAL)points[i].Y;
4269 }
4270
4271 stat = GdipFillClosedCurve2(graphics, brush, ptf, count, tension, fill);
4272
4273 heap_free(ptf);
4274
4275 return stat;
4276}
4277
4280{
4281 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4282 return GdipFillClosedCurve2(graphics, brush, points, count,
4283 0.5f, FillModeAlternate);
4284}
4285
4288{
4289 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4290 return GdipFillClosedCurve2I(graphics, brush, points, count,
4291 0.5f, FillModeAlternate);
4292}
4293
4296{
4297 GpStatus stat;
4298 GpPath *path;
4299
4300 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
4301
4302 if(!graphics || !brush)
4303 return InvalidParameter;
4304
4305 if(graphics->busy)
4306 return ObjectBusy;
4307
4309
4310 if (stat == Ok)
4311 {
4313
4314 if (stat == Ok)
4315 stat = GdipFillPath(graphics, brush, path);
4316
4318 }
4319
4320 return stat;
4321}
4322
4324 INT y, INT width, INT height)
4325{
4326 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
4327
4328 return GdipFillEllipse(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
4329}
4330
4332{
4333 INT save_state;
4335 HRGN hrgn=NULL;
4336
4337 if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
4338 return NotImplemented;
4339
4340 save_state = SaveDC(graphics->hdc);
4341 EndPath(graphics->hdc);
4342 SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
4343 : WINDING));
4344
4345 retval = get_clip_hrgn(graphics, &hrgn);
4346
4347 if (retval != Ok)
4348 goto end;
4349
4350 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
4351
4352 gdi_transform_acquire(graphics);
4353
4354 BeginPath(graphics->hdc);
4355 retval = draw_poly(graphics, NULL, path->pathdata.Points,
4356 path->pathdata.Types, path->pathdata.Count, FALSE);
4357
4358 if(retval == Ok)
4359 {
4360 EndPath(graphics->hdc);
4361 retval = brush_fill_path(graphics, brush);
4362 }
4363
4364 gdi_transform_release(graphics);
4365
4366end:
4367 RestoreDC(graphics->hdc, save_state);
4369
4370 return retval;
4371}
4372
4374{
4375 GpStatus stat;
4376 GpRegion *rgn;
4377
4378 if (!brush_can_fill_pixels(brush))
4379 return NotImplemented;
4380
4381 /* FIXME: This could probably be done more efficiently without regions. */
4382
4384
4385 if (stat == Ok)
4386 {
4387 stat = GdipFillRegion(graphics, brush, rgn);
4388
4389 GdipDeleteRegion(rgn);
4390 }
4391
4392 return stat;
4393}
4394
4396{
4398
4399 TRACE("(%p, %p, %p)\n", graphics, brush, path);
4400
4401 if(!brush || !graphics || !path)
4402 return InvalidParameter;
4403
4404 if(graphics->busy)
4405 return ObjectBusy;
4406
4407 if (!path->pathdata.Count)
4408 return Ok;
4409
4410 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4411 return METAFILE_FillPath((GpMetafile*)graphics->image, brush, path);
4412
4413 if (!graphics->image && !graphics->alpha_hdc)
4414 stat = GDI32_GdipFillPath(graphics, brush, path);
4415
4416 if (stat == NotImplemented)
4417 stat = SOFTWARE_GdipFillPath(graphics, brush, path);
4418
4419 if (stat == NotImplemented)
4420 {
4421 FIXME("Not implemented for brushtype %i\n", brush->bt);
4422 stat = Ok;
4423 }
4424
4425 return stat;
4426}
4427
4429 REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
4430{
4431 GpStatus stat;
4432 GpPath *path;
4433
4434 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
4435 graphics, brush, x, y, width, height, startAngle, sweepAngle);
4436
4437 if(!graphics || !brush)
4438 return InvalidParameter;
4439
4440 if(graphics->busy)
4441 return ObjectBusy;
4442
4444
4445 if (stat == Ok)
4446 {
4447 stat = GdipAddPathPie(path, x, y, width, height, startAngle, sweepAngle);
4448
4449 if (stat == Ok)
4450 stat = GdipFillPath(graphics, brush, path);
4451
4453 }
4454
4455 return stat;
4456}
4457
4459 INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
4460{
4461 TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n",
4462 graphics, brush, x, y, width, height, startAngle, sweepAngle);
4463
4464 return GdipFillPie(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
4465}
4466
4469{
4470 GpStatus stat;
4471 GpPath *path;
4472
4473 TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
4474
4475 if(!graphics || !brush || !points || !count)
4476 return InvalidParameter;
4477
4478 if(graphics->busy)
4479 return ObjectBusy;
4480
4482
4483 if (stat == Ok)
4484 {
4486
4487 if (stat == Ok)
4488 stat = GdipFillPath(graphics, brush, path);
4489
4491 }
4492
4493 return stat;
4494}
4495
4498{
4499 GpStatus stat;
4500 GpPath *path;
4501
4502 TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
4503
4504 if(!graphics || !brush || !points || !count)
4505 return InvalidParameter;
4506
4507 if(graphics->busy)
4508 return ObjectBusy;
4509
4511
4512 if (stat == Ok)
4513 {
4515
4516 if (stat == Ok)
4517 stat = GdipFillPath(graphics, brush, path);
4518
4520 }
4521
4522 return stat;
4523}
4524
4527{
4528 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4529
4530 return GdipFillPolygon(graphics, brush, points, count, FillModeAlternate);
4531}
4532
4535{
4536 TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
4537
4538 return GdipFillPolygonI(graphics, brush, points, count, FillModeAlternate);
4539}
4540
4543{
4544 GpRectF rect;
4545
4546 TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
4547
4548 rect.X = x;
4549 rect.Y = y;
4550 rect.Width = width;
4551 rect.Height = height;
4552
4553 return GdipFillRectangles(graphics, brush, &rect, 1);
4554}
4555
4557 INT x, INT y, INT width, INT height)
4558{
4559 GpRectF rect;
4560
4561 TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
4562
4563 rect.X = (REAL)x;
4564 rect.Y = (REAL)y;
4565 rect.Width = (REAL)width;
4566 rect.Height = (REAL)height;
4567
4568 return GdipFillRectangles(graphics, brush, &rect, 1);
4569}
4570
4572 INT count)
4573{
4575 GpPath *path;
4576
4577 TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
4578
4579 if(!graphics || !brush || !rects || count <= 0)
4580 return InvalidParameter;
4581
4582 if (graphics->image && graphics->image->type == ImageTypeMetafile)
4583 {
4584 status = METAFILE_FillRectangles((GpMetafile*)graphics->image, brush, rects, count);
4585 /* FIXME: Add gdi32 drawing. */
4586 return status;
4587 }
4588
4590 if (status != Ok) return status;
4591
4593 if (status == Ok)
4594 status = GdipFillPath(graphics, brush, path);
4595
4597 return status;
4598}
4599
4601 INT count)
4602{
4603 GpRectF *rectsF;
4604 GpStatus ret;
4605 INT i;
4606
4607 TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
4608
4609 if(!rects || count <= 0)
4610 return InvalidParameter;
4611
4612 rectsF = heap_alloc_zero(sizeof(GpRectF)*count);
4613 if(!rectsF)
4614 return OutOfMemory;
4615
4616 for(i = 0; i < count; i++){
4617 rectsF[i].X = (REAL)rects[i].X;
4618 rectsF[i].Y = (REAL)rects[i].Y;
4619 rectsF[i].Width = (REAL)rects[i].Width;
4620 rectsF[i].Height = (REAL)rects[i].Height;
4621 }
4622
4623 ret = GdipFillRectangles(graphics,brush,rectsF,count);
4624 heap_free(rectsF);
4625
4626 return ret;
4627}
4628
4630 GpRegion* region)
4631{
4632 INT save_state;
4634 HRGN hrgn;
4635 RECT rc;
4636
4637 if(!graphics->hdc || !brush_can_fill_path(brush, TRUE))
4638 return NotImplemented;
4639
4640 save_state = SaveDC(graphics->hdc);
4641 EndPath(graphics->hdc);
4642
4643 hrgn = NULL;
4644 status = get_clip_hrgn(graphics, &hrgn);
4645 if (status != Ok)
4646 {
4647 RestoreDC(graphics->hdc, save_state);
4648 return status;
4649 }
4650
4651 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_COPY);
4653
4654 status = GdipGetRegionHRgn(region, graphics, &hrgn);
4655 if (status != Ok)
4656 {
4657 RestoreDC(graphics->hdc, save_state);
4658 return status;
4659 }
4660
4661 ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
4663
4664 if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
4665 {
4666 BeginPath(graphics->hdc);
4667 Rectangle(graphics->hdc, rc.left, rc.top, rc.right, rc.bottom);
4668 EndPath(graphics->hdc);
4669
4670 status = brush_fill_path(graphics, brush);
4671 }
4672
4673 RestoreDC(graphics->hdc, save_state);
4674
4675
4676 return status;
4677}
4678
4680 GpRegion* region)
4681{
4682 GpStatus stat;
4683 GpRegion *temp_region;
4684 GpMatrix world_to_device;
4686 DWORD *pixel_data;
4687 HRGN hregion;
4688 RECT bound_rect;
4689 GpRect gp_bound_rect;
4690
4691 if (!brush_can_fill_pixels(brush))
4692 return NotImplemented;
4693
4694 stat = gdi_transform_acquire(graphics);
4695
4696 if (stat == Ok)
4698
4699 if (stat == Ok)
4700 stat = GdipCloneRegion(region, &temp_region);
4701
4702 if (stat == Ok)
4703 {
4705 CoordinateSpaceWorld, &world_to_device);
4706
4707 if (stat == Ok)
4708 stat = GdipTransformRegion(temp_region, &world_to_device);
4709
4710 if (stat == Ok)
4712
4713 if (stat == Ok)
4714 stat = GdipGetRegionHRgn(temp_region, NULL, &hregion);
4715
4716 GdipDeleteRegion(temp_region);
4717 }
4718
4719 if (stat == Ok && GetRgnBox(hregion, &bound_rect) == NULLREGION)
4720 {
4721 DeleteObject(hregion);
4722 gdi_transform_release(graphics);
4723 return Ok;
4724 }
4725
4726 if (stat == Ok)
4727 {
4728 gp_bound_rect.X = bound_rect.left;
4729 gp_bound_rect.Y = bound_rect.top;
4730 gp_bound_rect.Width = bound_rect.right - bound_rect.left;
4731 gp_bound_rect.Height = bound_rect.bottom - bound_rect.top;
4732
4733 pixel_data = heap_alloc_zero(sizeof(*pixel_data) * gp_bound_rect.Width * gp_bound_rect.Height);
4734 if (!pixel_data)
4735 stat = OutOfMemory;
4736
4737 if (stat == Ok)
4738 {
4739 stat = brush_fill_pixels(graphics, brush, pixel_data,
4740 &gp_bound_rect, gp_bound_rect.Width);
4741
4742 if (stat == Ok)
4743 stat = alpha_blend_pixels_hrgn(graphics, gp_bound_rect.X,
4744 gp_bound_rect.Y, (BYTE*)pixel_data, gp_bound_rect.Width,
4745 gp_bound_rect.Height, gp_bound_rect.Width * 4, hregion,
4747
4748 heap_free(pixel_data);
4749 }
4750
4751 DeleteObject(hregion);
4752 }
4753
4754 gdi_transform_release(graphics);
4755
4756 return stat;
4757}
4758
4759/*****************************************************************************
4760 * GdipFillRegion [GDIPLUS.@]
4761 */
4763 GpRegion* region)
4764{
4766
4767 TRACE("(%p, %p, %p)\n", graphics, brush, region);
4768
4769 if (!(graphics && brush && region))
4770 return InvalidParameter;
4771
4772 if(graphics->busy)
4773 return ObjectBusy;
4774
4775 if (!graphics->image && !graphics->alpha_hdc)
4776 stat = GDI32_GdipFillRegion(graphics, brush, region);
4777
4778 if (stat == NotImplemented)
4779 stat = SOFTWARE_GdipFillRegion(graphics, brush, region);
4780
4781 if (stat == NotImplemented)
4782 {
4783 FIXME("not implemented for brushtype %i\n", brush->bt);
4784 stat = Ok;
4785 }
4786
4787 return stat;
4788}
4789
4791{
4792 TRACE("(%p,%u)\n", graphics, intention);
4793
4794 if(!graphics)
4795 return InvalidParameter;
4796
4797 if(graphics->busy)
4798 return ObjectBusy;
4799
4800 /* We have no internal operation queue, so there's no need to clear it. */
4801
4802 if (graphics->hdc)
4803 GdiFlush();
4804
4805 return Ok;
4806}
4807
4808/*****************************************************************************
4809 * GdipGetClipBounds [GDIPLUS.@]
4810 */
4812{
4814 GpRegion *clip;
4815
4816 TRACE("(%p, %p)\n", graphics, rect);
4817
4818 if(!graphics)
4819 return InvalidParameter;
4820
4821 if(graphics->busy)
4822 return ObjectBusy;
4823
4824 status = GdipCreateRegion(&clip);
4825 if (status != Ok) return status;
4826
4827 status = GdipGetClip(graphics, clip);
4828 if (status == Ok)
4829 status = GdipGetRegionBounds(clip, graphics, rect);
4830
4831 GdipDeleteRegion(clip);
4832 return status;
4833}
4834
4835/*****************************************************************************
4836 * GdipGetClipBoundsI [GDIPLUS.@]
4837 */
4839{
4840 TRACE("(%p, %p)\n", graphics, rect);
4841
4842 if(!graphics)
4843 return InvalidParameter;
4844
4845 if(graphics->busy)
4846 return ObjectBusy;
4847
4848 return GdipGetRegionBoundsI(graphics->clip, graphics, rect);
4849}
4850
4851/* FIXME: Compositing mode is not used anywhere except the getter/setter. */
4854{
4855 TRACE("(%p, %p)\n", graphics, mode);
4856
4857 if(!graphics || !mode)
4858 return InvalidParameter;
4859
4860 if(graphics->busy)
4861 return ObjectBusy;
4862
4863 *mode = graphics->compmode;
4864
4865 return Ok;
4866}
4867
4868/* FIXME: Compositing quality is not used anywhere except the getter/setter. */
4871{
4872 TRACE("(%p, %p)\n", graphics, quality);
4873
4874 if(!graphics || !quality)
4875 return InvalidParameter;
4876
4877 if(graphics->busy)
4878 return ObjectBusy;
4879
4880 *quality = graphics->compqual;
4881
4882 return Ok;
4883}
4884
4885/* FIXME: Interpolation mode is not used anywhere except the getter/setter. */
4888{
4889 TRACE("(%p, %p)\n", graphics, mode);
4890
4891 if(!graphics || !mode)
4892 return InvalidParameter;
4893
4894 if(graphics->busy)
4895 return ObjectBusy;
4896
4897 *mode = graphics->interpolation;
4898
4899 return Ok;
4900}
4901
4902/* FIXME: Need to handle color depths less than 24bpp */
4904{
4905 FIXME("(%p, %p): Passing color unmodified\n", graphics, argb);
4906
4907 if(!graphics || !argb)
4908 return InvalidParameter;
4909
4910 if(graphics->busy)
4911 return ObjectBusy;
4912
4913 return Ok;
4914}
4915
4917{
4918 TRACE("(%p, %p)\n", graphics, scale);
4919
4920 if(!graphics || !scale)
4921 return InvalidParameter;
4922
4923 if(graphics->busy)
4924 return ObjectBusy;
4925
4926 *scale = graphics->scale;
4927
4928 return Ok;
4929}
4930
4932{
4933 TRACE("(%p, %p)\n", graphics, unit);
4934
4935 if(!graphics || !unit)
4936 return InvalidParameter;
4937
4938 if(graphics->busy)
4939 return ObjectBusy;
4940
4941 *unit = graphics->unit;
4942
4943 return Ok;
4944}
4945
4946/* FIXME: Pixel offset mode is not used anywhere except the getter/setter. */
4948 *mode)
4949{
4950 TRACE("(%p, %p)\n", graphics, mode);
4951
4952 if(!graphics || !mode)
4953 return InvalidParameter;
4954
4955 if(graphics->busy)
4956 return ObjectBusy;
4957
4958 *mode = graphics->pixeloffset;
4959
4960 return Ok;
4961}
4962
4963/* FIXME: Smoothing mode is not used anywhere except the getter/setter. */
4965{
4966 TRACE("(%p, %p)\n", graphics, mode);
4967
4968 if(!graphics || !mode)
4969 return InvalidParameter;
4970
4971 if(graphics->busy)
4972 return ObjectBusy;
4973
4974 *mode = graphics->smoothing;
4975
4976 return Ok;
4977}
4978
4980{
4981 TRACE("(%p, %p)\n", graphics, contrast);
4982
4983 if(!graphics || !contrast)
4984 return InvalidParameter;
4985
4986 *contrast = graphics->textcontrast;
4987
4988 return Ok;
4989}
4990
4991/* FIXME: Text rendering hint is not used anywhere except the getter/setter. */
4994{
4995 TRACE("(%p, %p)\n", graphics, hint);
4996
4997 if(!graphics || !hint)
4998 return InvalidParameter;
4999
5000 if(graphics->busy)
5001 return ObjectBusy;
5002
5003 *hint = graphics->texthint;
5004
5005 return Ok;
5006}
5007
5009{
5010 GpRegion *clip_rgn;
5011 GpStatus stat;
5012 GpMatrix device_to_world;
5013
5014 TRACE("(%p, %p)\n", graphics, rect);
5015
5016 if(!graphics || !rect)
5017 return InvalidParameter;
5018
5019 if(graphics->busy)
5020 return ObjectBusy;
5021
5022 /* intersect window and graphics clipping regions */
5023 if((stat = GdipCreateRegion(&clip_rgn)) != Ok)
5024 return stat;
5025
5026 if((stat = get_visible_clip_region(graphics, clip_rgn)) != Ok)
5027 goto cleanup;
5028
5029 /* transform to world coordinates */
5030 if((stat = get_graphics_transform(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &device_to_world)) != Ok)
5031 goto cleanup;
5032
5033 if((stat = GdipTransformRegion(clip_rgn, &device_to_world)) != Ok)
5034 goto cleanup;
5035
5036 /* get bounds of the region */
5037 stat = GdipGetRegionBounds(clip_rgn, graphics, rect);
5038
5039cleanup:
5040 GdipDeleteRegion(clip_rgn);
5041
5042 return stat;
5043}
5044
5046{
5047 GpRectF rectf;
5048 GpStatus stat;
5049
5050 TRACE("(%p, %p)\n", graphics, rect);
5051
5052 if(!graphics || !rect)
5053 return InvalidParameter;
5054
5055 if((stat = GdipGetVisibleClipBounds(graphics, &rectf)) == Ok)
5056 {
5057 rect->X = gdip_round(rectf.X);
5058 rect->Y = gdip_round(rectf.Y);
5059 rect->Width = gdip_round(rectf.Width);
5060 rect->Height = gdip_round(rectf.Height);
5061 }
5062
5063 return stat;
5064}
5065
5067{
5068 TRACE("(%p, %p)\n", graphics, matrix);
5069
5070 if(!graphics || !matrix)
5071 return InvalidParameter;
5072
5073 if(graphics->busy)
5074 return ObjectBusy;
5075
5076 *matrix = graphics->worldtrans;
5077 return Ok;
5078}
5079
5081{
5082 GpSolidFill *brush;
5083 GpStatus stat;
5084 GpRectF wnd_rect;
5085
5086 TRACE("(%p, %x)\n", graphics, color);
5087
5088 if(!graphics)
5089 return InvalidParameter;
5090
5091 if(graphics->busy)
5092 return ObjectBusy;
5093
5094 if (graphics->image && graphics->image->type == ImageTypeMetafile)
5095 return METAFILE_GraphicsClear((GpMetafile*)graphics->image, color);
5096
5097 if((stat = GdipCreateSolidFill(color, &brush)) != Ok)
5098 return stat;
5099
5100 if((stat = GdipGetVisibleClipBounds(graphics, &wnd_rect)) != Ok){
5101 GdipDeleteBrush((GpBrush*)brush);
5102 return stat;
5103 }
5104
5105 GdipFillRectangle(graphics, (GpBrush*)brush, wnd_rect.X, wnd_rect.Y,
5106 wnd_rect.Width, wnd_rect.Height);
5107
5108 GdipDeleteBrush((GpBrush*)brush);
5109
5110 return Ok;
5111}
5112
5114{
5115 TRACE("(%p, %p)\n", graphics, res);
5116
5117 if(!graphics || !res)
5118 return InvalidParameter;
5119
5120 return GdipIsEmptyRegion(graphics->clip, graphics, res);
5121}
5122
5124{
5125 GpStatus stat;
5126 GpRegion* rgn;
5127 GpPointF pt;
5128
5129 TRACE("(%p, %.2f, %.2f, %p)\n", graphics, x, y, result);
5130
5131 if(!graphics || !result)
5132 return InvalidParameter;
5133
5134 if(graphics->busy)
5135 return ObjectBusy;
5136
5137 pt.X = x;
5138 pt.Y = y;
5140 CoordinateSpaceWorld, &pt, 1)) != Ok)
5141 return stat;
5142
5143 if((stat = GdipCreateRegion(&rgn)) != Ok)
5144 return stat;
5145
5146 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
5147 goto cleanup;
5148
5149 stat = GdipIsVisibleRegionPoint(rgn, pt.X, pt.Y, graphics, result);
5150
5151cleanup:
5152 GdipDeleteRegion(rgn);
5153 return stat;
5154}
5155
5157{
5158 return GdipIsVisiblePoint(graphics, (REAL)x, (REAL)y, result);
5159}
5160
5162{
5163 GpStatus stat;
5164 GpRegion* rgn;
5165 GpPointF pts[2];
5166
5167 TRACE("(%p %.2f %.2f %.2f %.2f %p)\n", graphics, x, y, width, height, result);
5168
5169 if(!graphics || !result)
5170 return InvalidParameter;
5171
5172 if(graphics->busy)
5173 return ObjectBusy;
5174
5175 pts[0].X = x;
5176 pts[0].Y = y;
5177 pts[1].X = x + width;
5178 pts[1].Y = y + height;
5179
5181 CoordinateSpaceWorld, pts, 2)) != Ok)
5182 return stat;
5183
5184 pts[1].X -= pts[0].X;
5185 pts[1].Y -= pts[0].Y;
5186
5187 if((stat = GdipCreateRegion(&rgn)) != Ok)
5188 return stat;
5189
5190 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
5191 goto cleanup;
5192
5193 stat = GdipIsVisibleRegionRect(rgn, pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, graphics, result);
5194
5195cleanup:
5196 GdipDeleteRegion(rgn);
5197 return stat;
5198}
5199
5201{
5202 return GdipIsVisibleRect(graphics, (REAL)x, (REAL)y, (REAL)width, (REAL)height, result);
5203}
5204
5207 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip,
5208 gdip_format_string_callback callback, void *user_data)
5209{
5210 WCHAR* stringdup;
5211 int sum = 0, height = 0, fit, fitcpy, i, j, lret, nwidth,
5212 nheight, lineend, lineno = 0;
5213 RectF bounds;
5214 StringAlignment halign;
5215 GpStatus stat = Ok;
5216 SIZE size;
5217 HotkeyPrefix hkprefix;
5218 INT *hotkeyprefix_offsets=NULL;
5219 INT hotkeyprefix_count=0;
5220 INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
5221 BOOL seen_prefix = FALSE;
5222
5223 if(length == -1) length = lstrlenW(string);
5224
5225 stringdup = heap_alloc_zero((length + 1) * sizeof(WCHAR));
5226 if(!stringdup) return OutOfMemory;
5227
5228 if (!format)
5230
5231 nwidth = rect->Width;
5232 nheight = rect->Height;
5233 if (ignore_empty_clip)
5234 {
5235 if (!nwidth) nwidth = INT_MAX;
5236 if (!nheight) nheight = INT_MAX;
5237 }
5238
5239 hkprefix = format->hkprefix;
5240
5241 if (hkprefix == HotkeyPrefixShow)
5242 {
5243 for (i=0; i<length; i++)
5244 {
5245 if (string[i] == '&')
5246 hotkeyprefix_count++;
5247 }
5248 }
5249
5250 if (hotkeyprefix_count)
5251 hotkeyprefix_offsets = heap_alloc_zero(sizeof(INT) * hotkeyprefix_count);
5252
5253 hotkeyprefix_count = 0;
5254
5255 for(i = 0, j = 0; i < length; i++){
5256 /* FIXME: This makes the indexes passed to callback inaccurate. */
5257 if(!isprintW(string[i]) && (string[i] != '\n'))
5258 continue;
5259
5260 /* FIXME: tabs should be handled using tabstops from stringformat */
5261 if (string[i] == '\t')
5262 continue;
5263
5264 if (seen_prefix && hkprefix == HotkeyPrefixShow && string[i] != '&')
5265 hotkeyprefix_offsets[hotkeyprefix_count++] = j;
5266 else if (!seen_prefix && hkprefix != HotkeyPrefixNone && string[i] == '&')
5267 {
5268 seen_prefix = TRUE;
5269 continue;
5270 }
5271
5272 seen_prefix = FALSE;
5273
5274 stringdup[j] = string[i];
5275 j++;
5276 }
5277
5278 length = j;
5279
5280 halign = format->align;
5281
5282 while(sum < length){
5283 GetTextExtentExPointW(hdc, stringdup + sum, length - sum,
5284 nwidth, &fit, NULL, &size);
5285 fitcpy = fit;
5286
5287 if(fit == 0)
5288 break;
5289
5290 for(lret = 0; lret < fit; lret++)
5291 if(*(stringdup + sum + lret) == '\n')
5292 break;
5293
5294 /* Line break code (may look strange, but it imitates windows). */
5295 if(lret < fit)
5296 lineend = fit = lret; /* this is not an off-by-one error */
5297 else if(fit < (length - sum)){
5298 if(*(stringdup + sum + fit) == ' ')
5299 while(*(stringdup + sum + fit) == ' ')
5300 fit++;
5301 else
5302 while(*(stringdup + sum + fit - 1) != ' '){
5303 fit--;
5304
5305 if(*(stringdup + sum + fit) == '\t')
5306 break;
5307
5308 if(fit == 0){
5309 fit = fitcpy;
5310 break;
5311 }
5312 }
5313 lineend = fit;
5314 while(*(stringdup + sum + lineend - 1) == ' ' ||
5315 *(stringdup + sum + lineend - 1) == '\t')
5316 lineend--;
5317 }
5318 else
5319 lineend = fit;
5320
5321 GetTextExtentExPointW(hdc, stringdup + sum, lineend,
5322 nwidth, &j, NULL, &size);
5323
5324 bounds.Width = size.cx;
5325
5326 if(height + size.cy > nheight)
5327 {
5329 break;
5330 bounds.Height = nheight - (height + size.cy);
5331 }
5332 else
5333 bounds.Height = size.cy;
5334
5335 bounds.Y = rect->Y + height;
5336
5337 switch (halign)
5338 {
5340 default:
5341 bounds.X = rect->X;
5342 break;
5344 bounds.X = rect->X + (rect->Width/2) - (bounds.Width/2);
5345 break;
5346 case StringAlignmentFar:
5347 bounds.X = rect->X + rect->Width - bounds.Width;
5348 break;
5349 }
5350
5351 for (hotkeyprefix_end_pos=hotkeyprefix_pos; hotkeyprefix_end_pos<hotkeyprefix_count; hotkeyprefix_end_pos++)
5352 if (hotkeyprefix_offsets[hotkeyprefix_end_pos] >= sum + lineend)
5353 break;
5354
5355 stat = callback(hdc, stringdup, sum, lineend,
5356 font, rect, format, lineno, &bounds,
5357 &hotkeyprefix_offsets[hotkeyprefix_pos],
5358 hotkeyprefix_end_pos-hotkeyprefix_pos, user_data);
5359
5360 if (stat != Ok)
5361 break;
5362
5363 sum += fit + (lret < fitcpy ? 1 : 0);
5364 height += size.cy;
5365 lineno++;
5366
5367 hotkeyprefix_pos = hotkeyprefix_end_pos;
5368
5369 if(height > nheight)
5370 break;
5371
5372 /* Stop if this was a linewrap (but not if it was a linebreak). */
5373 if ((lret == fitcpy) && (format->attr & StringFormatFlagsNoWrap))
5374 break;
5375 }
5376
5377 heap_free(stringdup);
5378 heap_free(hotkeyprefix_offsets);
5379
5380 return stat;
5381}
5382
5386};
5387
5391 INT lineno, const RectF *bounds, INT *underlined_indexes,
5392 INT underlined_index_count, void *user_data)
5393{
5394 int i;
5395 GpStatus stat = Ok;
5396 struct measure_ranges_args *args = user_data;
5397
5398 for (i=0; i<format->range_count; i++)
5399 {
5400 INT range_start = max(index, format->character_ranges[i].First);
5401 INT range_end = min(index+length, format->character_ranges[i].First+format->character_ranges[i].Length);
5402 if (range_start < range_end)
5403 {
5404 GpRectF range_rect;
5405 SIZE range_size;
5406
5407 range_rect.Y = bounds->Y / args->rel_height;
5408 range_rect.Height = bounds->Height / args->rel_height;
5409
5410 GetTextExtentExPointW(hdc, string + index, range_start - index,
5411 INT_MAX, NULL, NULL, &range_size);
5412 range_rect.X = (bounds->X + range_size.cx) / args->rel_width;
5413
5414 GetTextExtentExPointW(hdc, string + index, range_end - index,
5415 INT_MAX, NULL, NULL, &range_size);
5416 range_rect.Width = (bounds->X + range_size.cx) / args->rel_width - range_rect.X;
5417
5418 stat = GdipCombineRegionRect(args->regions[i], &range_rect, CombineModeUnion);
5419 if (stat != Ok)
5420 break;
5421 }
5422 }
5423
5424 return stat;
5425}
5426
5430 INT regionCount, GpRegion** regions)
5431{
5432 GpStatus stat;
5433 int i;
5434 HFONT gdifont, oldfont;
5436 HDC hdc, temp_hdc=NULL;
5437 GpPointF pt[3];
5438 RectF scaled_rect;
5439 REAL margin_x;
5440
5441 TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_wn(string, length),
5442 length, font, debugstr_rectf(layoutRect), stringFormat, regionCount, regions);
5443
5444 if (!(graphics && string && font && layoutRect && stringFormat && regions))
5445 return InvalidParameter;
5446
5447 if (regionCount < stringFormat->range_count)
5448 return InvalidParameter;
5449
5450 if(!graphics->hdc)
5451 {
5452 hdc = temp_hdc = CreateCompatibleDC(0);
5453 if (!temp_hdc) return OutOfMemory;
5454 }
5455 else
5456 hdc = graphics->hdc;
5457
5458 if (stringFormat->attr)
5459 TRACE("may be ignoring some format flags: attr %x\n", stringFormat->attr);
5460
5461 pt[0].X = 0.0;
5462 pt[0].Y = 0.0;
5463 pt[1].X = 1.0;
5464 pt[1].Y = 0.0;
5465 pt[2].X = 0.0;
5466 pt[2].Y = 1.0;
5468 args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5469 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5470 args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5471 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5472
5473 margin_x = stringFormat->generic_typographic ? 0.0 : font->emSize / 6.0;
5474 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5475
5476 scaled_rect.X = (layoutRect->X + margin_x) * args.rel_width;
5477 scaled_rect.Y = layoutRect->Y * args.rel_height;
5478 scaled_rect.Width = layoutRect->Width * args.rel_width;
5479 scaled_rect.Height = layoutRect->Height * args.rel_height;
5480
5481 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5482 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5483
5484 get_font_hfont(graphics, font, stringFormat, &gdifont, NULL);
5485 oldfont = SelectObject(hdc, gdifont);
5486
5487 for (i=0; i<stringFormat->range_count; i++)
5488 {
5490 if (stat != Ok)
5491 return stat;
5492 }
5493
5494 args.regions = regions;
5495
5496 gdi_transform_acquire(graphics);
5497
5498 stat = gdip_format_string(hdc, string, length, font, &scaled_rect, stringFormat,
5500
5501 gdi_transform_release(graphics);
5502
5503 SelectObject(hdc, oldfont);
5504 DeleteObject(gdifont);
5505
5506 if (temp_hdc)
5507 DeleteDC(temp_hdc);
5508
5509 return stat;
5510}
5511
5517};
5518
5522 INT lineno, const RectF *bounds, INT *underlined_indexes,
5523 INT underlined_index_count, void *user_data)
5524{
5525 struct measure_string_args *args = user_data;
5526 REAL new_width, new_height;
5527
5528 new_width = bounds->Width / args->rel_width;
5529 new_height = (bounds->Height + bounds->Y) / args->rel_height - args->bounds->Y;
5530
5531 if (new_width > args->bounds->Width)
5532 args->bounds->Width = new_width;
5533
5534 if (new_height > args->bounds->Height)
5535 args->bounds->Height = new_height;
5536
5537 if (args->codepointsfitted)
5538 *args->codepointsfitted = index + length;
5539
5540 if (args->linesfilled)
5541 (*args->linesfilled)++;
5542
5543 return Ok;
5544}
5545
5546/* Find the smallest rectangle that bounds the text when it is printed in rect
5547 * according to the format options listed in format. If rect has 0 width and
5548 * height, then just find the smallest rectangle that bounds the text when it's
5549 * printed at location (rect->X, rect-Y). */
5554{
5555 HFONT oldfont, gdifont;
5557 HDC temp_hdc=NULL, hdc;
5558 GpPointF pt[3];
5559 RectF scaled_rect;
5560 REAL margin_x;
5561 INT lines, glyphs;
5562
5563 TRACE("(%p, %s, %i, %p, %s, %p, %p, %p, %p)\n", graphics,
5566
5567 if(!graphics || !string || !font || !rect || !bounds)
5568 return InvalidParameter;
5569
5570 if(!graphics->hdc)
5571 {
5572 hdc = temp_hdc = CreateCompatibleDC(0);
5573 if (!temp_hdc) return OutOfMemory;
5574 }
5575 else
5576 hdc = graphics->hdc;
5577
5578 if(linesfilled) *linesfilled = 0;
5580
5581 if(format)
5582 TRACE("may be ignoring some format flags: attr %x\n", format->attr);
5583
5584 pt[0].X = 0.0;
5585 pt[0].Y = 0.0;
5586 pt[1].X = 1.0;
5587 pt[1].Y = 0.0;
5588 pt[2].X = 0.0;
5589 pt[2].Y = 1.0;
5591 args.rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5592 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5593 args.rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5594 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5595
5596 margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
5597 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5598
5599 scaled_rect.X = (rect->X + margin_x) * args.rel_width;
5600 scaled_rect.Y = rect->Y * args.rel_height;
5601 scaled_rect.Width = rect->Width * args.rel_width;
5602 scaled_rect.Height = rect->Height * args.rel_height;
5603 if (scaled_rect.Width >= 0.5)
5604 {
5605 scaled_rect.Width -= margin_x * 2.0 * args.rel_width;
5606 if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
5607 }
5608
5609 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5610 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5611
5612 get_font_hfont(graphics, font, format, &gdifont, NULL);
5613 oldfont = SelectObject(hdc, gdifont);
5614
5615 bounds->X = rect->X;
5616 bounds->Y = rect->Y;
5617 bounds->Width = 0.0;
5618 bounds->Height = 0.0;
5619
5620 args.bounds = bounds;
5621 args.codepointsfitted = &glyphs;
5622 args.linesfilled = &lines;
5623 lines = glyphs = 0;
5624
5625 gdi_transform_acquire(graphics);
5626
5627 gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
5629
5630 gdi_transform_release(graphics);
5631
5634
5635 if (lines)
5636 bounds->Width += margin_x * 2.0;
5637
5638 SelectObject(hdc, oldfont);
5639 DeleteObject(gdifont);
5640
5641 if (temp_hdc)
5642 DeleteDC(temp_hdc);
5643
5644 return Ok;
5645}
5646
5651};
5652
5656 INT lineno, const RectF *bounds, INT *underlined_indexes,
5657 INT underlined_index_count, void *user_data)
5658{
5659 struct draw_string_args *args = user_data;
5660 PointF position;
5661 GpStatus stat;
5662
5663 position.X = args->x + bounds->X / args->rel_width;
5664 position.Y = args->y + bounds->Y / args->rel_height + args->ascent;
5665
5666 stat = draw_driver_string(args->graphics, &string[index], length, font, format,
5667 args->brush, &position,
5669
5670 if (stat == Ok && underlined_index_count)
5671 {
5673 REAL underline_y, underline_height;
5674 int i;
5675
5676 GetOutlineTextMetricsW(hdc, sizeof(otm), &otm);
5677
5678 underline_height = otm.otmsUnderscoreSize / args->rel_height;
5679 underline_y = position.Y - otm.otmsUnderscorePosition / args->rel_height - underline_height / 2;
5680
5681 for (i=0; i<underlined_index_count; i++)
5682 {
5684 SIZE text_size;
5685 INT ofs = underlined_indexes[i] - index;
5686
5687 GetTextExtentExPointW(hdc, string + index, ofs, INT_MAX, NULL, NULL, &text_size);
5688 start_x = text_size.cx / args->rel_width;
5689
5690 GetTextExtentExPointW(hdc, string + index, ofs+1, INT_MAX, NULL, NULL, &text_size);
5691 end_x = text_size.cx / args->rel_width;
5692
5693 GdipFillRectangle(args->graphics, (GpBrush*)args->brush, position.X+start_x, underline_y, end_x-start_x, underline_height);
5694 }
5695 }
5696
5697 return stat;
5698}
5699
5703{
5704 HRGN rgn = NULL;
5705 HFONT gdifont;
5706 GpPointF pt[3], rectcpy[4];
5707 POINT corners[4];
5708 REAL rel_width, rel_height, margin_x;
5709 INT save_state, format_flags = 0;
5710 REAL offsety = 0.0;
5711 struct draw_string_args args;
5712 RectF scaled_rect;
5713 HDC hdc, temp_hdc=NULL;
5714 TEXTMETRICW textmetric;
5715
5716 TRACE("(%p, %s, %i, %p, %s, %p, %p)\n", graphics, debugstr_wn(string, length),
5718
5719 if(!graphics || !string || !font || !brush || !rect)
5720 return InvalidParameter;
5721
5722 if(graphics->hdc)
5723 {
5724 hdc = graphics->hdc;
5725 }
5726 else
5727 {
5728 hdc = temp_hdc = CreateCompatibleDC(0);
5729 }
5730
5731 if(format){
5732 TRACE("may be ignoring some format flags: attr %x\n", format->attr);
5733
5734 format_flags = format->attr;
5735
5736 /* Should be no need to explicitly test for StringAlignmentNear as
5737 * that is default behavior if no alignment is passed. */
5738 if(format->line_align != StringAlignmentNear){
5739 RectF bounds, in_rect = *rect;
5740 in_rect.Height = 0.0; /* avoid height clipping */
5741 GdipMeasureString(graphics, string, length, font, &in_rect, format, &bounds, 0, 0);
5742
5743 TRACE("bounds %s\n", debugstr_rectf(&bounds));
5744
5745 if(format->line_align == StringAlignmentCenter)
5746 offsety = (rect->Height - bounds.Height) / 2;
5747 else if(format->line_align == StringAlignmentFar)
5748 offsety = (rect->Height - bounds.Height);
5749 }
5750 TRACE("line align %d, offsety %f\n", format->line_align, offsety);
5751 }
5752
5753 save_state = SaveDC(hdc);
5754
5755 pt[0].X = 0.0;
5756 pt[0].Y = 0.0;
5757 pt[1].X = 1.0;
5758 pt[1].Y = 0.0;
5759 pt[2].X = 0.0;
5760 pt[2].Y = 1.0;
5762 rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
5763 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
5764 rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
5765 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
5766
5767 rectcpy[3].X = rectcpy[0].X = rect->X;
5768 rectcpy[1].Y = rectcpy[0].Y = rect->Y;
5769 rectcpy[2].X = rectcpy[1].X = rect->X + rect->Width;
5770 rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
5772 round_points(corners, rectcpy, 4);
5773
5774 margin_x = (format && format->generic_typographic) ? 0.0 : font->emSize / 6.0;
5775 margin_x *= units_scale(font->unit, graphics->unit, graphics->xres);
5776
5777 scaled_rect.X = margin_x * rel_width;
5778 scaled_rect.Y = 0.0;
5779 scaled_rect.Width = rel_width * rect->Width;
5780 scaled_rect.Height = rel_height * rect->Height;
5781 if (scaled_rect.Width >= 0.5)
5782 {
5783 scaled_rect.Width -= margin_x * 2.0 * rel_width;
5784 if (scaled_rect.Width < 0.5) return Ok; /* doesn't fit */
5785 }
5786
5787 if (scaled_rect.Width >= 1 << 23) scaled_rect.Width = 1 << 23;
5788 if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
5789
5790 if (!(format_flags & StringFormatFlagsNoClip) &&
5791 scaled_rect.Width != 1 << 23 && scaled_rect.Height != 1 << 23 &&
5792 rect->Width > 0.0 && rect->Height > 0.0)
5793 {
5794 /* FIXME: If only the width or only the height is 0, we should probably still clip */
5795 rgn = CreatePolygonRgn(corners, 4, ALTERNATE);
5796 SelectClipRgn(hdc, rgn);
5797 }
5798
5799 get_font_hfont(graphics, font, format, &gdifont, NULL);
5800 SelectObject(hdc, gdifont);
5801
5802 args.graphics = graphics;
5803 args.brush = brush;
5804
5805 args.x = rect->X;
5806 args.y = rect->Y + offsety;
5807
5808 args.rel_width = rel_width;
5809 args.rel_height = rel_height;
5810
5812
5813 GetTextMetricsW(hdc, &textmetric);
5814 args.ascent = textmetric.tmAscent / rel_height;
5815
5816 gdip_format_string(hdc, string, length, font, &scaled_rect, format, TRUE,
5818
5820
5821 DeleteObject(rgn);
5822 DeleteObject(gdifont);
5823
5824 RestoreDC(hdc, save_state);
5825
5826 DeleteDC(temp_hdc);
5827
5828 return Ok;
5829}
5830
5832{
5833 TRACE("(%p)\n", graphics);
5834
5835 if(!graphics)
5836 return InvalidParameter;
5837
5838 if(graphics->busy)
5839 return ObjectBusy;
5840
5841 return GdipSetInfinite(graphics->clip);
5842}
5843
5845{
5846 GpStatus stat;
5847
5848 TRACE("(%p)\n", graphics);
5849
5850 if(!graphics)
5851 return InvalidParameter;
5852
5853 if(graphics->busy)
5854 return ObjectBusy;
5855
5858
5859 if (stat != Ok)
5860 return stat;
5861 }
5862
5863 return GdipSetMatrixElements(&graphics->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
5864}
5865
5868{
5869 GpStatus stat;
5870
5871 TRACE("(%p, %.2f, %d)\n", graphics, angle, order);
5872
5873 if(!graphics)
5874 return InvalidParameter;
5875
5876 if(graphics->busy)
5877 return ObjectBusy;
5878
5881
5882 if (stat != Ok)
5883 return stat;
5884 }
5885
5887}
5888
5891{
5893 GpStatus sts;
5894
5895 if(!graphics || !state)
5896 return InvalidParameter;
5897
5899 if(sts != Ok)
5900 return sts;
5901
5903 *state = graphics->contid = container->contid;
5904
5906 if (type == BEGIN_CONTAINER)
5908 else
5910 }
5911
5912 return Ok;
5913}
5914
5916{
5917 TRACE("(%p, %p)\n", graphics, state);
5919}
5920
5923{
5924 TRACE("(%p, %p)\n", graphics, state);
5926}
5927
5929{
5932 GpStatus stat;
5933 GpRectF scaled_srcrect;
5934 REAL scale_x, scale_y;
5935
5936 TRACE("(%p, %s, %s, %d, %p)\n", graphics, debugstr_rectf(dstrect), debugstr_rectf(srcrect), unit, state);
5937
5938 if(!graphics || !dstrect || !srcrect || unit < UnitPixel || unit > UnitMillimeter || !state)
5939 return InvalidParameter;
5940
5942 if(stat != Ok)
5943 return stat;
5944
5946 *state = graphics->contid = container->contid;
5947
5948 scale_x = units_to_pixels(1.0, unit, graphics->xres);
5949 scale_y = units_to_pixels(1.0, unit, graphics->yres);
5950
5951 scaled_srcrect.X = scale_x * srcrect->X;
5952 scaled_srcrect.Y = scale_y * srcrect->Y;
5953 scaled_srcrect.Width = scale_x * srcrect->Width;
5954 scaled_srcrect.Height = scale_y * srcrect->Height;
5955
5956 transform.matrix[0] = dstrect->Width / scaled_srcrect.Width;
5957 transform.matrix[1] = 0.0;
5958 transform.matrix[2] = 0.0;
5959 transform.matrix[3] = dstrect->Height / scaled_srcrect.Height;
5960 transform.matrix[4] = dstrect->X - scaled_srcrect.X;
5961 transform.matrix[5] = dstrect->Y - scaled_srcrect.Y;
5962
5964
5966 METAFILE_BeginContainer((GpMetafile*)graphics->image, dstrect, srcrect, unit, container->contid);
5967 }
5968
5969 return Ok;
5970}
5971
5973{
5974 GpRectF dstrectf, srcrectf;
5975
5976 TRACE("(%p, %p, %p, %d, %p)\n", graphics, dstrect, srcrect, unit, state);
5977
5978 if (!dstrect || !srcrect)
5979 return InvalidParameter;
5980
5981 dstrectf.X = dstrect->X;
5982 dstrectf.Y = dstrect->Y;
5983 dstrectf.Width = dstrect->Width;
5984 dstrectf.Height = dstrect->Height;
5985
5986 srcrectf.X = srcrect->X;
5987 srcrectf.Y = srcrect->Y;
5988 srcrectf.Width = srcrect->Width;
5989 srcrectf.Height = srcrect->Height;
5990
5991 return GdipBeginContainer(graphics, &dstrectf, &srcrectf, unit, state);
5992}
5993
5995{
5996 FIXME("(%p, %d, %p): stub\n", graphics, sizeData, data);
5997 return NotImplemented;
5998}
5999
6002{
6003 GpStatus sts;
6004 GraphicsContainerItem *container, *container2;
6005
6006 if(!graphics)
6007 return InvalidParameter;
6008
6010 if(container->contid == state && container->type == type)
6011 break;
6012 }
6013
6014 /* did not find a matching container */
6016 return Ok;
6017
6019 if(sts != Ok)
6020 return sts;
6021
6022 /* remove all of the containers on top of the found container */
6024 if(container->contid == state)
6025 break;
6028 }
6029
6032
6034 if (type == BEGIN_CONTAINER)
6036 else
6038 }
6039
6040 return Ok;
6041}
6042
6044{
6045 TRACE("(%p, %x)\n", graphics, state);
6047}
6048
6050{
6051 TRACE("(%p, %x)\n", graphics, state);
6053}
6054
6057{
6058 GpStatus stat;
6059
6060 TRACE("(%p, %.2f, %.2f, %d)\n", graphics, sx, sy, order);
6061
6062 if(!graphics)
6063 return InvalidParameter;
6064
6065 if(graphics->busy)
6066 return ObjectBusy;
6067
6070
6071 if (stat != Ok)
6072 return stat;
6073 }
6074
6075 return GdipScaleMatrix(&graphics->worldtrans, sx, sy, order);
6076}
6077
6080{
6081 TRACE("(%p, %p, %d)\n", graphics, srcgraphics, mode);
6082
6083 if(!graphics || !srcgraphics)
6084 return InvalidParameter;
6085
6086 return GdipCombineRegionRegion(graphics->clip, srcgraphics->clip, mode);
6087}
6088
6091{
6092 TRACE("(%p, %d)\n", graphics, mode);
6093
6094 if(!graphics)
6095 return InvalidParameter;
6096
6097 if(graphics->busy)
6098 return ObjectBusy;
6099
6100 if(graphics->compmode == mode)
6101 return Ok;
6102
6104 {
6105 GpStatus stat;
6106
6109 if(stat != Ok)
6110 return stat;
6111 }
6112
6114
6115 return Ok;
6116}
6117
6120{
6121 TRACE("(%p, %d)\n", graphics, quality);
6122
6123 if(!graphics)
6124 return InvalidParameter;
6125
6126 if(graphics->busy)
6127 return ObjectBusy;
6128
6129 if(graphics->compqual == quality)
6130 return Ok;
6131
6133 {
6134 GpStatus stat;
6135
6138 if(stat != Ok)
6139 return stat;
6140 }
6141
6143
6144 return Ok;
6145}
6146
6149{
6150 TRACE("(%p, %d)\n", graphics, mode);
6151
6153 return InvalidParameter;
6154
6155 if(graphics->busy)
6156 return ObjectBusy;
6157
6160
6163
6164 if (mode == graphics->interpolation)
6165 return Ok;
6166
6168 {
6169 GpStatus stat;
6170
6173 if (stat != Ok)
6174 return stat;
6175 }
6176
6178
6179 return Ok;
6180}
6181
6183{
6184 GpStatus stat;
6185
6186 TRACE("(%p, %.2f)\n", graphics, scale);
6187
6188 if(!graphics || (scale <= 0.0))
6189 return InvalidParameter;
6190
6191 if(graphics->busy)
6192 return ObjectBusy;
6193
6195 {
6197 if (stat != Ok)
6198 return stat;
6199 }
6200
6201 graphics->scale = scale;
6202
6203 return Ok;
6204}
6205
6207{
6208 GpStatus stat;
6209
6210 TRACE("(%p, %d)\n", graphics, unit);
6211
6212 if(!graphics)
6213 return InvalidParameter;
6214
6215 if(graphics->busy)
6216 return ObjectBusy;
6217
6218 if(unit == UnitWorld)
6219 return InvalidParameter;
6220
6222 {
6224 if (stat != Ok)
6225 return stat;
6226 }
6227
6228 graphics->unit = unit;
6229
6230 return Ok;
6231}
6232
6234 mode)
6235{
6236 TRACE("(%p, %d)\n", graphics, mode);
6237
6238 if(!graphics)
6239 return InvalidParameter;
6240
6241 if(graphics->busy)
6242 return ObjectBusy;
6243
6244 if(graphics->pixeloffset == mode)
6245 return Ok;
6246
6248 {
6249 GpStatus stat;
6250
6253 if(stat != Ok)
6254 return stat;
6255 }
6256
6258
6259 return Ok;
6260}
6261
6263{
6264 static int calls;
6265
6266 TRACE("(%p,%i,%i)\n", graphics, x, y);
6267
6268 if (!(calls++))
6269 FIXME("value is unused in rendering\n");
6270
6271 if (!graphics)
6272 return InvalidParameter;
6273
6274 graphics->origin_x = x;
6275 graphics->origin_y = y;
6276
6277 return Ok;
6278}
6279
6281{
6282 TRACE("(%p,%p,%p)\n", graphics, x, y);
6283
6284 if (!graphics || !x || !y)
6285 return InvalidParameter;
6286
6287 *x = graphics->origin_x;
6288 *y = graphics->origin_y;
6289
6290 return Ok;
6291}
6292
6294{
6295 TRACE("(%p, %d)\n", graphics, mode);
6296
6297 if(!graphics)
6298 return InvalidParameter;
6299
6300 if(graphics->busy)
6301 return ObjectBusy;
6302
6303 if(graphics->smoothing == mode)
6304 return Ok;
6305
6307 GpStatus stat;
6308 BOOL antialias = (mode != SmoothingModeDefault &&
6310
6312 EmfPlusRecordTypeSetAntiAliasMode, (mode << 1) + antialias);
6313 if(stat != Ok)
6314 return stat;
6315 }
6316
6318
6319 return Ok;
6320}
6321
6323{
6324 TRACE("(%p, %d)\n", graphics, contrast);
6325
6326 if(!graphics)
6327 return InvalidParameter;
6328
6329 graphics->textcontrast = contrast;
6330
6331 return Ok;
6332}
6333
6336{
6337 TRACE("(%p, %d)\n", graphics, hint);
6338
6340 return InvalidParameter;
6341
6342 if(graphics->busy)
6343 return ObjectBusy;
6344
6345 if(graphics->texthint == hint)
6346 return Ok;
6347
6349 GpStatus stat;
6350
6353 if(stat != Ok)
6354 return stat;
6355 }
6356
6358
6359 return Ok;
6360}
6361
6363{
6364 GpStatus stat;
6365
6366 TRACE("(%p, %p)\n", graphics, matrix);
6367
6368 if(!graphics || !matrix)
6369 return InvalidParameter;
6370
6371 if(graphics->busy)
6372 return ObjectBusy;
6373
6374 TRACE("%f,%f,%f,%f,%f,%f\n",
6375 matrix->matrix[0], matrix->matrix[1], matrix->matrix[2],
6376 matrix->matrix[3], matrix->matrix[4], matrix->matrix[5]);
6377
6380
6381 if (stat != Ok)
6382 return stat;
6383 }
6384
6386
6387 return Ok;
6388}
6389
6392{
6393 GpStatus stat;
6394
6395 TRACE("(%p, %.2f, %.2f, %d)\n", graphics, dx, dy, order);
6396
6397 if(!graphics)
6398 return InvalidParameter;
6399
6400 if(graphics->busy)
6401 return ObjectBusy;
6402
6405
6406 if (stat != Ok)
6407 return stat;
6408 }
6409
6411}
6412
6413/*****************************************************************************
6414 * GdipSetClipHrgn [GDIPLUS.@]
6415 */
6417{
6418 GpRegion *region;
6421
6422 TRACE("(%p, %p, %d)\n", graphics, hrgn, mode);
6423
6424 if(!graphics)
6425 return InvalidParameter;
6426
6427 if(graphics->busy)
6428 return ObjectBusy;
6429
6430 /* hrgn is in gdi32 device units */
6431 status = GdipCreateRegionHrgn(hrgn, &region);
6432
6433 if (status == Ok)
6434 {
6436
6437 if (status == Ok)
6439
6440 if (status == Ok)
6442
6443 GdipDeleteRegion(region);
6444 }
6445 return status;
6446}
6447
6449{
6451 GpPath *clip_path;
6452
6453 TRACE("(%p, %p, %d)\n", graphics, path, mode);
6454
6455 if(!graphics)
6456 return InvalidParameter;
6457
6458 if(graphics->busy)
6459 return ObjectBusy;
6460
6461 status = GdipClonePath(path, &clip_path);
6462 if (status == Ok)
6463 {
6464 GpMatrix world_to_device;
6465
6467 CoordinateSpaceWorld, &world_to_device);
6468 status = GdipTransformPath(clip_path, &world_to_device);
6469 if (status == Ok)
6471
6472 GdipDeletePath(clip_path);
6473 }
6474 return status;
6475}
6476
6480{
6482 GpRectF rect;
6483 GpRegion *region;
6484
6485 TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %d)\n", graphics, x, y, width, height, mode);
6486
6487 if(!graphics)
6488 return InvalidParameter;
6489
6490 if(graphics->busy)
6491 return ObjectBusy;
6492
6494 {
6496 if (status != Ok)
6497 return status;
6498 }
6499
6500 rect.X = x;
6501 rect.Y = y;
6502 rect.Width = width;
6503 rect.Height = height;
6504 status = GdipCreateRegionRect(&rect, &region);
6505 if (status == Ok)
6506 {
6507 GpMatrix world_to_device;
6508 BOOL identity;
6509
6511 status = GdipIsMatrixIdentity(&world_to_device, &identity);
6512 if (status == Ok && !identity)
6513 status = GdipTransformRegion(region, &world_to_device);
6514 if (status == Ok)
6516
6517 GdipDeleteRegion(region);
6518 }
6519 return status;
6520}
6521
6525{
6526 TRACE("(%p, %d, %d, %d, %d, %d)\n", graphics, x, y, width, height, mode);
6527
6528 if(!graphics)
6529 return InvalidParameter;
6530
6531 if(graphics->busy)
6532 return ObjectBusy;
6533
6535}
6536
6539{
6541 GpRegion *clip;
6542
6543 TRACE("(%p, %p, %d)\n", graphics, region, mode);
6544
6545 if(!graphics || !region)
6546 return InvalidParameter;
6547
6548 if(graphics->busy)
6549 return ObjectBusy;
6550
6552 {
6554 if (status != Ok)
6555 return status;
6556 }
6557
6558 status = GdipCloneRegion(region, &clip);
6559 if (status == Ok)
6560 {
6561 GpMatrix world_to_device;
6562 BOOL identity;
6563
6565 status = GdipIsMatrixIdentity(&world_to_device, &identity);
6566 if (status == Ok && !identity)
6567 status = GdipTransformRegion(clip, &world_to_device);
6568 if (status == Ok)
6570
6571 GdipDeleteRegion(clip);
6572 }
6573 return status;
6574}
6575
6577 INT count)
6578{
6580 GpPath* path;
6581
6582 TRACE("(%p, %p, %d)\n", graphics, points, count);
6583
6584 if(!graphics || !pen || count<=0)
6585 return InvalidParameter;
6586
6587 if(graphics->busy)
6588 return ObjectBusy;
6589
6591 if (status != Ok) return status;
6592
6594 if (status == Ok)
6596
6598
6599 return status;
6600}
6601
6603 INT count)
6604{
6605 GpStatus ret;
6606 GpPointF *ptf;
6607 INT i;
6608
6609 TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
6610
6611 if(count<=0) return InvalidParameter;
6612 ptf = heap_alloc_zero(sizeof(GpPointF) * count);
6613
6614 for(i = 0;i < count; i++){
6615 ptf[i].X = (REAL)points[i].X;
6616 ptf[i].Y = (REAL)points[i].Y;
6617 }
6618
6619 ret = GdipDrawPolygon(graphics,pen,ptf,count);
6620 heap_free(ptf);
6621
6622 return ret;
6623}
6624
6626{
6627 TRACE("(%p, %p)\n", graphics, dpi);
6628
6629 if(!graphics || !dpi)
6630 return InvalidParameter;
6631
6632 if(graphics->busy)
6633 return ObjectBusy;
6634
6635 *dpi = graphics->xres;
6636 return Ok;
6637}
6638
6640{
6641 TRACE("(%p, %p)\n", graphics, dpi);
6642
6643 if(!graphics || !dpi)
6644 return InvalidParameter;
6645
6646 if(graphics->busy)
6647 return ObjectBusy;
6648
6649 *dpi = graphics->yres;
6650 return Ok;
6651}
6652
6655{
6656 GpMatrix m;
6657 GpStatus ret;
6658
6659 TRACE("(%p, %p, %d)\n", graphics, matrix, order);
6660
6661 if(!graphics || !matrix)
6662 return InvalidParameter;
6663
6664 if(graphics->busy)
6665 return ObjectBusy;
6666
6669
6670 if (ret != Ok)
6671 return ret;
6672 }
6673
6675
6677 if(ret == Ok)
6679
6680 return ret;
6681}
6682
6683/* Color used to fill bitmaps so we can tell which parts have been drawn over by gdi32. */
6684static const COLORREF DC_BACKGROUND_KEY = 0x0c0b0d;
6685
6687{
6689
6690 TRACE("(%p, %p)\n", graphics, hdc);
6691
6692 if(!graphics || !hdc)
6693 return InvalidParameter;
6694
6695 if(graphics->busy)
6696 return ObjectBusy;
6697
6699 {
6701 }
6702 else if (!graphics->hdc ||
6704 {
6705 /* Create a fake HDC and fill it with a constant color. */
6706 HDC temp_hdc;
6708 GpRectF bounds;
6709 BITMAPINFOHEADER bmih;
6710 int i;
6711
6712 stat = get_graphics_bounds(graphics, &bounds);
6713 if (stat != Ok)
6714 return stat;
6715
6718
6719 bmih.biSize = sizeof(bmih);
6722 bmih.biPlanes = 1;
6723 bmih.biBitCount = 32;
6724 bmih.biCompression = BI_RGB;
6725 bmih.biSizeImage = 0;
6726 bmih.biXPelsPerMeter = 0;
6727 bmih.biYPelsPerMeter = 0;
6728 bmih.biClrUsed = 0;
6729 bmih.biClrImportant = 0;
6730
6732 (void**)&graphics->temp_bits, NULL, 0);
6733 if (!hbitmap)
6734 return GenericError;
6735
6736 temp_hdc = CreateCompatibleDC(0);
6737 if (!temp_hdc)
6738 {
6740 return GenericError;
6741 }
6742
6745
6746 SelectObject(temp_hdc, hbitmap);
6747
6749 *hdc = graphics->temp_hdc = temp_hdc;
6750 }
6751 else
6752 {
6753 *hdc = graphics->hdc;
6754 }
6755
6756 if (stat == Ok)
6757 graphics->busy = TRUE;
6758
6759 return stat;
6760}
6761
6763{
6765
6766 TRACE("(%p, %p)\n", graphics, hdc);
6767
6768 if(!graphics || !hdc || !graphics->busy)
6769 return InvalidParameter;
6770
6772 {
6774 }
6775 else if (graphics->temp_hdc == hdc)
6776 {
6777 DWORD* pos;
6778 int i;
6779
6780 /* Find the pixels that have changed, and mark them as opaque. */
6783 {
6784 if (*pos != DC_BACKGROUND_KEY)
6785 {
6786 *pos |= 0xff000000;
6787 }
6788 pos++;
6789 }
6790
6791 /* Write the changed pixels to the real target. */
6795
6796 /* Clean up. */
6801 }
6802 else if (hdc != graphics->hdc)
6803 {
6805 }
6806
6807 if (stat == Ok)
6808 graphics->busy = FALSE;
6809
6810 return stat;
6811}
6812
6814{
6815 GpRegion *clip;
6817 GpMatrix device_to_world;
6818
6819 TRACE("(%p, %p)\n", graphics, region);
6820
6821 if(!graphics || !region)
6822 return InvalidParameter;
6823
6824 if(graphics->busy)
6825 return ObjectBusy;
6826
6827 if((status = GdipCloneRegion(graphics->clip, &clip)) != Ok)
6828 return status;
6829
6831 status = GdipTransformRegion(clip, &device_to_world);
6832 if (status != Ok)
6833 {
6834 GdipDeleteRegion(clip);
6835 return status;
6836 }
6837
6838 /* free everything except root node and header */
6839 delete_element(&region->node);
6840 memcpy(region, clip, sizeof(GpRegion));
6841 heap_free(clip);
6842
6843 return Ok;
6844}
6845
6847{
6849 {
6855 }
6857 return Ok;
6858}
6859
6861{
6863 {
6864 ERR("called without matching gdi_transform_acquire\n");
6865 return GenericError;
6866 }
6868 {
6870 }
6872 return Ok;
6873}
6874
6876 GpCoordinateSpace src_space, GpMatrix *matrix)
6877{
6878 GpStatus stat = Ok;
6879 REAL scale_x, scale_y;
6880
6881 GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
6882
6883 if (dst_space != src_space)
6884 {
6885 scale_x = units_to_pixels(1.0, graphics->unit, graphics->xres);
6886 scale_y = units_to_pixels(1.0, graphics->unit, graphics->yres);
6887
6888 if(graphics->unit != UnitDisplay)
6889 {
6890 scale_x *= graphics->scale;
6891 scale_y *= graphics->scale;
6892 }
6893
6894 if (dst_space < src_space)
6895 {
6896 /* transform towards world space */
6897 switch ((int)src_space)
6898 {
6900 {
6901 GpMatrix gdixform;
6902 gdixform = graphics->gdi_transform;
6903 stat = GdipInvertMatrix(&gdixform);
6904 if (stat != Ok)
6905 break;
6907 if (dst_space == CoordinateSpaceDevice)
6908 break;
6909 /* else fall-through */
6910 }
6912 GdipScaleMatrix(matrix, 1.0/scale_x, 1.0/scale_y, MatrixOrderAppend);
6913 if (dst_space == CoordinateSpacePage)
6914 break;
6915 /* else fall-through */
6917 {
6918 GpMatrix inverted_transform = graphics->worldtrans;
6919 stat = GdipInvertMatrix(&inverted_transform);
6920 if (stat == Ok)
6921 GdipMultiplyMatrix(matrix, &inverted_transform, MatrixOrderAppend);
6922 break;
6923 }
6924 }
6925 }
6926 else
6927 {
6928 /* transform towards device space */
6929 switch ((int)src_space)
6930 {
6933 if (dst_space == CoordinateSpacePage)
6934 break;
6935 /* else fall-through */
6937 GdipScaleMatrix(matrix, scale_x, scale_y, MatrixOrderAppend);
6938 if (dst_space == CoordinateSpaceDevice)
6939 break;
6940 /* else fall-through */
6942 {
6944 break;
6945 }
6946 }
6947 }
6948 }
6949 return stat;
6950}
6951
6954{
6956 GpStatus stat;
6957
6958 stat = get_graphics_transform(graphics, dst_space, src_space, &matrix);
6959 if (stat != Ok) return stat;
6960
6962}
6963
6966{
6967 if(!graphics || !points || count <= 0 ||
6968 dst_space < 0 || dst_space > CoordinateSpaceDevice ||
6969 src_space < 0 || src_space > CoordinateSpaceDevice)
6970 return InvalidParameter;
6971
6972 if(graphics->busy)
6973 return ObjectBusy;
6974
6975 TRACE("(%p, %d, %d, %p, %d)\n", graphics, dst_space, src_space, points, count);
6976
6977 if (src_space == dst_space) return Ok;
6978
6979 return gdip_transform_points(graphics, dst_space, src_space, points, count);
6980}
6981
6984{
6985 GpPointF *pointsF;
6986 GpStatus ret;
6987 INT i;
6988
6989 TRACE("(%p, %d, %d, %p, %d)\n", graphics, dst_space, src_space, points, count);
6990
6991 if(count <= 0)
6992 return InvalidParameter;
6993
6994 pointsF = heap_alloc_zero(sizeof(GpPointF) * count);
6995 if(!pointsF)
6996 return OutOfMemory;
6997
6998 for(i = 0; i < count; i++){
6999 pointsF[i].X = (REAL)points[i].X;
7000 pointsF[i].Y = (REAL)points[i].Y;
7001 }
7002
7003 ret = GdipTransformPoints(graphics, dst_space, src_space, pointsF, count);
7004
7005 if(ret == Ok)
7006 for(i = 0; i < count; i++){
7007 points[i].X = gdip_round(pointsF[i].X);
7008 points[i].Y = gdip_round(pointsF[i].Y);
7009 }
7010 heap_free(pointsF);
7011
7012 return ret;
7013}
7014
7016{
7017 static int calls;
7018
7019 TRACE("\n");
7020
7021 if (!calls++)
7022 FIXME("stub\n");
7023
7024 return NULL;
7025}
7026
7027/*****************************************************************************
7028 * GdipTranslateClip [GDIPLUS.@]
7029 */
7031{
7032 TRACE("(%p, %.2f, %.2f)\n", graphics, dx, dy);
7033
7034 if(!graphics)
7035 return InvalidParameter;
7036
7037 if(graphics->busy)
7038 return ObjectBusy;
7039
7041}
7042
7043/*****************************************************************************
7044 * GdipTranslateClipI [GDIPLUS.@]
7045 */
7047{
7048 TRACE("(%p, %d, %d)\n", graphics, dx, dy);
7049
7050 if(!graphics)
7051 return InvalidParameter;
7052
7053 if(graphics->busy)
7054 return ObjectBusy;
7055
7057}
7058
7059
7060/*****************************************************************************
7061 * GdipMeasureDriverString [GDIPLUS.@]
7062 */
7064 GDIPCONST GpFont *font, GDIPCONST PointF *positions,
7065 INT flags, GDIPCONST GpMatrix *matrix, RectF *boundingBox)
7066{
7067 static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
7068 HFONT hfont;
7069 HDC hdc;
7070 REAL min_x, min_y, max_x, max_y, x, y;
7071 int i;
7072 TEXTMETRICW textmetric;
7073 const WORD *glyph_indices;
7074 WORD *dynamic_glyph_indices=NULL;
7075 REAL rel_width, rel_height, ascent, descent;
7076 GpPointF pt[3];
7077
7078 TRACE("(%p %p %d %p %p %d %p %p)\n", graphics, text, length, font, positions, flags, matrix, boundingBox);
7079
7080 if (!graphics || !text || !font || !positions || !boundingBox)
7081 return InvalidParameter;
7082
7083 if (length == -1)
7084 length = strlenW(text);
7085
7086 if (length == 0)
7087 {
7088 boundingBox->X = 0.0;
7089 boundingBox->Y = 0.0;
7090 boundingBox->Width = 0.0;
7091 boundingBox->Height = 0.0;
7092 }
7093
7094 if (flags & unsupported_flags)
7095 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7096
7098
7101
7102 GetTextMetricsW(hdc, &textmetric);
7103
7104 pt[0].X = 0.0;
7105 pt[0].Y = 0.0;
7106 pt[1].X = 1.0;
7107 pt[1].Y = 0.0;
7108 pt[2].X = 0.0;
7109 pt[2].Y = 1.0;
7110 if (matrix)
7111 {
7112 GpMatrix xform = *matrix;
7113 GdipTransformMatrixPoints(&xform, pt, 3);
7114 }
7116 rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
7117 (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
7118 rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
7119 (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
7120
7122 {
7123 glyph_indices = dynamic_glyph_indices = heap_alloc_zero(sizeof(WORD) * length);
7124 if (!glyph_indices)
7125 {
7126 DeleteDC(hdc);
7128 return OutOfMemory;
7129 }
7130
7131 GetGlyphIndicesW(hdc, text, length, dynamic_glyph_indices, 0);
7132 }
7133 else
7134 glyph_indices = text;
7135
7136 min_x = max_x = x = positions[0].X;
7137 min_y = max_y = y = positions[0].Y;
7138
7139 ascent = textmetric.tmAscent / rel_height;
7140 descent = textmetric.tmDescent / rel_height;
7141
7142 for (i=0; i<length; i++)
7143 {
7144 int char_width;
7145 ABC abc;
7146
7148 {
7149 x = positions[i].X;
7150 y = positions[i].Y;
7151 }
7152
7153 GetCharABCWidthsW(hdc, glyph_indices[i], glyph_indices[i], &abc);
7154 char_width = abc.abcA + abc.abcB + abc.abcC;
7155
7156 if (min_y > y - ascent) min_y = y - ascent;
7157 if (max_y < y + descent) max_y = y + descent;
7158 if (min_x > x) min_x = x;
7159
7160 x += char_width / rel_width;
7161
7162 if (max_x < x) max_x = x;
7163 }
7164
7165 heap_free(dynamic_glyph_indices);
7166 DeleteDC(hdc);
7168
7169 boundingBox->X = min_x;
7170 boundingBox->Y = min_y;
7171 boundingBox->Width = max_x - min_x;
7172 boundingBox->Height = max_y - min_y;
7173
7174 return Ok;
7175}
7176
7179 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7181{
7182 static const INT unsupported_flags = ~(DriverStringOptionsRealizedAdvance|DriverStringOptionsCmapLookup);
7183 INT save_state;
7184 GpPointF pt;
7185 HFONT hfont;
7186 UINT eto_flags=0;
7188 HRGN hrgn;
7189
7190 if (flags & unsupported_flags)
7191 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7192
7194 eto_flags |= ETO_GLYPH_INDEX;
7195
7196 save_state = SaveDC(graphics->hdc);
7199
7201
7202 if (status == Ok)
7203 {
7206 }
7207
7208 pt = positions[0];
7210
7213
7215
7217
7219
7221
7222 RestoreDC(graphics->hdc, save_state);
7223
7225
7226 return Ok;
7227}
7228
7231 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7233{
7234 static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
7235 GpStatus stat;
7236 PointF *real_positions, real_position;
7237 POINT *pti;
7238 HFONT hfont;
7239 HDC hdc;
7240 int min_x=INT_MAX, min_y=INT_MAX, max_x=INT_MIN, max_y=INT_MIN, i, x, y;
7241 DWORD max_glyphsize=0;
7242 GLYPHMETRICS glyphmetrics;
7243 static const MAT2 identity = {{0,1}, {0,0}, {0,0}, {0,1}};
7244 BYTE *glyph_mask;
7245 BYTE *text_mask;
7246 int text_mask_stride;
7247 BYTE *pixel_data;
7248 int pixel_data_stride;
7249 GpRect pixel_area;
7250 UINT ggo_flags = GGO_GRAY8_BITMAP;
7251
7252 if (length <= 0)
7253 return Ok;
7254
7256 ggo_flags |= GGO_GLYPH_INDEX;
7257
7258 if (flags & unsupported_flags)
7259 FIXME("Ignoring flags %x\n", flags & unsupported_flags);
7260
7261 pti = heap_alloc_zero(sizeof(POINT) * length);
7262 if (!pti)
7263 return OutOfMemory;
7264
7266 {
7267 real_position = positions[0];
7268
7270 round_points(pti, &real_position, 1);
7271 }
7272 else
7273 {
7274 real_positions = heap_alloc_zero(sizeof(PointF) * length);
7275 if (!real_positions)
7276 {
7277 heap_free(pti);
7278 return OutOfMemory;
7279 }
7280
7281 memcpy(real_positions, positions, sizeof(PointF) * length);
7282
7284 round_points(pti, real_positions, length);
7285
7286 heap_free(real_positions);
7287 }
7288
7290
7293
7294 /* Get the boundaries of the text to be drawn */
7295 for (i=0; i<length; i++)
7296 {
7297 DWORD glyphsize;
7298 int left, top, right, bottom;
7299
7300 glyphsize = GetGlyphOutlineW(hdc, text[i], ggo_flags,
7301 &glyphmetrics, 0, NULL, &identity);
7302
7303 if (glyphsize == GDI_ERROR)
7304 {
7305 ERR("GetGlyphOutlineW failed\n");
7306 heap_free(pti);
7307 DeleteDC(hdc);
7309 return GenericError;
7310 }
7311
7312 if (glyphsize > max_glyphsize)
7313 max_glyphsize = glyphsize;
7314
7315 if (glyphsize != 0)
7316 {
7317 left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
7318 top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
7319 right = pti[i].x + glyphmetrics.gmptGlyphOrigin.x + glyphmetrics.gmBlackBoxX;
7320 bottom = pti[i].y - glyphmetrics.gmptGlyphOrigin.y + glyphmetrics.gmBlackBoxY;
7321
7322 if (left < min_x) min_x = left;
7323 if (top < min_y) min_y = top;
7324 if (right > max_x) max_x = right;
7325 if (bottom > max_y) max_y = bottom;
7326 }
7327
7329 {
7330 pti[i+1].x = pti[i].x + glyphmetrics.gmCellIncX;
7331 pti[i+1].y = pti[i].y + glyphmetrics.gmCellIncY;
7332 }
7333 }
7334
7335 if (max_glyphsize == 0)
7336 /* Nothing to draw. */
7337 return Ok;
7338
7339 glyph_mask = heap_alloc_zero(max_glyphsize);
7340 text_mask = heap_alloc_zero((max_x - min_x) * (max_y - min_y));
7341 text_mask_stride = max_x - min_x;
7342
7343 if (!(glyph_mask && text_mask))
7344 {
7345 heap_free(glyph_mask);
7346 heap_free(text_mask);
7347 heap_free(pti);
7348 DeleteDC(hdc);
7350 return OutOfMemory;
7351 }
7352
7353 /* Generate a mask for the text */
7354 for (i=0; i<length; i++)
7355 {
7356 DWORD ret;
7357 int left, top, stride;
7358
7359 ret = GetGlyphOutlineW(hdc, text[i], ggo_flags,
7360 &glyphmetrics, max_glyphsize, glyph_mask, &identity);
7361
7362 if (ret == GDI_ERROR || ret == 0)
7363 continue; /* empty glyph */
7364
7365 left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
7366 top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
7367 stride = (glyphmetrics.gmBlackBoxX + 3) & (~3);
7368
7369 for (y=0; y<glyphmetrics.gmBlackBoxY; y++)
7370 {
7371 BYTE *glyph_val = glyph_mask + y * stride;
7372 BYTE *text_val = text_mask + (left - min_x) + (top - min_y + y) * text_mask_stride;
7373 for (x=0; x<glyphmetrics.gmBlackBoxX; x++)
7374 {
7375 *text_val = min(64, *text_val + *glyph_val);
7376 glyph_val++;
7377 text_val++;
7378 }
7379 }
7380 }
7381
7382 heap_free(pti);
7383 DeleteDC(hdc);
7385 heap_free(glyph_mask);
7386
7387 /* get the brush data */
7388 pixel_data = heap_alloc_zero(4 * (max_x - min_x) * (max_y - min_y));
7389 if (!pixel_data)
7390 {
7391 heap_free(text_mask);
7392 return OutOfMemory;
7393 }
7394
7395 pixel_area.X = min_x;
7396 pixel_area.Y = min_y;
7397 pixel_area.Width = max_x - min_x;
7398 pixel_area.Height = max_y - min_y;
7399 pixel_data_stride = pixel_area.Width * 4;
7400
7401 stat = brush_fill_pixels(graphics, (GpBrush*)brush, (DWORD*)pixel_data, &pixel_area, pixel_area.Width);
7402 if (stat != Ok)
7403 {
7404 heap_free(text_mask);
7405 heap_free(pixel_data);
7406 return stat;
7407 }
7408
7409 /* multiply the brush data by the mask */
7410 for (y=0; y<pixel_area.Height; y++)
7411 {
7412 BYTE *text_val = text_mask + text_mask_stride * y;
7413 BYTE *pixel_val = pixel_data + pixel_data_stride * y + 3;
7414 for (x=0; x<pixel_area.Width; x++)
7415 {
7416 *pixel_val = (*pixel_val) * (*text_val) / 64;
7417 text_val++;
7418 pixel_val+=4;
7419 }
7420 }
7421
7422 heap_free(text_mask);
7423
7425
7426 /* draw the result */
7427 stat = alpha_blend_pixels(graphics, min_x, min_y, pixel_data, pixel_area.Width,
7428 pixel_area.Height, pixel_data_stride, PixelFormat32bppARGB);
7429
7431
7432 heap_free(pixel_data);
7433
7434 return stat;
7435}
7436
7439 GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
7441{
7443
7444 if (length == -1)
7445 length = strlenW(text);
7446
7447 if (graphics->hdc && !graphics->alpha_hdc &&
7450 (((GpSolidFill*)brush)->color & 0xff000000) == 0xff000000)
7452 brush, positions, flags, matrix);
7453 if (stat == NotImplemented)
7455 brush, positions, flags, matrix);
7456 return stat;
7457}
7458
7459/*****************************************************************************
7460 * GdipDrawDriverString [GDIPLUS.@]
7461 */
7464 GDIPCONST PointF *positions, INT flags,
7466{
7467 TRACE("(%p %s %p %p %p %d %p)\n", graphics, debugstr_wn(text, length), font, brush, positions, flags, matrix);
7468
7469 if (!graphics || !text || !font || !brush || !positions)
7470 return InvalidParameter;
7471
7473 brush, positions, flags, matrix);
7474}
7475
7476/*****************************************************************************
7477 * GdipIsVisibleClipEmpty [GDIPLUS.@]
7478 */
7480{
7481 GpStatus stat;
7482 GpRegion* rgn;
7483
7484 TRACE("(%p, %p)\n", graphics, res);
7485
7486 if((stat = GdipCreateRegion(&rgn)) != Ok)
7487 return stat;
7488
7489 if((stat = get_visible_clip_region(graphics, rgn)) != Ok)
7490 goto cleanup;
7491
7493
7494cleanup:
7495 GdipDeleteRegion(rgn);
7496 return stat;
7497}
7498
7500{
7501 static int calls;
7502
7503 TRACE("(%p) stub\n", graphics);
7504
7505 if(!(calls++))
7506 FIXME("not implemented\n");
7507
7508 return NotImplemented;
7509}
7510
7512{
7513 TRACE("(%p, %p)\n", graphics, pabort);
7514
7515 if (!graphics)
7516 return InvalidParameter;
7517
7518 if (pabort)
7519 FIXME("Abort callback is not supported.\n");
7520
7521 return Ok;
7522}
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: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
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:6625
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:3498
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:7437
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:3473
GpStatus WINGDIPAPI GdipFillClosedCurve(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:4278
GpStatus WINGDIPAPI GdipSetClipGraphics(GpGraphics *graphics, GpGraphics *srcgraphics, CombineMode mode)
Definition: graphics.c:6078
#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:7015
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:5205
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:4571
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:5994
GpStatus WINGDIPAPI GdipFillPolygon2I(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:4533
static GpStatus SOFTWARE_GdipFillRegion(GpGraphics *graphics, GpBrush *brush, GpRegion *region)
Definition: graphics.c:4679
GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, GraphicsContainer *state)
Definition: graphics.c:5928
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:4556
GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix)
Definition: graphics.c:6875
GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics *graphics, TextRenderingHint *hint)
Definition: graphics.c:4992
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:4331
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:3565
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:4762
GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPoint *points, INT count, GpFillMode fillMode)
Definition: graphics.c:4496
GpStatus WINGDIPAPI GdipGraphicsSetAbort(GpGraphics *graphics, GdiplusAbort *pabort)
Definition: graphics.c:7511
static volatile LONG g_priv_contid
Definition: graphics.c:58
GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:6639
GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics *graphics, GDIPCONST GpRect *dstrect, GDIPCONST GpRect *srcrect, GpUnit unit, GraphicsContainer *state)
Definition: graphics.c:5972
GpStatus WINGDIPAPI GdipGetNearestColor(GpGraphics *graphics, ARGB *argb)
Definition: graphics.c:4903
GpStatus WINGDIPAPI GdipDrawLine(GpGraphics *graphics, GpPen *pen, REAL x1, REAL y1, REAL x2, REAL y2)
Definition: graphics.c:3573
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:6416
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
static GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:3678
GpStatus WINGDIPAPI GdipFlush(GpGraphics *graphics, GpFlushIntention intention)
Definition: graphics.c:4790
GpStatus WINGDIPAPI GdipFillRectanglesI(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpRect *rects, INT count)
Definition: graphics.c:4600
GpStatus WINGDIPAPI GdipTranslateClip(GpGraphics *graphics, REAL dx, REAL dy)
Definition: graphics.c:7030
GpStatus WINGDIPAPI GdipResetPageTransform(GpGraphics *graphics)
Definition: graphics.c:7499
GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx, REAL sy, GpMatrixOrder order)
Definition: graphics.c:6055
static void delete_container(GraphicsContainerItem *container)
Definition: graphics.c:2156
static const COLORREF DC_BACKGROUND_KEY
Definition: graphics.c:6684
static GpStatus begin_container(GpGraphics *graphics, GraphicsContainerType type, GraphicsContainer *state)
Definition: graphics.c:5889
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:4246
GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, GpMatrixOrder order)
Definition: graphics.c:5866
GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:4294
static HBRUSH create_gdi_brush(const GpBrush *brush)
Definition: graphics.c:231
GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region)
Definition: graphics.c:6813
GpStatus WINGDIPAPI GdipTranslateWorldTransform(GpGraphics *graphics, REAL dx, REAL dy, GpMatrixOrder order)
Definition: graphics.c:6390
static GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:3649
GpStatus WINGDIPAPI GdipSetCompositingMode(GpGraphics *graphics, CompositingMode mode)
Definition: graphics.c:6089
GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count)
Definition: graphics.c:6952
GpStatus WINGDIPAPI GdipTranslateClipI(GpGraphics *graphics, INT dx, INT dy)
Definition: graphics.c:7046
GpStatus WINGDIPAPI GdipFillClosedCurve2(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count, REAL tension, GpFillMode fill)
Definition: graphics.c:4217
GpStatus WINGDIPAPI GdipDrawPolygonI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:6602
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:4095
GpStatus WINGDIPAPI GdipDrawPolygon(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:6576
GpStatus WINGDIPAPI GdipResetClip(GpGraphics *graphics)
Definition: graphics.c:5831
GpStatus WINGDIPAPI GdipGetSmoothingMode(GpGraphics *graphics, SmoothingMode *mode)
Definition: graphics.c:4964
static ARGB blend_line_gradient(GpLineGradient *brush, REAL position)
Definition: graphics.c:591
GpStatus WINGDIPAPI GdipGetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode *mode)
Definition: graphics.c:4947
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:3601
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:4979
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:5653
GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc)
Definition: graphics.c:6686
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:7229
GpStatus WINGDIPAPI GdipGetPageScale(GpGraphics *graphics, REAL *scale)
Definition: graphics.c:4916
GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color)
Definition: graphics.c:5080
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:6522
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:4163
GpStatus WINGDIPAPI GdipFillPie(GpGraphics *graphics, GpBrush *brush, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4428
static GpStatus SOFTWARE_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *path)
Definition: graphics.c:4373
GpStatus WINGDIPAPI GdipSetTextRenderingHint(GpGraphics *graphics, TextRenderingHint hint)
Definition: graphics.c:6334
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:7462
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:5550
GpStatus WINGDIPAPI GdipGetClipBounds(GpGraphics *graphics, GpRectF *rect)
Definition: graphics.c:4811
GpStatus WINGDIPAPI GdipGetCompositingMode(GpGraphics *graphics, CompositingMode *mode)
Definition: graphics.c:4852
GpStatus WINGDIPAPI GdipSetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
Definition: graphics.c:6362
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:4869
GpStatus WINGDIPAPI GdipDrawRectanglesI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpRect *rects, INT count)
Definition: graphics.c:4188
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:3521
GpStatus WINGDIPAPI GdipFillPolygon2(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpPointF *points, INT count)
Definition: graphics.c:4525
GpStatus WINGDIPAPI GdipGetVisibleClipBoundsI(GpGraphics *graphics, GpRect *rect)
Definition: graphics.c:5045
GpStatus WINGDIPAPI GdipTransformPointsI(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPoint *points, INT count)
Definition: graphics.c:6982
GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region, CombineMode mode)
Definition: graphics.c:6537
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:5123
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:4286
GpStatus gdi_transform_acquire(GpGraphics *graphics)
Definition: graphics.c:6846
GpStatus WINGDIPAPI GdipMultiplyWorldTransform(GpGraphics *graphics, GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
Definition: graphics.c:6653
GpStatus WINGDIPAPI GdipGetRenderingOrigin(GpGraphics *graphics, INT *x, INT *y)
Definition: graphics.c:6280
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:6477
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:5008
#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:3593
GpStatus WINGDIPAPI GdipDrawLinesI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, INT count)
Definition: graphics.c:3626
GpStatus WINGDIPAPI GdipIsVisiblePointI(GpGraphics *graphics, INT x, INT y, BOOL *result)
Definition: graphics.c:5156
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:7063
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:5915
static GpStatus GDI32_GdipFillRegion(GpGraphics *graphics, GpBrush *brush, GpRegion *region)
Definition: graphics.c:4629
GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
Definition: graphics.c:4070
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:7177
#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:6043
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:5113
GpStatus gdi_transform_release(GpGraphics *graphics)
Definition: graphics.c:6860
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:6118
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:6147
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:5161
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:7479
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:3983
GpStatus WINGDIPAPI GdipGetInterpolationMode(GpGraphics *graphics, InterpolationMode *mode)
Definition: graphics.c:4886
#define fmax
Definition: graphics.c:64
GpStatus WINGDIPAPI GdipDrawRectangle(GpGraphics *graphics, GpPen *pen, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:4130
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:4395
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:4541
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:4467
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:5427
GpStatus WINGDIPAPI GdipDrawPieI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4121
GpStatus WINGDIPAPI GdipIsVisibleRectI(GpGraphics *graphics, INT x, INT y, INT width, INT height, BOOL *result)
Definition: graphics.c:5200
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:6762
struct _GraphicsContainerItem GraphicsContainerItem
GpStatus WINGDIPAPI GdipSetRenderingOrigin(GpGraphics *graphics, INT x, INT y)
Definition: graphics.c:6262
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:4838
GpStatus WINGDIPAPI GdipTransformPoints(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count)
Definition: graphics.c:6964
GpStatus WINGDIPAPI GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
Definition: graphics.c:4458
GpStatus WINGDIPAPI GdipSetClipPath(GpGraphics *graphics, GpPath *path, CombineMode mode)
Definition: graphics.c:6448
GpStatus WINGDIPAPI GdipDrawImageRect(GpGraphics *graphics, GpImage *image, REAL x, REAL y, REAL width, REAL height)
Definition: graphics.c:3544
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:5700
GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state)
Definition: graphics.c:6049
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:6206
GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, INT y, INT width, INT height)
Definition: graphics.c:4155
GpStatus WINGDIPAPI GdipGetPageUnit(GpGraphics *graphics, GpUnit *unit)
Definition: graphics.c:4931
GpStatus WINGDIPAPI GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode mode)
Definition: graphics.c:6293
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:5519
GpStatus WINGDIPAPI GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, INT width, INT height)
Definition: graphics.c:4323
GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
Definition: graphics.c:5066
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:6233
GpStatus WINGDIPAPI GdipSetTextContrast(GpGraphics *graphics, UINT contrast)
Definition: graphics.c:6322
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y)
Definition: graphics.c:2969
GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics)
Definition: graphics.c:5844
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:6182
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:5388
static GpStatus end_container(GpGraphics *graphics, GraphicsContainerType type, GraphicsContainer state)
Definition: graphics.c:6000
GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state)
Definition: graphics.c:5921
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:1794
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:56
_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
GLuint GLuint GLsizei count
Definition: gl.h:1545
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
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
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
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
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
GLuint64EXT * result
Definition: glext.h:11304
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLenum cap
Definition: glext.h:9639
GLsizei const GLfloat * points
Definition: glext.h:8112
GLenum fillMode
Definition: glext.h:11728
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
_Check_return_ float __cdecl powf(_In_ float b, _In_ float e)
Definition: math.h:246
_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:242
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
#define bits
Definition: infblock.c:15
#define INT_MIN
Definition: intsafe.h:123
#define INT_MAX
Definition: intsafe.h:150
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 HDC
Definition: imagelist.c:88
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
static int font_height(HFONT hFont)
Definition: combo.c:46
#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:34
#define isprintW
Definition: unicode.h:68
#define strcpyW(d, s)
Definition: unicode.h:35
#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:154
#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:5649
GpGraphics * graphics
Definition: graphics.c:5648
Definition: dsound.c:943
Definition: format.c:58
Definition: copy.c:22
Definition: parser.c:49
GpRegion ** regions
Definition: graphics.c:5384
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
double DOUBLE
Definition: typedefs.h:70
_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
int retval
Definition: wcstombs.cpp:91
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:1233
#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:1546
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:1174
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