ReactOS 0.4.15-dev-5664-g3bf4ef6
region.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Google (Lei Zhang)
3 * Copyright (C) 2013 Dmitry Timoshkov
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include <stdarg.h>
21
22#include "windef.h"
23#include "winbase.h"
24#include "wingdi.h"
25
26#include "objbase.h"
27
28#include "gdiplus.h"
29#include "gdiplus_private.h"
30#include "wine/debug.h"
31
33
34/**********************************************************
35 *
36 * Data returned by GdipGetRegionData looks something like this:
37 *
38 * struct region_data_header
39 * {
40 * DWORD size; size in bytes of the data - 8.
41 * DWORD magic1; probably a checksum.
42 * DWORD magic2; always seems to be 0xdbc01001 - version?
43 * DWORD num_ops; number of combining ops * 2
44 * };
45 *
46 * Then follows a sequence of combining ops and region elements.
47 *
48 * A region element is either a RECTF or some path data.
49 *
50 * Combining ops are just stored as their CombineMode value.
51 *
52 * Each RECTF is preceded by the DWORD 0x10000000. An empty rect is
53 * stored as 0x10000002 (with no following RECTF) and an infinite rect
54 * is stored as 0x10000003 (again with no following RECTF).
55 *
56 * Path data is preceded by the DWORD 0x10000001. Then follows a
57 * DWORD size and then size bytes of data.
58 *
59 * The combining ops are stored in the reverse order to the region
60 * elements and in the reverse order to which the region was
61 * constructed.
62 *
63 * When two or more complex regions (ie those with more than one
64 * element) are combined, the combining op for the two regions comes
65 * first, then the combining ops for the region elements in region 1,
66 * followed by the region elements for region 1, then follows the
67 * combining ops for region 2 and finally region 2's region elements.
68 * Presumably you're supposed to use the 0x1000000x header to find the
69 * end of the op list (the count of the elements in each region is not
70 * stored).
71 *
72 * When a simple region (1 element) is combined, it's treated as if a
73 * single rect/path is being combined.
74 *
75 */
76
77#define FLAGS_INTPATH 0x4000
78
80{
83};
84
86{
90};
91
92struct path_header
93{
98};
99
100typedef struct packed_point
101{
102 short X;
103 short Y;
105
107{
108 INT needed = sizeof(DWORD); /* DWORD for the type */
109 switch(element->type)
110 {
111 case RegionDataRect:
112 return needed + sizeof(GpRect);
113 case RegionDataPath:
114 {
115 needed += write_path_data(element->elementdata.path, NULL);
116 needed += sizeof(DWORD); /* Extra DWORD for path size */
117 return needed;
118 }
121 return needed;
122 default:
123 needed += get_element_size(element->elementdata.combine.left);
124 needed += get_element_size(element->elementdata.combine.right);
125 return needed;
126 }
127
128 return 0;
129}
130
131/* Does not check parameters, caller must do that */
132static inline GpStatus init_region(GpRegion* region, const RegionType type)
133{
134 region->node.type = type;
135 region->num_children = 0;
136
137 return Ok;
138}
139
141 region_element** element2)
142{
144
145 /* root node is allocated with GpRegion */
146 if(!*element2){
147 *element2 = heap_alloc_zero(sizeof(region_element));
148 if (!*element2)
149 return OutOfMemory;
150 }
151
152 (*element2)->type = element->type;
153
154 switch (element->type)
155 {
156 case RegionDataRect:
157 (*element2)->elementdata.rect = element->elementdata.rect;
158 return Ok;
161 return Ok;
162 case RegionDataPath:
163 stat = GdipClonePath(element->elementdata.path, &(*element2)->elementdata.path);
164 if (stat == Ok) return Ok;
165 break;
166 default:
167 (*element2)->elementdata.combine.left = NULL;
168 (*element2)->elementdata.combine.right = NULL;
169
170 stat = clone_element(element->elementdata.combine.left,
171 &(*element2)->elementdata.combine.left);
172 if (stat == Ok)
173 {
174 stat = clone_element(element->elementdata.combine.right,
175 &(*element2)->elementdata.combine.right);
176 if (stat == Ok) return Ok;
177 }
178 break;
179 }
180
181 delete_element(*element2);
182 *element2 = NULL;
183 return stat;
184}
185
186/* Common code for CombineRegion*
187 * All the caller has to do is get its format into an element
188 */
189static inline void fuse_region(GpRegion* region, region_element* left,
191{
192 region->node.type = mode;
193 region->node.elementdata.combine.left = left;
194 region->node.elementdata.combine.right = right;
195 region->num_children += 2;
196}
197
198/*****************************************************************************
199 * GdipCloneRegion [GDIPLUS.@]
200 *
201 * Creates a deep copy of the region
202 *
203 * PARAMS
204 * region [I] source region
205 * clone [O] resulting clone
206 *
207 * RETURNS
208 * SUCCESS: Ok
209 * FAILURE: InvalidParameter or OutOfMemory
210 */
212{
214
215 TRACE("%p %p\n", region, clone);
216
217 if (!(region && clone))
218 return InvalidParameter;
219
220 *clone = heap_alloc_zero(sizeof(GpRegion));
221 if (!*clone)
222 return OutOfMemory;
223 element = &(*clone)->node;
224
225 (*clone)->num_children = region->num_children;
226 return clone_element(&region->node, &element);
227}
228
229/*****************************************************************************
230 * GdipCombineRegionPath [GDIPLUS.@]
231 */
233{
234 GpRegion *path_region;
237
238 TRACE("%p %p %d\n", region, path, mode);
239
240 if (!(region && path))
241 return InvalidParameter;
242
243 stat = GdipCreateRegionPath(path, &path_region);
244 if (stat != Ok)
245 return stat;
246
247 /* simply replace region data */
249 delete_element(&region->node);
250 memcpy(region, path_region, sizeof(GpRegion));
251 heap_free(path_region);
252 return Ok;
253 }
254
255 left = heap_alloc_zero(sizeof(region_element));
256 if (left)
257 {
258 *left = region->node;
259 stat = clone_element(&path_region->node, &right);
260 if (stat == Ok)
261 {
262 fuse_region(region, left, right, mode);
263 GdipDeleteRegion(path_region);
264 return Ok;
265 }
266 }
267 else
269
271 GdipDeleteRegion(path_region);
272 return stat;
273}
274
275/*****************************************************************************
276 * GdipCombineRegionRect [GDIPLUS.@]
277 */
280{
281 GpRegion *rect_region;
284
285 TRACE("%p %s %d\n", region, debugstr_rectf(rect), mode);
286
287 if (!(region && rect))
288 return InvalidParameter;
289
290 stat = GdipCreateRegionRect(rect, &rect_region);
291 if (stat != Ok)
292 return stat;
293
294 /* simply replace region data */
296 delete_element(&region->node);
297 memcpy(region, rect_region, sizeof(GpRegion));
298 heap_free(rect_region);
299 return Ok;
300 }
301
302 left = heap_alloc_zero(sizeof(region_element));
303 if (left)
304 {
305 memcpy(left, &region->node, sizeof(region_element));
306 stat = clone_element(&rect_region->node, &right);
307 if (stat == Ok)
308 {
309 fuse_region(region, left, right, mode);
310 GdipDeleteRegion(rect_region);
311 return Ok;
312 }
313 }
314 else
316
318 GdipDeleteRegion(rect_region);
319 return stat;
320}
321
322/*****************************************************************************
323 * GdipCombineRegionRectI [GDIPLUS.@]
324 */
327{
328 GpRectF rectf;
329
330 TRACE("%p %p %d\n", region, rect, mode);
331
332 if (!rect)
333 return InvalidParameter;
334
335 rectf.X = (REAL)rect->X;
336 rectf.Y = (REAL)rect->Y;
337 rectf.Height = (REAL)rect->Height;
338 rectf.Width = (REAL)rect->Width;
339
340 return GdipCombineRegionRect(region, &rectf, mode);
341}
342
343/*****************************************************************************
344 * GdipCombineRegionRegion [GDIPLUS.@]
345 */
347 GpRegion *region2, CombineMode mode)
348{
351 GpRegion *reg2copy;
352
353 TRACE("%p %p %d\n", region1, region2, mode);
354
355 if(!(region1 && region2))
356 return InvalidParameter;
357
358 /* simply replace region data */
360 stat = GdipCloneRegion(region2, &reg2copy);
361 if(stat != Ok) return stat;
362
363 delete_element(&region1->node);
364 memcpy(region1, reg2copy, sizeof(GpRegion));
365 heap_free(reg2copy);
366 return Ok;
367 }
368
369 left = heap_alloc_zero(sizeof(region_element));
370 if (!left)
371 return OutOfMemory;
372
373 *left = region1->node;
374 stat = clone_element(&region2->node, &right);
375 if (stat != Ok)
376 {
378 return OutOfMemory;
379 }
380
381 fuse_region(region1, left, right, mode);
382 region1->num_children += region2->num_children;
383
384 return Ok;
385}
386
387/*****************************************************************************
388 * GdipCreateRegion [GDIPLUS.@]
389 */
391{
392 TRACE("%p\n", region);
393
394 if(!region)
395 return InvalidParameter;
396
397 *region = heap_alloc_zero(sizeof(GpRegion));
398 if(!*region)
399 return OutOfMemory;
400
401 TRACE("=> %p\n", *region);
402
403 return init_region(*region, RegionDataInfiniteRect);
404}
405
406/*****************************************************************************
407 * GdipCreateRegionPath [GDIPLUS.@]
408 *
409 * Creates a GpRegion from a GpPath
410 *
411 * PARAMS
412 * path [I] path to base the region on
413 * region [O] pointer to the newly allocated region
414 *
415 * RETURNS
416 * SUCCESS: Ok
417 * FAILURE: InvalidParameter
418 *
419 * NOTES
420 * If a path has no floating point points, its points will be stored as shorts
421 * (INTPATH)
422 *
423 * If a path is empty, it is considered to be an INTPATH
424 */
426{
429
430 TRACE("%p, %p\n", path, region);
431
432 if (!(path && region))
433 return InvalidParameter;
434
435 *region = heap_alloc_zero(sizeof(GpRegion));
436 if(!*region)
437 return OutOfMemory;
438 stat = init_region(*region, RegionDataPath);
439 if (stat != Ok)
440 {
441 GdipDeleteRegion(*region);
442 return stat;
443 }
444 element = &(*region)->node;
445
446 stat = GdipClonePath(path, &element->elementdata.path);
447 if (stat != Ok)
448 {
449 GdipDeleteRegion(*region);
450 return stat;
451 }
452
453 return Ok;
454}
455
456/*****************************************************************************
457 * GdipCreateRegionRect [GDIPLUS.@]
458 */
460 GpRegion **region)
461{
463
464 TRACE("%p, %p\n", rect, region);
465
466 if (!(rect && region))
467 return InvalidParameter;
468
469 *region = heap_alloc_zero(sizeof(GpRegion));
470 stat = init_region(*region, RegionDataRect);
471 if(stat != Ok)
472 {
473 GdipDeleteRegion(*region);
474 return stat;
475 }
476
477 (*region)->node.elementdata.rect.X = rect->X;
478 (*region)->node.elementdata.rect.Y = rect->Y;
479 (*region)->node.elementdata.rect.Width = rect->Width;
480 (*region)->node.elementdata.rect.Height = rect->Height;
481
482 return Ok;
483}
484
485/*****************************************************************************
486 * GdipCreateRegionRectI [GDIPLUS.@]
487 */
489 GpRegion **region)
490{
491 GpRectF rectf;
492
493 TRACE("%p, %p\n", rect, region);
494
495 rectf.X = (REAL)rect->X;
496 rectf.Y = (REAL)rect->Y;
497 rectf.Width = (REAL)rect->Width;
498 rectf.Height = (REAL)rect->Height;
499
500 return GdipCreateRegionRect(&rectf, region);
501}
502
503/******************************************************************************
504 * GdipCreateRegionHrgn [GDIPLUS.@]
505 */
507{
508 DWORD size;
510 LPRECT rect;
512 GpPath* path;
514 DWORD i;
515
516 TRACE("(%p, %p)\n", hrgn, region);
517
518 if(!region || !(size = GetRegionData(hrgn, 0, NULL)))
519 return InvalidParameter;
520
521 buf = heap_alloc_zero(size);
522 if(!buf)
523 return OutOfMemory;
524
525 if(!GetRegionData(hrgn, size, buf)){
526 heap_free(buf);
527 return GenericError;
528 }
529
530 if(buf->rdh.nCount == 0){
531 if((stat = GdipCreateRegion(&local)) != Ok){
532 heap_free(buf);
533 return stat;
534 }
535 if((stat = GdipSetEmpty(local)) != Ok){
536 heap_free(buf);
538 return stat;
539 }
540 *region = local;
541 heap_free(buf);
542 return Ok;
543 }
544
546 heap_free(buf);
547 return stat;
548 }
549
550 rect = (LPRECT)buf->Buffer;
551 for(i = 0; i < buf->rdh.nCount; i++){
552 if((stat = GdipAddPathRectangle(path, (REAL)rect->left, (REAL)rect->top,
553 (REAL)(rect->right - rect->left), (REAL)(rect->bottom - rect->top))) != Ok){
554 heap_free(buf);
556 return stat;
557 }
558 rect++;
559 }
560
561 stat = GdipCreateRegionPath(path, region);
562
563 heap_free(buf);
565 return stat;
566}
567
568/*****************************************************************************
569 * GdipDeleteRegion [GDIPLUS.@]
570 */
572{
573 TRACE("%p\n", region);
574
575 if (!region)
576 return InvalidParameter;
577
578 delete_element(&region->node);
579 heap_free(region);
580
581 return Ok;
582}
583
584/*****************************************************************************
585 * GdipGetRegionBounds [GDIPLUS.@]
586 */
588{
589 HRGN hrgn;
590 RECT r;
592
593 TRACE("(%p, %p, %p)\n", region, graphics, rect);
594
595 if(!region || !graphics || !rect)
596 return InvalidParameter;
597
598 /* Contrary to MSDN, native ignores the graphics transform. */
599 status = GdipGetRegionHRgn(region, NULL, &hrgn);
600 if(status != Ok)
601 return status;
602
603 /* infinite */
604 if(!hrgn){
605 rect->X = rect->Y = -(REAL)(1 << 22);
606 rect->Width = rect->Height = (REAL)(1 << 23);
607 TRACE("%p => infinite\n", region);
608 return Ok;
609 }
610
611 if(GetRgnBox(hrgn, &r)){
612 rect->X = r.left;
613 rect->Y = r.top;
614 rect->Width = r.right - r.left;
615 rect->Height = r.bottom - r.top;
616 TRACE("%p => %s\n", region, debugstr_rectf(rect));
617 }
618 else
620
622
623 return status;
624}
625
626/*****************************************************************************
627 * GdipGetRegionBoundsI [GDIPLUS.@]
628 */
630{
631 GpRectF rectf;
633
634 TRACE("(%p, %p, %p)\n", region, graphics, rect);
635
636 if(!rect)
637 return InvalidParameter;
638
639 status = GdipGetRegionBounds(region, graphics, &rectf);
640 if(status == Ok){
641 rect->X = gdip_round(rectf.X);
642 rect->Y = gdip_round(rectf.Y);
643 rect->Width = gdip_round(rectf.Width);
644 rect->Height = gdip_round(rectf.Height);
645 }
646
647 return status;
648}
649
650static inline void write_dword(DWORD* location, INT* offset, const DWORD write)
651{
653 (*offset)++;
654}
655
656static inline void write_float(DWORD* location, INT* offset, const FLOAT write)
657{
658 ((FLOAT*)location)[*offset] = write;
659 (*offset)++;
660}
661
663 INT* filled)
664{
665 write_dword(buffer, filled, element->type);
666 switch (element->type)
667 {
670 case CombineModeUnion:
671 case CombineModeXor:
674 write_element(element->elementdata.combine.left, buffer, filled);
675 write_element(element->elementdata.combine.right, buffer, filled);
676 break;
677 case RegionDataRect:
678 write_float(buffer, filled, element->elementdata.rect.X);
679 write_float(buffer, filled, element->elementdata.rect.Y);
680 write_float(buffer, filled, element->elementdata.rect.Width);
681 write_float(buffer, filled, element->elementdata.rect.Height);
682 break;
683 case RegionDataPath:
684 {
685 DWORD size = write_path_data(element->elementdata.path, buffer + *filled + 1);
686 write_dword(buffer, filled, size);
687 *filled += size / sizeof(DWORD);
688 break;
689 }
692 break;
693 }
694}
695
697{
698 struct region_header *header = data;
699 INT filled = 0;
700 DWORD size;
701
702 size = sizeof(struct region_header) + get_element_size(&region->node);
703 if (!data) return size;
704
705 header->magic = VERSION_MAGIC2;
706 header->num_children = region->num_children;
707 filled += 2;
708 /* With few exceptions, everything written is DWORD aligned,
709 * so use that as our base */
710 write_element(&region->node, (DWORD*)data, &filled);
711 return size;
712}
713
714/*****************************************************************************
715 * GdipGetRegionData [GDIPLUS.@]
716 *
717 * Returns the header, followed by combining ops and region elements.
718 *
719 * PARAMS
720 * region [I] region to retrieve from
721 * buffer [O] buffer to hold the resulting data
722 * size [I] size of the buffer
723 * needed [O] (optional) how much data was written
724 *
725 * RETURNS
726 * SUCCESS: Ok
727 * FAILURE: InvalidParameter
728 *
729 * NOTES
730 * The header contains the size, a checksum, a version string, and the number
731 * of children. The size does not count itself or the checksum.
732 * Version is always something like 0xdbc01001 or 0xdbc01002
733 *
734 * An element is a RECT, or PATH; Combining ops are stored as their
735 * CombineMode value. Special regions (infinite, empty) emit just their
736 * op-code; GpRectFs emit their code followed by their points; GpPaths emit
737 * their code followed by a second header for the path followed by the actual
738 * path data. Followed by the flags for each point. The pathheader contains
739 * the size of the data to follow, a version number again, followed by a count
740 * of how many points, and any special flags which may apply. 0x4000 means it's
741 * a path of shorts instead of FLOAT.
742 *
743 * Combining Ops are stored in reverse order from when they were constructed;
744 * the output is a tree where the left side combining area is always taken
745 * first.
746 */
748 UINT *needed)
749{
751 UINT required;
752
753 TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
754
755 if (!region || !buffer || !size)
756 return InvalidParameter;
757
758 required = FIELD_OFFSET(struct region_data_header, header) + write_region_data(region, NULL);
759 if (size < required)
760 {
761 if (needed) *needed = size;
762 return InsufficientBuffer;
763 }
764
768
769 if (needed)
770 *needed = required;
771
772 return Ok;
773}
774
776{
778 const DWORD *type;
779
780 type = buffer_read(mbuf, sizeof(*type));
781 if (!type) return Ok;
782
783 TRACE("type %#x\n", *type);
784
785 node->type = *type;
786
787 switch (node->type)
788 {
791 case CombineModeUnion:
792 case CombineModeXor:
795 {
797
798 left = heap_alloc_zero(sizeof(region_element));
799 if (!left) return OutOfMemory;
800 right = heap_alloc_zero(sizeof(region_element));
801 if (!right)
802 {
804 return OutOfMemory;
805 }
806
807 status = read_element(mbuf, region, left, count);
808 if (status == Ok)
809 {
810 status = read_element(mbuf, region, right, count);
811 if (status == Ok)
812 {
813 node->elementdata.combine.left = left;
814 node->elementdata.combine.right = right;
815 region->num_children += 2;
816 return Ok;
817 }
818 }
819
822 return status;
823 }
824
825 case RegionDataRect:
826 {
827 const GpRectF *rc;
828
829 rc = buffer_read(mbuf, sizeof(*rc));
830 if (!rc)
831 {
832 ERR("failed to read rect data\n");
833 return InvalidParameter;
834 }
835
836 node->elementdata.rect = *rc;
837 *count += 1;
838 return Ok;
839 }
840
841 case RegionDataPath:
842 {
843 GpPath *path;
844 const struct path_header *path_header;
845 const BYTE *types;
846
847 path_header = buffer_read(mbuf, sizeof(*path_header));
848 if (!path_header)
849 {
850 ERR("failed to read path header\n");
851 return InvalidParameter;
852 }
854 {
855 ERR("invalid path header magic %#x\n", path_header->magic);
856 return InvalidParameter;
857 }
858
859 /* Windows always fails to create an empty path in a region */
860 if (!path_header->count)
861 {
862 TRACE("refusing to create an empty path in a region\n");
863 return GenericError;
864 }
865
867 if (status) return status;
868
869 node->elementdata.path = path;
870
872 return OutOfMemory;
873
874 path->pathdata.Count = path_header->count;
875
877 FIXME("unhandled path flags %#x\n", path_header->flags);
878
880 {
881 const packed_point *pt;
882 DWORD i;
883
884 pt = buffer_read(mbuf, sizeof(*pt) * path_header->count);
885 if (!pt)
886 {
887 ERR("failed to read packed %u path points\n", path_header->count);
888 return InvalidParameter;
889 }
890
891 for (i = 0; i < path_header->count; i++)
892 {
893 path->pathdata.Points[i].X = (REAL)pt[i].X;
894 path->pathdata.Points[i].Y = (REAL)pt[i].Y;
895 }
896 }
897 else
898 {
899 const GpPointF *ptf;
900
901 ptf = buffer_read(mbuf, sizeof(*ptf) * path_header->count);
902 if (!ptf)
903 {
904 ERR("failed to read %u path points\n", path_header->count);
905 return InvalidParameter;
906 }
907 memcpy(path->pathdata.Points, ptf, sizeof(*ptf) * path_header->count);
908 }
909
911 if (!types)
912 {
913 ERR("failed to read %u path types\n", path_header->count);
914 return InvalidParameter;
915 }
916 memcpy(path->pathdata.Types, types, path_header->count);
917 if (path_header->count & 3)
918 {
919 if (!buffer_read(mbuf, 4 - (path_header->count & 3)))
920 {
921 ERR("failed to read rounding %u bytes\n", 4 - (path_header->count & 3));
922 return InvalidParameter;
923 }
924 }
925
926 *count += 1;
927 return Ok;
928 }
929
932 *count += 1;
933 return Ok;
934
935 default:
936 FIXME("element type %#x is not supported\n", *type);
937 break;
938 }
939
940 return InvalidParameter;
941}
942
943/*****************************************************************************
944 * GdipCreateRegionRgnData [GDIPLUS.@]
945 */
947{
949 struct memory_buffer mbuf;
951 INT count;
952
953 TRACE("(%p, %d, %p)\n", data, size, region);
954
955 if (!data || !size)
956 return InvalidParameter;
957
959
962 return InvalidParameter;
963
964 status = GdipCreateRegion(region);
965 if (status != Ok)
966 return status;
967
968 count = 0;
969 status = read_element(&mbuf, *region, &(*region)->node, &count);
970 if (status == Ok && !count)
972
973 if (status != Ok)
974 {
975 GdipDeleteRegion(*region);
976 *region = NULL;
977 }
978
979 return status;
980}
981
982/*****************************************************************************
983 * GdipGetRegionDataSize [GDIPLUS.@]
984 */
986{
987 TRACE("%p, %p\n", region, needed);
988
989 if (!(region && needed))
990 return InvalidParameter;
991
992 /* header.size doesn't count header.size and header.checksum */
993 *needed = FIELD_OFFSET(struct region_data_header, header) + write_region_data(region, NULL);
994
995 return Ok;
996}
997
999{
1000 HDC new_hdc=NULL;
1001 GpGraphics *new_graphics=NULL;
1002 GpStatus stat;
1003 INT save_state;
1004
1005 if (!path->pathdata.Count) /* PathToRegion doesn't support empty paths */
1006 {
1007 *hrgn = CreateRectRgn( 0, 0, 0, 0 );
1008 return *hrgn ? Ok : OutOfMemory;
1009 }
1010
1011 if (!graphics)
1012 {
1013 new_hdc = CreateCompatibleDC(0);
1014 if (!new_hdc)
1015 return OutOfMemory;
1016
1017 stat = GdipCreateFromHDC(new_hdc, &new_graphics);
1018 graphics = new_graphics;
1019 if (stat != Ok)
1020 {
1021 DeleteDC(new_hdc);
1022 return stat;
1023 }
1024 }
1025 else if (!graphics->hdc)
1026 {
1027 graphics->hdc = new_hdc = CreateCompatibleDC(0);
1028 if (!new_hdc)
1029 return OutOfMemory;
1030 }
1031
1032 save_state = SaveDC(graphics->hdc);
1033 EndPath(graphics->hdc);
1034
1035 SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
1036 : WINDING));
1037
1038 gdi_transform_acquire(graphics);
1039
1040 stat = trace_path(graphics, path);
1041 if (stat == Ok)
1042 {
1043 *hrgn = PathToRegion(graphics->hdc);
1044 stat = *hrgn ? Ok : OutOfMemory;
1045 }
1046
1047 gdi_transform_release(graphics);
1048
1049 RestoreDC(graphics->hdc, save_state);
1050 if (new_hdc)
1051 {
1052 DeleteDC(new_hdc);
1053 if (new_graphics)
1054 GdipDeleteGraphics(new_graphics);
1055 else
1056 graphics->hdc = NULL;
1057 }
1058
1059 return stat;
1060}
1061
1063{
1064 switch (element->type)
1065 {
1067 *hrgn = NULL;
1068 return Ok;
1070 *hrgn = CreateRectRgn(0, 0, 0, 0);
1071 return *hrgn ? Ok : OutOfMemory;
1072 case RegionDataPath:
1073 return get_path_hrgn(element->elementdata.path, graphics, hrgn);
1074 case RegionDataRect:
1075 {
1076 GpPath* path;
1077 GpStatus stat;
1078 GpRectF* rc = &element->elementdata.rect;
1079
1081 if (stat != Ok)
1082 return stat;
1083 stat = GdipAddPathRectangle(path, rc->X, rc->Y, rc->Width, rc->Height);
1084
1085 if (stat == Ok)
1086 stat = get_path_hrgn(path, graphics, hrgn);
1087
1089
1090 return stat;
1091 }
1093 case CombineModeUnion:
1094 case CombineModeXor:
1095 case CombineModeExclude:
1097 {
1098 HRGN left, right;
1099 GpStatus stat;
1100 int ret;
1101
1102 stat = get_region_hrgn(element->elementdata.combine.left, graphics, &left);
1103 if (stat != Ok)
1104 {
1105 *hrgn = NULL;
1106 return stat;
1107 }
1108
1109 if (left == NULL)
1110 {
1111 /* existing region is infinite */
1112 switch (element->type)
1113 {
1115 return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn);
1117 left = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22);
1118 break;
1120 *hrgn = NULL;
1121 return Ok;
1122 }
1123 }
1124
1125 stat = get_region_hrgn(element->elementdata.combine.right, graphics, &right);
1126 if (stat != Ok)
1127 {
1129 *hrgn = NULL;
1130 return stat;
1131 }
1132
1133 if (right == NULL)
1134 {
1135 /* new region is infinite */
1136 switch (element->type)
1137 {
1139 *hrgn = left;
1140 return Ok;
1142 right = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22);
1143 break;
1146 *hrgn = NULL;
1147 return Ok;
1148 }
1149 }
1150
1151 switch (element->type)
1152 {
1155 break;
1156 case CombineModeUnion:
1158 break;
1159 case CombineModeXor:
1161 break;
1162 case CombineModeExclude:
1164 break;
1167 break;
1168 default:
1169 ret = ERROR;
1170 }
1171
1173
1174 if (ret == ERROR)
1175 {
1177 *hrgn = NULL;
1178 return GenericError;
1179 }
1180
1181 *hrgn = left;
1182 return Ok;
1183 }
1184 default:
1185 FIXME("GdipGetRegionHRgn unimplemented for region type=%x\n", element->type);
1186 *hrgn = NULL;
1187 return NotImplemented;
1188 }
1189}
1190
1191/*****************************************************************************
1192 * GdipGetRegionHRgn [GDIPLUS.@]
1193 */
1195{
1196 TRACE("(%p, %p, %p)\n", region, graphics, hrgn);
1197
1198 if (!region || !hrgn)
1199 return InvalidParameter;
1200
1201 return get_region_hrgn(&region->node, graphics, hrgn);
1202}
1203
1205{
1207 GpRectF rect;
1208
1209 TRACE("(%p, %p, %p)\n", region, graphics, res);
1210
1211 if(!region || !graphics || !res)
1212 return InvalidParameter;
1213
1214 status = GdipGetRegionBounds(region, graphics, &rect);
1215 if (status != Ok) return status;
1216
1217 *res = rect.Width == 0.0 && rect.Height == 0.0;
1218 TRACE("=> %d\n", *res);
1219
1220 return Ok;
1221}
1222
1223/*****************************************************************************
1224 * GdipIsEqualRegion [GDIPLUS.@]
1225 */
1227 BOOL *res)
1228{
1229 HRGN hrgn1, hrgn2;
1230 GpStatus stat;
1231
1232 TRACE("(%p, %p, %p, %p)\n", region, region2, graphics, res);
1233
1234 if(!region || !region2 || !graphics || !res)
1235 return InvalidParameter;
1236
1237 stat = GdipGetRegionHRgn(region, graphics, &hrgn1);
1238 if(stat != Ok)
1239 return stat;
1240 stat = GdipGetRegionHRgn(region2, graphics, &hrgn2);
1241 if(stat != Ok){
1242 DeleteObject(hrgn1);
1243 return stat;
1244 }
1245
1246 *res = EqualRgn(hrgn1, hrgn2);
1247
1248 /* one of GpRegions is infinite */
1249 if(*res == ERROR)
1250 *res = (!hrgn1 && !hrgn2);
1251
1252 DeleteObject(hrgn1);
1254
1255 return Ok;
1256}
1257
1258/*****************************************************************************
1259 * GdipIsInfiniteRegion [GDIPLUS.@]
1260 */
1262{
1263 /* I think graphics is ignored here */
1264 TRACE("(%p, %p, %p)\n", region, graphics, res);
1265
1266 if(!region || !graphics || !res)
1267 return InvalidParameter;
1268
1269 *res = (region->node.type == RegionDataInfiniteRect);
1270
1271 return Ok;
1272}
1273
1274/*****************************************************************************
1275 * GdipIsVisibleRegionRect [GDIPLUS.@]
1276 */
1278{
1279 HRGN hrgn;
1280 GpStatus stat;
1281 RECT rect;
1282
1283 TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %p, %p)\n", region, x, y, w, h, graphics, res);
1284
1285 if(!region || !res)
1286 return InvalidParameter;
1287
1288 if((stat = GdipGetRegionHRgn(region, NULL, &hrgn)) != Ok)
1289 return stat;
1290
1291 /* infinite */
1292 if(!hrgn){
1293 *res = TRUE;
1294 return Ok;
1295 }
1296
1297 SetRect(&rect, ceilr(x), ceilr(y), ceilr(x + w), ceilr(y + h));
1298 *res = RectInRegion(hrgn, &rect);
1299
1301
1302 return Ok;
1303}
1304
1305/*****************************************************************************
1306 * GdipIsVisibleRegionRectI [GDIPLUS.@]
1307 */
1309{
1310 TRACE("(%p, %d, %d, %d, %d, %p, %p)\n", region, x, y, w, h, graphics, res);
1311 if(!region || !res)
1312 return InvalidParameter;
1313
1314 return GdipIsVisibleRegionRect(region, (REAL)x, (REAL)y, (REAL)w, (REAL)h, graphics, res);
1315}
1316
1317/*****************************************************************************
1318 * GdipIsVisibleRegionPoint [GDIPLUS.@]
1319 */
1321{
1322 HRGN hrgn;
1323 GpStatus stat;
1324
1325 TRACE("(%p, %.2f, %.2f, %p, %p)\n", region, x, y, graphics, res);
1326
1327 if(!region || !res)
1328 return InvalidParameter;
1329
1330 if((stat = GdipGetRegionHRgn(region, NULL, &hrgn)) != Ok)
1331 return stat;
1332
1333 /* infinite */
1334 if(!hrgn){
1335 *res = TRUE;
1336 return Ok;
1337 }
1338
1340
1342
1343 return Ok;
1344}
1345
1346/*****************************************************************************
1347 * GdipIsVisibleRegionPointI [GDIPLUS.@]
1348 */
1350{
1351 TRACE("(%p, %d, %d, %p, %p)\n", region, x, y, graphics, res);
1352
1353 return GdipIsVisibleRegionPoint(region, (REAL)x, (REAL)y, graphics, res);
1354}
1355
1356/*****************************************************************************
1357 * GdipSetEmpty [GDIPLUS.@]
1358 */
1360{
1361 GpStatus stat;
1362
1363 TRACE("%p\n", region);
1364
1365 if (!region)
1366 return InvalidParameter;
1367
1368 delete_element(&region->node);
1370
1371 return stat;
1372}
1373
1375{
1376 GpStatus stat;
1377
1378 TRACE("%p\n", region);
1379
1380 if (!region)
1381 return InvalidParameter;
1382
1383 delete_element(&region->node);
1385
1386 return stat;
1387}
1388
1389/* Transforms GpRegion elements with given matrix */
1391{
1392 GpStatus stat;
1393
1394 switch(element->type)
1395 {
1398 return Ok;
1399 case RegionDataRect:
1400 {
1401 GpRegion *new_region;
1402 GpPath *path;
1403
1404 if (matrix->matrix[1] == 0.0 && matrix->matrix[2] == 0.0)
1405 {
1406 GpPointF points[2];
1407
1408 points[0].X = element->elementdata.rect.X;
1409 points[0].Y = element->elementdata.rect.Y;
1410 points[1].X = element->elementdata.rect.X + element->elementdata.rect.Width;
1411 points[1].Y = element->elementdata.rect.Y + element->elementdata.rect.Height;
1412
1414 if (stat != Ok)
1415 return stat;
1416
1417 if (points[0].X > points[1].X)
1418 {
1419 REAL temp;
1420 temp = points[0].X;
1421 points[0].X = points[1].X;
1422 points[1].X = temp;
1423 }
1424
1425 if (points[0].Y > points[1].Y)
1426 {
1427 REAL temp;
1428 temp = points[0].Y;
1429 points[0].Y = points[1].Y;
1430 points[1].Y = temp;
1431 }
1432
1433 element->elementdata.rect.X = points[0].X;
1434 element->elementdata.rect.Y = points[0].Y;
1435 element->elementdata.rect.Width = points[1].X - points[0].X;
1436 element->elementdata.rect.Height = points[1].Y - points[0].Y;
1437 return Ok;
1438 }
1439
1440 /* We can't rotate/shear a rectangle, so convert it to a path. */
1442 if (stat == Ok)
1443 {
1445 element->elementdata.rect.X, element->elementdata.rect.Y,
1446 element->elementdata.rect.Width, element->elementdata.rect.Height);
1447
1448 if (stat == Ok)
1449 stat = GdipCreateRegionPath(path, &new_region);
1450
1452 }
1453
1454 if (stat == Ok)
1455 {
1456 /* Steal the element from the created region. */
1457 memcpy(element, &new_region->node, sizeof(region_element));
1458 heap_free(new_region);
1459 }
1460 else
1461 return stat;
1462 }
1463 /* Fall-through to do the actual conversion. */
1464 case RegionDataPath:
1465 if (!element->elementdata.path->pathdata.Count)
1466 return Ok;
1467
1469 element->elementdata.path->pathdata.Points,
1470 element->elementdata.path->pathdata.Count);
1471 return stat;
1472 default:
1473 stat = transform_region_element(element->elementdata.combine.left, matrix);
1474 if (stat == Ok)
1475 stat = transform_region_element(element->elementdata.combine.right, matrix);
1476 return stat;
1477 }
1478}
1479
1481{
1482 TRACE("(%p, %p)\n", region, matrix);
1483
1484 if (!region || !matrix)
1485 return InvalidParameter;
1486
1487 return transform_region_element(&region->node, matrix);
1488}
1489
1490/* Translates GpRegion elements with specified offsets */
1492{
1493 INT i;
1494
1495 switch(element->type)
1496 {
1499 return;
1500 case RegionDataRect:
1501 element->elementdata.rect.X += dx;
1502 element->elementdata.rect.Y += dy;
1503 return;
1504 case RegionDataPath:
1505 for(i = 0; i < element->elementdata.path->pathdata.Count; i++){
1506 element->elementdata.path->pathdata.Points[i].X += dx;
1507 element->elementdata.path->pathdata.Points[i].Y += dy;
1508 }
1509 return;
1510 default:
1511 translate_region_element(element->elementdata.combine.left, dx, dy);
1512 translate_region_element(element->elementdata.combine.right, dx, dy);
1513 return;
1514 }
1515}
1516
1517/*****************************************************************************
1518 * GdipTranslateRegion [GDIPLUS.@]
1519 */
1521{
1522 TRACE("(%p, %f, %f)\n", region, dx, dy);
1523
1524 if(!region)
1525 return InvalidParameter;
1526
1527 translate_region_element(&region->node, dx, dy);
1528
1529 return Ok;
1530}
1531
1532/*****************************************************************************
1533 * GdipTranslateRegionI [GDIPLUS.@]
1534 */
1536{
1537 TRACE("(%p, %d, %d)\n", region, dx, dy);
1538
1539 return GdipTranslateRegion(region, (REAL)dx, (REAL)dy);
1540}
1541
1543{
1544 GpRegion *region_copy;
1545 GpStatus stat;
1546 HRGN hrgn;
1547 DWORD data_size;
1548
1549 stat = GdipCloneRegion(region, &region_copy);
1550
1551 if (stat == Ok)
1552 {
1553 stat = GdipTransformRegion(region_copy, matrix);
1554
1555 if (stat == Ok)
1556 stat = GdipGetRegionHRgn(region_copy, NULL, &hrgn);
1557
1558 if (stat == Ok)
1559 {
1560 if (hrgn)
1561 {
1562 data_size = GetRegionData(hrgn, 0, NULL);
1563
1564 *data = heap_alloc_zero(data_size);
1565
1566 if (*data)
1567 GetRegionData(hrgn, data_size, *data);
1568 else
1569 stat = OutOfMemory;
1570
1572 }
1573 else
1574 {
1575 data_size = sizeof(RGNDATAHEADER) + sizeof(RECT);
1576
1577 *data = heap_alloc_zero(data_size);
1578
1579 if (*data)
1580 {
1581 (*data)->rdh.dwSize = sizeof(RGNDATAHEADER);
1582 (*data)->rdh.iType = RDH_RECTANGLES;
1583 (*data)->rdh.nCount = 1;
1584 (*data)->rdh.nRgnSize = sizeof(RECT);
1585 (*data)->rdh.rcBound.left = (*data)->rdh.rcBound.top = -0x400000;
1586 (*data)->rdh.rcBound.right = (*data)->rdh.rcBound.bottom = 0x400000;
1587
1588 memcpy((*data)->Buffer, &(*data)->rdh.rcBound, sizeof(RECT));
1589 }
1590 else
1591 stat = OutOfMemory;
1592 }
1593 }
1594
1595 GdipDeleteRegion(region_copy);
1596 }
1597
1598 return stat;
1599}
1600
1602{
1603 GpStatus stat;
1605
1606 TRACE("(%p, %p, %p)\n", region, count, matrix);
1607
1608 if (!region || !count || !matrix)
1609 return InvalidParameter;
1610
1612
1613 if (stat == Ok)
1614 {
1615 *count = data->rdh.nCount;
1616 heap_free(data);
1617 }
1618
1619 return stat;
1620}
1621
1623{
1624 GpStatus stat;
1625 DWORD i;
1627 RECT *rects;
1628
1629 if (!region || !count || !matrix)
1630 return InvalidParameter;
1631
1633
1634 if (stat == Ok)
1635 {
1636 *count = data->rdh.nCount;
1637 rects = (RECT*)data->Buffer;
1638
1639 if (scans)
1640 {
1641 for (i=0; i<data->rdh.nCount; i++)
1642 {
1643 scans[i].X = rects[i].left;
1644 scans[i].Y = rects[i].top;
1645 scans[i].Width = rects[i].right - rects[i].left;
1646 scans[i].Height = rects[i].bottom - rects[i].top;
1647 }
1648 }
1649
1650 heap_free(data);
1651 }
1652
1653 return Ok;
1654}
1655
1657{
1658 GpStatus stat;
1659 DWORD i;
1661 RECT *rects;
1662
1663 if (!region || !count || !matrix)
1664 return InvalidParameter;
1665
1667
1668 if (stat == Ok)
1669 {
1670 *count = data->rdh.nCount;
1671 rects = (RECT*)data->Buffer;
1672
1673 if (scans)
1674 {
1675 for (i=0; i<data->rdh.nCount; i++)
1676 {
1677 scans[i].X = rects[i].left;
1678 scans[i].Y = rects[i].top;
1679 scans[i].Width = rects[i].right - rects[i].left;
1680 scans[i].Height = rects[i].bottom - rects[i].top;
1681 }
1682 }
1683
1684 heap_free(data);
1685 }
1686
1687 return Ok;
1688}
static HRGN hrgn2
static HRGN hrgn
#define stat
Definition: acwin.h:99
#define write
Definition: acwin.h:97
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
struct _RGNDATAHEADER RGNDATAHEADER
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WINDING
Definition: constants.h:279
#define ALTERNATE
Definition: constants.h:278
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
float REAL
Definition: types.h:41
#define Y(I)
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
Definition: graphics.c:2395
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y, REAL width, REAL height)
GpStatus WINGDIPAPI GdipClonePath(GpPath *path, GpPath **clone)
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:363
DWORD write_region_data(const GpRegion *region, void *data)
Definition: region.c:696
static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:1062
GpStatus WINGDIPAPI GdipIsVisibleRegionRect(GpRegion *region, REAL x, REAL y, REAL w, REAL h, GpGraphics *graphics, BOOL *res)
Definition: region.c:1277
#define FLAGS_INTPATH
Definition: region.c:77
GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode)
Definition: region.c:232
static GpStatus clone_element(const region_element *element, region_element **element2)
Definition: region.c:140
static GpStatus get_region_scans_data(GpRegion *region, GpMatrix *matrix, LPRGNDATA *data)
Definition: region.c:1542
static void translate_region_element(region_element *element, REAL dx, REAL dy)
Definition: region.c:1491
static void write_element(const region_element *element, DWORD *buffer, INT *filled)
Definition: region.c:662
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
Definition: region.c:1204
GpStatus WINGDIPAPI GdipIsInfiniteRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
Definition: region.c:1261
GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region)
Definition: region.c:1374
GpStatus WINGDIPAPI GdipSetEmpty(GpRegion *region)
Definition: region.c:1359
GpStatus WINGDIPAPI GdipTranslateRegionI(GpRegion *region, INT dx, INT dy)
Definition: region.c:1535
GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:1194
GpStatus WINGDIPAPI GdipGetRegionBoundsI(GpRegion *region, GpGraphics *graphics, GpRect *rect)
Definition: region.c:629
GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *region, GpMatrix *matrix)
Definition: region.c:1480
GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect, GpRegion **region)
Definition: region.c:459
GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion *region, REAL x, REAL y, GpGraphics *graphics, BOOL *res)
Definition: region.c:1320
static GpStatus init_region(GpRegion *region, const RegionType type)
Definition: region.c:132
GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region)
Definition: region.c:946
static GpStatus transform_region_element(region_element *element, GpMatrix *matrix)
Definition: region.c:1390
GpStatus WINGDIPAPI GdipIsVisibleRegionRectI(GpRegion *region, INT x, INT y, INT w, INT h, GpGraphics *graphics, BOOL *res)
Definition: region.c:1308
static INT get_element_size(const region_element *element)
Definition: region.c:106
GpStatus WINGDIPAPI GdipTranslateRegion(GpRegion *region, REAL dx, REAL dy)
Definition: region.c:1520
GpStatus WINGDIPAPI GdipGetRegionScans(GpRegion *region, GpRectF *scans, INT *count, GpMatrix *matrix)
Definition: region.c:1656
GpStatus WINGDIPAPI GdipIsEqualRegion(GpRegion *region, GpRegion *region2, GpGraphics *graphics, BOOL *res)
Definition: region.c:1226
static void write_float(DWORD *location, INT *offset, const FLOAT write)
Definition: region.c:656
GpStatus WINGDIPAPI GdipCombineRegionRectI(GpRegion *region, GDIPCONST GpRect *rect, CombineMode mode)
Definition: region.c:325
GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
Definition: region.c:390
static void fuse_region(GpRegion *region, region_element *left, region_element *right, const CombineMode mode)
Definition: region.c:189
GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
Definition: region.c:985
GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect, CombineMode mode)
Definition: region.c:278
GpStatus WINGDIPAPI GdipGetRegionScansCount(GpRegion *region, UINT *count, GpMatrix *matrix)
Definition: region.c:1601
GpStatus WINGDIPAPI GdipCreateRegionHrgn(HRGN hrgn, GpRegion **region)
Definition: region.c:506
GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2, CombineMode mode)
Definition: region.c:346
static void write_dword(DWORD *location, INT *offset, const DWORD write)
Definition: region.c:650
static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, region_element *node, INT *count)
Definition: region.c:775
GpStatus WINGDIPAPI GdipIsVisibleRegionPointI(GpRegion *region, INT x, INT y, GpGraphics *graphics, BOOL *res)
Definition: region.c:1349
GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, UINT *needed)
Definition: region.c:747
GpStatus WINGDIPAPI GdipGetRegionScansI(GpRegion *region, GpRect *scans, INT *count, GpMatrix *matrix)
Definition: region.c:1622
GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics, GpRectF *rect)
Definition: region.c:587
static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
Definition: region.c:998
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
Definition: region.c:425
GpStatus WINGDIPAPI GdipDeleteRegion(GpRegion *region)
Definition: region.c:571
GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect, GpRegion **region)
Definition: region.c:488
GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
Definition: region.c:211
#define pt(x, y)
Definition: drawing.c:79
#define ERROR(name)
Definition: error_private.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define local
Definition: zutil.h:30
pKey DeleteObject()
void delete_element(region_element *element)
Definition: gdiplus.c:455
const char * debugstr_rectf(const RectF *rc)
Definition: gdiplus.c:476
BOOL lengthen_path(GpPath *path, INT len)
Definition: gdiplus.c:405
DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN
static INT gdip_round(REAL x)
static void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size)
#define VERSION_MAGIC2
static const void * buffer_read(struct memory_buffer *mbuf, INT size)
static INT ceilr(REAL x)
GpStatus gdi_transform_acquire(GpGraphics *graphics)
Definition: graphics.c:6842
RegionType
@ RegionDataEmptyRect
@ RegionDataRect
@ RegionDataInfiniteRect
@ RegionDataPath
#define VALID_MAGIC(x)
GpStatus gdi_transform_release(GpGraphics *graphics)
Definition: graphics.c:6856
GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN
Definition: graphics.c:2087
CombineMode
Definition: gdiplusenums.h:350
@ CombineModeUnion
Definition: gdiplusenums.h:353
@ CombineModeReplace
Definition: gdiplusenums.h:351
@ CombineModeComplement
Definition: gdiplusenums.h:356
@ CombineModeIntersect
Definition: gdiplusenums.h:352
@ CombineModeExclude
Definition: gdiplusenums.h:355
@ CombineModeXor
Definition: gdiplusenums.h:354
@ FillModeAlternate
Definition: gdiplusenums.h:55
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
Rect GpRect
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
@ InvalidParameter
Definition: gdiplustypes.h:28
@ OutOfMemory
Definition: gdiplustypes.h:29
@ InsufficientBuffer
Definition: gdiplustypes.h:31
@ NotImplemented
Definition: gdiplustypes.h:32
@ GenericError
Definition: gdiplustypes.h:27
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei count
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
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLdouble GLdouble right
Definition: glext.h:10859
GLuint GLenum matrix
Definition: glext.h:9407
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLsizei const GLfloat * points
Definition: glext.h:8112
GLintptr offset
Definition: glext.h:5920
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HDC
Definition: imagelist.c:92
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
static calc_node_t temp
Definition: rpn_ieee.c:38
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
region_element node
DWORD num_children
REAL X
Definition: gdiplustypes.h:648
REAL Height
Definition: gdiplustypes.h:664
REAL X
Definition: gdiplustypes.h:661
REAL Width
Definition: gdiplustypes.h:663
REAL Y
Definition: gdiplustypes.h:662
INT Width
Definition: gdiplustypes.h:671
INT Height
Definition: gdiplustypes.h:672
INT X
Definition: gdiplustypes.h:669
INT Y
Definition: gdiplustypes.h:670
short X
Definition: region.c:102
short Y
Definition: region.c:103
DWORD size
Definition: region.c:94
DWORD magic
Definition: region.c:95
struct region_header header
Definition: region.c:89
DWORD checksum
Definition: region.c:88
struct region_element::@402::@403 combine
union region_element::@402 elementdata
DWORD num_children
Definition: region.c:82
DWORD magic
Definition: region.c:81
Definition: stat.h:55
Definition: ps.c:97
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
Definition: cmds.c:130
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
float FLOAT
Definition: typedefs.h:69
int32_t INT
Definition: typedefs.h:58
Definition: dlist.c:348
int ret
#define LPRECT
Definition: precomp.h:28
#define RECT
Definition: precomp.h:26
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
#define RGN_DIFF
Definition: wingdi.h:358
#define RDH_RECTANGLES
Definition: wingdi.h:669
BOOL WINAPI EqualRgn(_In_ HRGN, _In_ HRGN)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI PtInRegion(_In_ HRGN, _In_ int, _In_ int)
int WINAPI CombineRgn(_In_opt_ HRGN hrgnDest, _In_opt_ HRGN hrgnSrc1, _In_opt_ HRGN hrgnSrc2, _In_ int fnCombineMode)
#define RGN_AND
Definition: wingdi.h:356
BOOL WINAPI RestoreDC(_In_ HDC, _In_ int)
HRGN WINAPI PathToRegion(_In_ HDC)
#define RGN_XOR
Definition: wingdi.h:360
#define RGN_OR
Definition: wingdi.h:359
BOOL WINAPI RectInRegion(_In_ HRGN, _In_ LPCRECT)
DWORD WINAPI GetRegionData(_In_ HRGN hrgn, _In_ DWORD nCount, _Out_writes_bytes_to_opt_(nCount, return) LPRGNDATA lpRgnData)
BOOL WINAPI DeleteDC(_In_ HDC)
BOOL WINAPI EndPath(_In_ HDC)
int WINAPI SaveDC(_In_ HDC)
int WINAPI GetRgnBox(_In_ HRGN, _Out_ LPRECT)
int WINAPI SetPolyFillMode(_In_ HDC, _In_ int)
Definition: dc.c:1167
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
unsigned char BYTE
Definition: xxhash.c:193