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