1 /*
2  * tkWinRegion.c --
3  *
4  *	Tk Region emulation code.
5  *
6  * Copyright (c) 1995 Sun Microsystems, Inc.
7  *
8  * See the file "license.terms" for information on usage and redistribution of
9  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  */
11 
12 #include "tkWinInt.h"
13 
14 #undef TkCreateRegion
15 #undef TkDestroyRegion
16 #undef TkClipBox
17 #undef TkIntersectRegion
18 #undef TkUnionRectWithRegion
19 #undef TkRectInRegion
20 #undef TkSubtractRegion
21 
22 /*
23  *----------------------------------------------------------------------
24  *
25  * TkCreateRegion --
26  *
27  *	Construct an empty region.
28  *
29  * Results:
30  *	Returns a new region handle.
31  *
32  * Side effects:
33  *	None.
34  *
35  *----------------------------------------------------------------------
36  */
37 
38 TkRegion
TkCreateRegion(void)39 TkCreateRegion(void)
40 {
41     RECT rect;
42     memset(&rect, 0, sizeof(RECT));
43     return (TkRegion) CreateRectRgnIndirect(&rect);
44 }
45 
46 /*
47  *----------------------------------------------------------------------
48  *
49  * TkDestroyRegion --
50  *
51  *	Destroy the specified region.
52  *
53  * Results:
54  *	None.
55  *
56  * Side effects:
57  *	Frees the storage associated with the specified region.
58  *
59  *----------------------------------------------------------------------
60  */
61 
62 void
TkDestroyRegion(TkRegion r)63 TkDestroyRegion(
64     TkRegion r)
65 {
66     DeleteObject((HRGN) r);
67 }
68 
69 /*
70  *----------------------------------------------------------------------
71  *
72  * TkClipBox --
73  *
74  *	Computes the bounding box of a region.
75  *
76  * Results:
77  *	Sets rect_return to the bounding box of the region.
78  *
79  * Side effects:
80  *	None.
81  *
82  *----------------------------------------------------------------------
83  */
84 
85 void
TkClipBox(TkRegion r,XRectangle * rect_return)86 TkClipBox(
87     TkRegion r,
88     XRectangle* rect_return)
89 {
90     RECT rect;
91 
92     GetRgnBox((HRGN)r, &rect);
93     rect_return->x = (short) rect.left;
94     rect_return->y = (short) rect.top;
95     rect_return->width = (short) (rect.right - rect.left);
96     rect_return->height = (short) (rect.bottom - rect.top);
97 }
98 
99 /*
100  *----------------------------------------------------------------------
101  *
102  * TkIntersectRegion --
103  *
104  *	Compute the intersection of two regions.
105  *
106  * Results:
107  *	Returns the result in the dr_return region.
108  *
109  * Side effects:
110  *	None.
111  *
112  *----------------------------------------------------------------------
113  */
114 
115 void
TkIntersectRegion(TkRegion sra,TkRegion srb,TkRegion dr_return)116 TkIntersectRegion(
117     TkRegion sra,
118     TkRegion srb,
119     TkRegion dr_return)
120 {
121     CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_AND);
122 }
123 
124 /*
125  *----------------------------------------------------------------------
126  *
127  * TkUnionRectWithRegion --
128  *
129  *	Create the union of a source region and a rectangle.
130  *
131  * Results:
132  *	Returns the result in the dr_return region.
133  *
134  * Side effects:
135  *	None.
136  *
137  *----------------------------------------------------------------------
138  */
139 
140 void
TkUnionRectWithRegion(XRectangle * rectangle,TkRegion src_region,TkRegion dest_region_return)141 TkUnionRectWithRegion(
142     XRectangle *rectangle,
143     TkRegion src_region,
144     TkRegion dest_region_return)
145 {
146     HRGN rectRgn = CreateRectRgn(rectangle->x, rectangle->y,
147 	    rectangle->x + rectangle->width, rectangle->y + rectangle->height);
148 
149     CombineRgn((HRGN) dest_region_return, (HRGN) src_region,
150 	    (HRGN) rectRgn, RGN_OR);
151     DeleteObject(rectRgn);
152 }
153 
154 /*
155  *----------------------------------------------------------------------
156  *
157  * TkpBuildRegionFromAlphaData --
158  *
159  *	Set up a rectangle of the given region based on the supplied alpha
160  *	data.
161  *
162  * Results:
163  *	None
164  *
165  * Side effects:
166  *	The region is updated, with extra pixels added to it.
167  *
168  *----------------------------------------------------------------------
169  */
170 
171 void
TkpBuildRegionFromAlphaData(TkRegion region,unsigned int x,unsigned int y,unsigned int width,unsigned int height,unsigned char * dataPtr,unsigned int pixelStride,unsigned int lineStride)172 TkpBuildRegionFromAlphaData(
173     TkRegion region,
174     unsigned int x, unsigned int y,
175 				/* Where in region to update. */
176     unsigned int width, unsigned int height,
177 				/* Size of rectangle to update. */
178     unsigned char *dataPtr,	/* Data to read from. */
179     unsigned int pixelStride,	/* Num bytes from one piece of alpha data to
180 				 * the next in the line. */
181     unsigned int lineStride)	/* Num bytes from one line of alpha data to
182 				 * the next line. */
183 {
184     unsigned char *lineDataPtr;
185     unsigned int x1, y1, end;
186     HRGN rectRgn = CreateRectRgn(0,0,1,1); /* Workspace region. */
187 
188     for (y1 = 0; y1 < height; y1++) {
189 	lineDataPtr = dataPtr;
190 	for (x1 = 0; x1 < width; x1 = end) {
191 	    /*
192 	     * Search for first non-transparent pixel.
193 	     */
194 
195 	    while ((x1 < width) && !*lineDataPtr) {
196 		x1++;
197 		lineDataPtr += pixelStride;
198 	    }
199 	    end = x1;
200 
201 	    /*
202 	     * Search for first transparent pixel.
203 	     */
204 
205 	    while ((end < width) && *lineDataPtr) {
206 		end++;
207 		lineDataPtr += pixelStride;
208 	    }
209 	    if (end > x1) {
210 		/*
211 		 * Manipulate Win32 regions directly; it's more efficient.
212 		 */
213 
214 		SetRectRgn(rectRgn, (int) (x+x1), (int) (y+y1),
215 			(int) (x+end), (int) (y+y1+1));
216 		CombineRgn((HRGN) region, (HRGN) region, rectRgn, RGN_OR);
217 	    }
218 	}
219 	dataPtr += lineStride;
220     }
221 
222     DeleteObject(rectRgn);
223 }
224 
225 /*
226  *----------------------------------------------------------------------
227  *
228  * TkRectInRegion --
229  *
230  *	Test whether a given rectangle overlaps with a region.
231  *
232  * Results:
233  *	Returns RectanglePart or RectangleOut. Note that this is not a
234  *	complete implementation since it doesn't test for RectangleIn.
235  *
236  * Side effects:
237  *	None.
238  *
239  *----------------------------------------------------------------------
240  */
241 
242 int
TkRectInRegion(TkRegion r,int x,int y,unsigned int width,unsigned int height)243 TkRectInRegion(
244     TkRegion r,			/* Region to inspect */
245     int x, int y,		/* Top-left of rectangle */
246     unsigned int width,		/* Width of rectangle */
247     unsigned int height)	/* Height of rectangle */
248 {
249     RECT rect;
250     rect.top = y;
251     rect.left = x;
252     rect.bottom = y+height;
253     rect.right = x+width;
254     return RectInRegion((HRGN)r, &rect) ? RectanglePart : RectangleOut;
255 }
256 
257 /*
258  *----------------------------------------------------------------------
259  *
260  * TkSubtractRegion --
261  *
262  *	Compute the set-difference of two regions.
263  *
264  * Results:
265  *	Returns the result in the dr_return region.
266  *
267  * Side effects:
268  *	None.
269  *
270  *----------------------------------------------------------------------
271  */
272 
273 void
TkSubtractRegion(TkRegion sra,TkRegion srb,TkRegion dr_return)274 TkSubtractRegion(
275     TkRegion sra,
276     TkRegion srb,
277     TkRegion dr_return)
278 {
279     CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_DIFF);
280 }
281 
282 /*
283  * Local Variables:
284  * mode: c
285  * c-basic-offset: 4
286  * fill-column: 78
287  * End:
288  */
289