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