Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. | |
3 | * | |
4 | *Permission is hereby granted, free of charge, to any person obtaining | |
5 | * a copy of this software and associated documentation files (the | |
6 | *"Software"), to deal in the Software without restriction, including | |
7 | *without limitation the rights to use, copy, modify, merge, publish, | |
8 | *distribute, sublicense, and/or sell copies of the Software, and to | |
9 | *permit persons to whom the Software is furnished to do so, subject to | |
10 | *the following conditions: | |
11 | * | |
12 | *The above copyright notice and this permission notice shall be | |
13 | *included in all copies or substantial portions of the Software. | |
14 | * | |
15 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
16 | *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
17 | *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
18 | *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR | |
19 | *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
20 | *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
21 | *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | *Except as contained in this notice, the name of the XFree86 Project | |
24 | *shall not be used in advertising or otherwise to promote the sale, use | |
25 | *or other dealings in this Software without prior written authorization | |
26 | *from the XFree86 Project. | |
27 | * | |
28 | * Authors: Harold L Hunt II | |
29 | * Alan Hourihane <alanh@fairlite.demon.co.uk> | |
30 | */ | |
31 | ||
32 | #ifdef HAVE_XWIN_CONFIG_H | |
33 | #include <xwin-config.h> | |
34 | #endif | |
35 | #include "win.h" | |
36 | ||
37 | extern void ROP16(HDC hdc, int rop); | |
38 | ||
39 | #define TRANSLATE_COLOR(color) \ | |
40 | { \ | |
41 | if (pDrawable->depth == 15) \ | |
42 | color = ((color & 0x1F) << 19) | ((color & 0x03E0) << 6) | \ | |
43 | ((color & 0xF800) >> 8); \ | |
44 | else if (pDrawable->depth == 16) \ | |
45 | color = ((color & 0x1F) << 19) | ((color & 0x07E0) << 5) | \ | |
46 | ((color & 0xF800) >> 8); \ | |
47 | else if (pDrawable->depth == 24 || pDrawable->depth == 32) \ | |
48 | color = ((color & 0xFF) << 16) | (color & 0xFF00) | \ | |
49 | ((color & 0xFF0000) >> 16); \ | |
50 | } | |
51 | ||
52 | /* See Porting Layer Definition - p. 54 */ | |
53 | void | |
54 | winFillSpansNativeGDI(DrawablePtr pDrawable, | |
55 | GCPtr pGC, | |
56 | int iSpans, | |
57 | DDXPointPtr pPoints, int *piWidths, int fSorted) | |
58 | { | |
59 | winGCPriv(pGC); | |
60 | HBITMAP hbmpOrig = NULL, hbmpOrigStipple = NULL; | |
61 | HBITMAP hPenOrig = NULL; | |
62 | HBITMAP hBitmap = NULL; | |
63 | PixmapPtr pPixmap = NULL; | |
64 | winPrivPixmapPtr pPixmapPriv = NULL; | |
65 | PixmapPtr pStipple = NULL; | |
66 | winPrivPixmapPtr pStipplePriv = NULL; | |
67 | PixmapPtr pTile = NULL; | |
68 | winPrivPixmapPtr pTilePriv = NULL; | |
69 | HDC hdcStipple = NULL, hdcTile = NULL; | |
70 | HPEN hPen = NULL; | |
71 | int iX; | |
72 | int fg, bg; | |
73 | RegionPtr pClip = pGC->pCompositeClip; | |
74 | BoxPtr pextent, pbox; | |
75 | int nbox; | |
76 | int extentX1, extentX2, extentY1, extentY2; | |
77 | int fullX1, fullX2, fullY1; | |
78 | HRGN hrgn = NULL, combined = NULL; | |
79 | ||
80 | nbox = RegionNumRects(pClip); | |
81 | pbox = RegionRects(pClip); | |
82 | ||
83 | if (!nbox) | |
84 | return; | |
85 | ||
86 | combined = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2); | |
87 | nbox--; | |
88 | pbox++; | |
89 | ||
90 | while (nbox--) { | |
91 | hrgn = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2); | |
92 | CombineRgn(combined, combined, hrgn, RGN_OR); | |
93 | DeleteObject(hrgn); | |
94 | hrgn = NULL; | |
95 | pbox++; | |
96 | } | |
97 | ||
98 | pextent = RegionExtents(pClip); | |
99 | extentX1 = pextent->x1; | |
100 | extentY1 = pextent->y1; | |
101 | extentX2 = pextent->x2; | |
102 | extentY2 = pextent->y2; | |
103 | ||
104 | /* Branch on the type of drawable we have */ | |
105 | switch (pDrawable->type) { | |
106 | case DRAWABLE_PIXMAP: | |
107 | ||
108 | SelectClipRgn(pGCPriv->hdcMem, combined); | |
109 | DeleteObject(combined); | |
110 | combined = NULL; | |
111 | ||
112 | /* Get a pixmap pointer from the drawable pointer, and fetch privates */ | |
113 | pPixmap = (PixmapPtr) pDrawable; | |
114 | pPixmapPriv = winGetPixmapPriv(pPixmap); | |
115 | ||
116 | /* Select the drawable pixmap into memory hdc */ | |
117 | hbmpOrig = SelectObject(pGCPriv->hdcMem, pPixmapPriv->hBitmap); | |
118 | if (hbmpOrig == NULL) | |
119 | FatalError("winFillSpans - DRAWABLE_PIXMAP - " | |
120 | "SelectObject () failed on\n\tpPixmapPriv->hBitmap: " | |
121 | "%p\n", pPixmapPriv->hBitmap); | |
122 | ||
123 | /* Branch on the fill type */ | |
124 | switch (pGC->fillStyle) { | |
125 | case FillSolid: | |
126 | ||
127 | ROP16(pGCPriv->hdcMem, pGC->alu); | |
128 | ||
129 | if (pDrawable->depth == 1) { | |
130 | if (pGC->fgPixel == 0) | |
131 | hPenOrig = SelectObject(pGCPriv->hdcMem, | |
132 | GetStockObject(BLACK_PEN)); | |
133 | else | |
134 | hPenOrig = SelectObject(pGCPriv->hdcMem, | |
135 | GetStockObject(WHITE_PEN)); | |
136 | } | |
137 | else { | |
138 | fg = pGC->fgPixel; | |
139 | TRANSLATE_COLOR(fg); | |
140 | hPen = CreatePen(PS_SOLID, 0, fg); | |
141 | hPenOrig = SelectObject(pGCPriv->hdcMem, hPen); | |
142 | } | |
143 | ||
144 | while (iSpans--) { | |
145 | fullX1 = pPoints->x; | |
146 | fullY1 = pPoints->y; | |
147 | fullX2 = fullX1 + (int) *piWidths; | |
148 | pPoints++; | |
149 | piWidths++; | |
150 | ||
151 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
152 | continue; | |
153 | ||
154 | if (fullX1 < extentX1) | |
155 | fullX1 = extentX1; | |
156 | if (fullX2 > extentX2) | |
157 | fullX2 = extentX2; | |
158 | ||
159 | if (fullX1 >= fullX2) | |
160 | continue; | |
161 | ||
162 | MoveToEx(pGCPriv->hdcMem, fullX1, fullY1, NULL); | |
163 | LineTo(pGCPriv->hdcMem, fullX2, fullY1); | |
164 | } | |
165 | ||
166 | SetROP2(pGCPriv->hdcMem, R2_COPYPEN); | |
167 | ||
168 | /* Give back the Pen */ | |
169 | SelectObject(pGCPriv->hdcMem, hPenOrig); | |
170 | ||
171 | if (pDrawable->depth != 1) | |
172 | DeleteObject(hPen); | |
173 | break; | |
174 | ||
175 | case FillOpaqueStippled: | |
176 | ||
177 | pStipple = pGC->stipple; | |
178 | pStipplePriv = winGetPixmapPriv(pStipple); | |
179 | ||
180 | /* Create a device-dependent bitmap for the stipple */ | |
181 | hBitmap = CreateDIBitmap(pGCPriv->hdcMem, | |
182 | (BITMAPINFOHEADER *) pStipplePriv->pbmih, | |
183 | CBM_INIT, | |
184 | pStipplePriv->pbBits, | |
185 | (BITMAPINFO *) pStipplePriv->pbmih, | |
186 | DIB_RGB_COLORS); | |
187 | ||
188 | /* Create a memory DC to hold the stipple */ | |
189 | hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem); | |
190 | ||
191 | /* Select the stipple bitmap into the stipple DC */ | |
192 | hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); | |
193 | if (hbmpOrigStipple == NULL) | |
194 | FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " | |
195 | "SelectObject () failed on hbmpOrigStipple\n"); | |
196 | ||
197 | /* Make a temporary copy of the foreground and background colors */ | |
198 | bg = pGC->bgPixel; | |
199 | fg = pGC->fgPixel; | |
200 | ||
201 | /* Translate the depth-dependent colors to Win32 COLORREFs */ | |
202 | TRANSLATE_COLOR(fg); | |
203 | TRANSLATE_COLOR(bg); | |
204 | SetTextColor(pGCPriv->hdcMem, fg); | |
205 | SetBkColor(pGCPriv->hdcMem, bg); | |
206 | ||
207 | while (iSpans--) { | |
208 | int width = pStipple->drawable.width; | |
209 | ||
210 | fullX1 = pPoints->x; | |
211 | fullY1 = pPoints->y; | |
212 | fullX2 = fullX1 + (int) *piWidths; | |
213 | pPoints++; | |
214 | piWidths++; | |
215 | ||
216 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
217 | continue; | |
218 | ||
219 | if (fullX1 < extentX1) | |
220 | fullX1 = extentX1; | |
221 | if (fullX2 > extentX2) | |
222 | fullX2 = extentX2; | |
223 | ||
224 | if (fullX1 >= fullX2) | |
225 | continue; | |
226 | ||
227 | for (iX = fullX1; iX < fullX2; iX += width) { | |
228 | int xoffset; | |
229 | ||
230 | if ((iX + pStipple->drawable.width) > fullX2) | |
231 | width = fullX2 - iX; | |
232 | else | |
233 | width = pStipple->drawable.width; | |
234 | ||
235 | if (iX == fullX1) | |
236 | xoffset = | |
237 | (fullX1 - | |
238 | (pDrawable->x + | |
239 | (pGC->patOrg.x % pStipple->drawable.width) - | |
240 | pStipple->drawable.width)) % | |
241 | pStipple->drawable.width; | |
242 | else | |
243 | xoffset = 0; | |
244 | ||
245 | if (xoffset + width > pStipple->drawable.width) | |
246 | width = pStipple->drawable.width - xoffset; | |
247 | ||
248 | BitBlt(pGCPriv->hdcMem, | |
249 | iX, fullY1, | |
250 | width, 1, | |
251 | hdcStipple, | |
252 | xoffset, | |
253 | (fullY1 - | |
254 | (pDrawable->y + | |
255 | (pGC->patOrg.y % pStipple->drawable.height) - | |
256 | pStipple->drawable.height)) % | |
257 | pStipple->drawable.height, g_copyROP[pGC->alu]); | |
258 | } | |
259 | } | |
260 | ||
261 | /* Clear the stipple HDC */ | |
262 | SelectObject(hdcStipple, hbmpOrigStipple); | |
263 | DeleteDC(hdcStipple); | |
264 | ||
265 | /* Delete the device dependent stipple bitmap */ | |
266 | DeleteObject(hBitmap); | |
267 | ||
268 | break; | |
269 | case FillStippled: | |
270 | ||
271 | pStipple = pGC->stipple; | |
272 | pStipplePriv = winGetPixmapPriv(pStipple); | |
273 | ||
274 | /* Create a device-dependent bitmap for the stipple */ | |
275 | hBitmap = CreateDIBitmap(pGCPriv->hdcMem, | |
276 | (BITMAPINFOHEADER *) pStipplePriv->pbmih, | |
277 | CBM_INIT, | |
278 | pStipplePriv->pbBits, | |
279 | (BITMAPINFO *) pStipplePriv->pbmih, | |
280 | DIB_RGB_COLORS); | |
281 | ||
282 | /* Create a memory DC to hold the stipple */ | |
283 | hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem); | |
284 | ||
285 | /* Select the stipple bitmap into the stipple DC */ | |
286 | hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); | |
287 | if (hbmpOrigStipple == NULL) | |
288 | FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " | |
289 | "SelectObject () failed on hbmpOrigStipple\n"); | |
290 | ||
291 | /* Make a temporary copy of the foreground and background colors */ | |
292 | bg = pGC->bgPixel; | |
293 | fg = pGC->fgPixel; | |
294 | ||
295 | /* Translate the depth-dependent colors to Win32 COLORREFs */ | |
296 | TRANSLATE_COLOR(fg); | |
297 | TRANSLATE_COLOR(bg); | |
298 | ||
299 | /* this is fudgy, we should only invert on the last one | |
300 | * We need to get the black/white pixels right in the | |
301 | * colormap. But yeah ! it's working.. | |
302 | */ | |
303 | if (pGC->bgPixel != -1 && pGC->fgPixel != -1) { | |
304 | SetTextColor(pGCPriv->hdcMem, fg); | |
305 | SetBkColor(pGCPriv->hdcMem, bg); | |
306 | BitBlt(hdcStipple, | |
307 | 0, 0, | |
308 | pStipple->drawable.width, pStipple->drawable.height, | |
309 | hdcStipple, 0, 0, 0x330008); | |
310 | } | |
311 | else if (pGC->bgPixel == -1) { | |
312 | SetTextColor(pGCPriv->hdcMem, fg); | |
313 | SetBkMode(pGCPriv->hdcMem, TRANSPARENT); | |
314 | BitBlt(hdcStipple, | |
315 | 0, 0, | |
316 | pStipple->drawable.width, pStipple->drawable.height, | |
317 | hdcStipple, 0, 0, 0x330008); | |
318 | } | |
319 | else if (pGC->fgPixel == -1) { | |
320 | SetTextColor(pGCPriv->hdcMem, bg); | |
321 | SetBkMode(pGCPriv->hdcMem, TRANSPARENT); | |
322 | #if 0 | |
323 | BitBlt(hdcStipple, | |
324 | 0, 0, | |
325 | pStipple->drawable.width, pStipple->drawable.height, | |
326 | hdcStipple, 0, 0, 0x330008); | |
327 | #endif | |
328 | } | |
329 | ||
330 | while (iSpans--) { | |
331 | int width = pStipple->drawable.width; | |
332 | ||
333 | fullX1 = pPoints->x; | |
334 | fullY1 = pPoints->y; | |
335 | fullX2 = fullX1 + (int) *piWidths; | |
336 | pPoints++; | |
337 | piWidths++; | |
338 | ||
339 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
340 | continue; | |
341 | ||
342 | if (fullX1 < extentX1) | |
343 | fullX1 = extentX1; | |
344 | if (fullX2 > extentX2) | |
345 | fullX2 = extentX2; | |
346 | ||
347 | if (fullX1 >= fullX2) | |
348 | continue; | |
349 | ||
350 | for (iX = fullX1; iX < fullX2; iX += width) { | |
351 | int xoffset; | |
352 | ||
353 | if ((iX + pStipple->drawable.width) > fullX2) | |
354 | width = fullX2 - iX; | |
355 | else | |
356 | width = pStipple->drawable.width; | |
357 | ||
358 | if (iX == fullX1) | |
359 | xoffset = | |
360 | (fullX1 - | |
361 | (pDrawable->x + | |
362 | (pGC->patOrg.x % pStipple->drawable.width) - | |
363 | pStipple->drawable.width)) % | |
364 | pStipple->drawable.width; | |
365 | else | |
366 | xoffset = 0; | |
367 | ||
368 | if (xoffset + width > pStipple->drawable.width) | |
369 | width = pStipple->drawable.width - xoffset; | |
370 | ||
371 | BitBlt(pGCPriv->hdcMem, | |
372 | iX, fullY1, | |
373 | width, 1, | |
374 | hdcStipple, | |
375 | xoffset, | |
376 | (fullY1 - | |
377 | (pDrawable->y + | |
378 | (pGC->patOrg.y % pStipple->drawable.height) - | |
379 | pStipple->drawable.height)) % | |
380 | pStipple->drawable.height, g_copyROP[pGC->alu]); | |
381 | } | |
382 | } | |
383 | ||
384 | /* Clear the stipple HDC */ | |
385 | SelectObject(hdcStipple, hbmpOrigStipple); | |
386 | DeleteDC(hdcStipple); | |
387 | ||
388 | /* Delete the device dependent stipple bitmap */ | |
389 | DeleteObject(hBitmap); | |
390 | ||
391 | /* Restore the background mode */ | |
392 | SetBkMode(pGCPriv->hdcMem, OPAQUE); | |
393 | break; | |
394 | ||
395 | case FillTiled: | |
396 | ||
397 | /* Get a pixmap pointer from the tile pointer, and fetch privates */ | |
398 | pTile = (PixmapPtr) pGC->tile.pixmap; | |
399 | pTilePriv = winGetPixmapPriv(pTile); | |
400 | ||
401 | /* Create a memory DC to hold the tile */ | |
402 | hdcTile = CreateCompatibleDC(pGCPriv->hdcMem); | |
403 | ||
404 | /* Select the tile into a DC */ | |
405 | hbmpOrig = SelectObject(hdcTile, pTilePriv->hBitmap); | |
406 | if (hbmpOrig == NULL) | |
407 | FatalError("winFillSpans - DRAWABLE_PIXMAP - FillTiled - " | |
408 | "SelectObject () failed on pTilePriv->hBitmap\n"); | |
409 | ||
410 | while (iSpans--) { | |
411 | int width = pTile->drawable.width; | |
412 | ||
413 | fullX1 = pPoints->x; | |
414 | fullY1 = pPoints->y; | |
415 | fullX2 = fullX1 + (int) *piWidths; | |
416 | pPoints++; | |
417 | piWidths++; | |
418 | ||
419 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
420 | continue; | |
421 | ||
422 | if (fullX1 < extentX1) | |
423 | fullX1 = extentX1; | |
424 | if (fullX2 > extentX2) | |
425 | fullX2 = extentX2; | |
426 | ||
427 | if (fullX1 >= fullX2) | |
428 | continue; | |
429 | ||
430 | for (iX = fullX1; iX < fullX2; iX += width) { | |
431 | int xoffset; | |
432 | ||
433 | if ((iX + pTile->drawable.width) > fullX2) | |
434 | width = fullX2 - iX; | |
435 | else | |
436 | width = pTile->drawable.width; | |
437 | ||
438 | if (iX == fullX1) | |
439 | xoffset = | |
440 | (fullX1 - | |
441 | (pDrawable->x + | |
442 | (pGC->patOrg.x % pTile->drawable.width) - | |
443 | pTile->drawable.width)) % pTile->drawable.width; | |
444 | else | |
445 | xoffset = 0; | |
446 | ||
447 | if (xoffset + width > pTile->drawable.width) | |
448 | width = pTile->drawable.width - xoffset; | |
449 | ||
450 | BitBlt(pGCPriv->hdcMem, | |
451 | iX, fullY1, | |
452 | width, 1, | |
453 | hdcTile, | |
454 | xoffset, | |
455 | (fullY1 - | |
456 | (pDrawable->y + | |
457 | (pGC->patOrg.y % pTile->drawable.height) - | |
458 | pTile->drawable.height)) % pTile->drawable.height, | |
459 | g_copyROP[pGC->alu]); | |
460 | } | |
461 | } | |
462 | ||
463 | /* Push the tile pixmap out of the memory HDC */ | |
464 | SelectObject(hdcTile, hbmpOrig); | |
465 | ||
466 | /* Delete the tile */ | |
467 | DeleteDC(hdcTile); | |
468 | break; | |
469 | ||
470 | default: | |
471 | ErrorF("winFillSpans - DRAWABLE_PIXMAP - Unknown fillStyle\n"); | |
472 | break; | |
473 | } | |
474 | ||
475 | /* Reset clip region */ | |
476 | SelectClipRgn(pGCPriv->hdcMem, NULL); | |
477 | ||
478 | /* Push the drawable pixmap out of the GC HDC */ | |
479 | SelectObject(pGCPriv->hdcMem, hbmpOrig); | |
480 | break; | |
481 | ||
482 | case DRAWABLE_WINDOW: | |
483 | ||
484 | SelectClipRgn(pGCPriv->hdc, combined); | |
485 | DeleteObject(combined); | |
486 | combined = NULL; | |
487 | ||
488 | /* Branch on fill style */ | |
489 | switch (pGC->fillStyle) { | |
490 | case FillSolid: | |
491 | ||
492 | ROP16(pGCPriv->hdc, pGC->alu); | |
493 | ||
494 | if (pDrawable->depth == 1) { | |
495 | if (pGC->fgPixel == 0) | |
496 | hPenOrig = SelectObject(pGCPriv->hdc, | |
497 | GetStockObject(BLACK_PEN)); | |
498 | else | |
499 | hPenOrig = SelectObject(pGCPriv->hdc, | |
500 | GetStockObject(WHITE_PEN)); | |
501 | } | |
502 | else { | |
503 | fg = pGC->fgPixel; | |
504 | TRANSLATE_COLOR(fg); | |
505 | hPen = CreatePen(PS_SOLID, 0, fg); | |
506 | hPenOrig = SelectObject(pGCPriv->hdc, hPen); | |
507 | } | |
508 | ||
509 | while (iSpans--) { | |
510 | fullX1 = pPoints->x; | |
511 | fullY1 = pPoints->y; | |
512 | fullX2 = fullX1 + (int) *piWidths; | |
513 | pPoints++; | |
514 | piWidths++; | |
515 | ||
516 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
517 | continue; | |
518 | ||
519 | if (fullX1 < extentX1) | |
520 | fullX1 = extentX1; | |
521 | if (fullX2 > extentX2) | |
522 | fullX2 = extentX2; | |
523 | ||
524 | if (fullX1 >= fullX2) | |
525 | continue; | |
526 | ||
527 | MoveToEx(pGCPriv->hdc, fullX1, fullY1, NULL); | |
528 | LineTo(pGCPriv->hdc, fullX2, fullY1); | |
529 | } | |
530 | ||
531 | SetROP2(pGCPriv->hdc, R2_COPYPEN); | |
532 | ||
533 | /* Give back the Brush */ | |
534 | SelectObject(pGCPriv->hdc, hPenOrig); | |
535 | ||
536 | if (pDrawable->depth != 1) | |
537 | DeleteObject(hPen); | |
538 | break; | |
539 | ||
540 | case FillOpaqueStippled: | |
541 | ||
542 | pStipple = pGC->stipple; | |
543 | pStipplePriv = winGetPixmapPriv(pStipple); | |
544 | ||
545 | /* Create a device-dependent bitmap for the stipple */ | |
546 | hBitmap = CreateDIBitmap(pGCPriv->hdc, | |
547 | (BITMAPINFOHEADER *) pStipplePriv->pbmih, | |
548 | CBM_INIT, | |
549 | pStipplePriv->pbBits, | |
550 | (BITMAPINFO *) pStipplePriv->pbmih, | |
551 | DIB_RGB_COLORS); | |
552 | ||
553 | /* Create a memory DC to hold the stipple */ | |
554 | hdcStipple = CreateCompatibleDC(pGCPriv->hdc); | |
555 | ||
556 | /* Select the stipple bitmap into the stipple DC */ | |
557 | hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); | |
558 | if (hbmpOrigStipple == NULL) | |
559 | FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " | |
560 | "SelectObject () failed on hbmpOrigStipple\n"); | |
561 | ||
562 | /* Make a temporary copy of the foreground and background colors */ | |
563 | bg = pGC->bgPixel; | |
564 | fg = pGC->fgPixel; | |
565 | ||
566 | /* Translate the depth-dependent colors to Win32 COLORREFs */ | |
567 | TRANSLATE_COLOR(fg); | |
568 | TRANSLATE_COLOR(bg); | |
569 | SetTextColor(pGCPriv->hdc, fg); | |
570 | SetBkColor(pGCPriv->hdc, bg); | |
571 | ||
572 | while (iSpans--) { | |
573 | int width = pStipple->drawable.width; | |
574 | ||
575 | fullX1 = pPoints->x; | |
576 | fullY1 = pPoints->y; | |
577 | fullX2 = fullX1 + (int) *piWidths; | |
578 | pPoints++; | |
579 | piWidths++; | |
580 | ||
581 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
582 | continue; | |
583 | ||
584 | if (fullX1 < extentX1) | |
585 | fullX1 = extentX1; | |
586 | if (fullX2 > extentX2) | |
587 | fullX2 = extentX2; | |
588 | ||
589 | if (fullX1 >= fullX2) | |
590 | continue; | |
591 | ||
592 | for (iX = fullX1; iX < fullX2; iX += width) { | |
593 | int xoffset; | |
594 | ||
595 | if ((iX + pStipple->drawable.width) > fullX2) | |
596 | width = fullX2 - iX; | |
597 | else | |
598 | width = pStipple->drawable.width; | |
599 | ||
600 | if (iX == fullX1) | |
601 | xoffset = | |
602 | (fullX1 - | |
603 | (pDrawable->x + | |
604 | (pGC->patOrg.x % pStipple->drawable.width) - | |
605 | pStipple->drawable.width)) % | |
606 | pStipple->drawable.width; | |
607 | else | |
608 | xoffset = 0; | |
609 | ||
610 | if (xoffset + width > pStipple->drawable.width) | |
611 | width = pStipple->drawable.width - xoffset; | |
612 | ||
613 | BitBlt(pGCPriv->hdc, | |
614 | iX, fullY1, | |
615 | width, 1, | |
616 | hdcStipple, | |
617 | xoffset, | |
618 | (fullY1 - | |
619 | (pDrawable->y + | |
620 | (pGC->patOrg.y % pStipple->drawable.height) - | |
621 | pStipple->drawable.height)) % | |
622 | pStipple->drawable.height, g_copyROP[pGC->alu]); | |
623 | } | |
624 | } | |
625 | ||
626 | /* Clear the stipple HDC */ | |
627 | SelectObject(hdcStipple, hbmpOrigStipple); | |
628 | DeleteDC(hdcStipple); | |
629 | ||
630 | /* Delete the device dependent stipple bitmap */ | |
631 | DeleteObject(hBitmap); | |
632 | ||
633 | break; | |
634 | ||
635 | case FillStippled: | |
636 | pStipple = pGC->stipple; | |
637 | pStipplePriv = winGetPixmapPriv(pStipple); | |
638 | ||
639 | /* Create a device-dependent bitmap for the stipple */ | |
640 | hBitmap = CreateDIBitmap(pGCPriv->hdcMem, | |
641 | (BITMAPINFOHEADER *) pStipplePriv->pbmih, | |
642 | CBM_INIT, | |
643 | pStipplePriv->pbBits, | |
644 | (BITMAPINFO *) pStipplePriv->pbmih, | |
645 | DIB_RGB_COLORS); | |
646 | ||
647 | /* Create a memory DC to hold the stipple */ | |
648 | hdcStipple = CreateCompatibleDC(pGCPriv->hdc); | |
649 | ||
650 | /* Select the stipple bitmap into the stipple DC */ | |
651 | hbmpOrigStipple = SelectObject(hdcStipple, hBitmap); | |
652 | if (hbmpOrigStipple == NULL) | |
653 | FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - " | |
654 | "SelectObject () failed on hbmpOrigStipple\n"); | |
655 | ||
656 | /* Make a temporary copy of the foreground and background colors */ | |
657 | bg = pGC->bgPixel; | |
658 | fg = pGC->fgPixel; | |
659 | ||
660 | /* Translate the depth-dependent colors to Win32 COLORREFs */ | |
661 | TRANSLATE_COLOR(fg); | |
662 | TRANSLATE_COLOR(bg); | |
663 | ||
664 | /* this is fudgy, we should only invert on the last one | |
665 | * We need to get the black/white pixels right in the | |
666 | * colormap. But yeah ! it's working.. | |
667 | */ | |
668 | if (pGC->bgPixel != -1 && pGC->fgPixel != -1) { | |
669 | SetTextColor(pGCPriv->hdc, fg); | |
670 | SetBkColor(pGCPriv->hdc, bg); | |
671 | BitBlt(hdcStipple, | |
672 | 0, 0, | |
673 | pStipple->drawable.width, pStipple->drawable.height, | |
674 | hdcStipple, 0, 0, 0x330008); | |
675 | } | |
676 | else if (pGC->bgPixel == -1) { | |
677 | SetTextColor(pGCPriv->hdc, fg); | |
678 | SetBkMode(pGCPriv->hdc, TRANSPARENT); | |
679 | BitBlt(hdcStipple, | |
680 | 0, 0, | |
681 | pStipple->drawable.width, pStipple->drawable.height, | |
682 | hdcStipple, 0, 0, 0x330008); | |
683 | } | |
684 | else if (pGC->fgPixel == -1) { | |
685 | SetTextColor(pGCPriv->hdc, bg); | |
686 | SetBkMode(pGCPriv->hdc, TRANSPARENT); | |
687 | #if 0 | |
688 | BitBlt(hdcStipple, | |
689 | 0, 0, | |
690 | pStipple->drawable.width, pStipple->drawable.height, | |
691 | hdcStipple, 0, 0, 0x330008); | |
692 | #endif | |
693 | } | |
694 | ||
695 | while (iSpans--) { | |
696 | int width = pStipple->drawable.width; | |
697 | ||
698 | fullX1 = pPoints->x; | |
699 | fullY1 = pPoints->y; | |
700 | fullX2 = fullX1 + (int) *piWidths; | |
701 | pPoints++; | |
702 | piWidths++; | |
703 | ||
704 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
705 | continue; | |
706 | ||
707 | if (fullX1 < extentX1) | |
708 | fullX1 = extentX1; | |
709 | if (fullX2 > extentX2) | |
710 | fullX2 = extentX2; | |
711 | ||
712 | if (fullX1 >= fullX2) | |
713 | continue; | |
714 | ||
715 | for (iX = fullX1; iX < fullX2; iX += width) { | |
716 | int xoffset; | |
717 | ||
718 | if ((iX + pStipple->drawable.width) > fullX2) | |
719 | width = fullX2 - iX; | |
720 | else | |
721 | width = pStipple->drawable.width; | |
722 | ||
723 | if (iX == fullX1) | |
724 | xoffset = | |
725 | (fullX1 - | |
726 | (pDrawable->x + | |
727 | (pGC->patOrg.x % pStipple->drawable.width) - | |
728 | pStipple->drawable.width)) % | |
729 | pStipple->drawable.width; | |
730 | else | |
731 | xoffset = 0; | |
732 | ||
733 | if (xoffset + width > pStipple->drawable.width) | |
734 | width = pStipple->drawable.width - xoffset; | |
735 | ||
736 | BitBlt(pGCPriv->hdc, | |
737 | iX, fullY1, | |
738 | width, 1, | |
739 | hdcStipple, | |
740 | xoffset, | |
741 | (fullY1 - | |
742 | (pDrawable->y + | |
743 | (pGC->patOrg.y % pStipple->drawable.height) - | |
744 | pStipple->drawable.height)) % | |
745 | pStipple->drawable.height, g_copyROP[pGC->alu]); | |
746 | } | |
747 | } | |
748 | ||
749 | /* Clear the stipple HDC */ | |
750 | SelectObject(hdcStipple, hbmpOrigStipple); | |
751 | DeleteDC(hdcStipple); | |
752 | ||
753 | /* Delete the device dependent stipple bitmap */ | |
754 | DeleteObject(hBitmap); | |
755 | ||
756 | /* Restore the background mode */ | |
757 | SetBkMode(pGCPriv->hdc, OPAQUE); | |
758 | break; | |
759 | ||
760 | case FillTiled: | |
761 | ||
762 | /* Get a pixmap pointer from the tile pointer, and fetch privates */ | |
763 | pTile = (PixmapPtr) pGC->tile.pixmap; | |
764 | pTilePriv = winGetPixmapPriv(pTile); | |
765 | ||
766 | /* Select the tile into a DC */ | |
767 | hbmpOrig = SelectObject(pGCPriv->hdcMem, pTilePriv->hBitmap); | |
768 | if (hbmpOrig == NULL) | |
769 | FatalError("winFillSpans - DRAWABLE_WINDOW - FillTiled - " | |
770 | "SelectObject () failed on pTilePriv->hBitmap\n"); | |
771 | ||
772 | while (iSpans--) { | |
773 | int width = pTile->drawable.width; | |
774 | ||
775 | fullX1 = pPoints->x; | |
776 | fullY1 = pPoints->y; | |
777 | fullX2 = fullX1 + (int) *piWidths; | |
778 | pPoints++; | |
779 | piWidths++; | |
780 | ||
781 | if (fullY1 < extentY1 || extentY2 <= fullY1) | |
782 | continue; | |
783 | ||
784 | if (fullX1 < extentX1) | |
785 | fullX1 = extentX1; | |
786 | if (fullX2 > extentX2) | |
787 | fullX2 = extentX2; | |
788 | ||
789 | if (fullX1 >= fullX2) | |
790 | continue; | |
791 | ||
792 | for (iX = fullX1; iX < fullX2; iX += width) { | |
793 | int xoffset; | |
794 | ||
795 | if ((iX + pTile->drawable.width) > fullX2) | |
796 | width = fullX2 - iX; | |
797 | else | |
798 | width = pTile->drawable.width; | |
799 | ||
800 | if (iX == fullX1) | |
801 | xoffset = | |
802 | (fullX1 - | |
803 | (pDrawable->x + | |
804 | (pGC->patOrg.x % pTile->drawable.width) - | |
805 | pTile->drawable.width)) % pTile->drawable.width; | |
806 | else | |
807 | xoffset = 0; | |
808 | ||
809 | if (xoffset + width > pTile->drawable.width) | |
810 | width = pTile->drawable.width - xoffset; | |
811 | ||
812 | BitBlt(pGCPriv->hdc, | |
813 | iX, fullY1, | |
814 | width, 1, | |
815 | pGCPriv->hdcMem, | |
816 | xoffset, | |
817 | (fullY1 - | |
818 | (pDrawable->y + | |
819 | (pGC->patOrg.y % pTile->drawable.height) - | |
820 | pTile->drawable.height)) % pTile->drawable.height, | |
821 | g_copyROP[pGC->alu]); | |
822 | } | |
823 | } | |
824 | ||
825 | /* Push the tile pixmap out of the memory HDC */ | |
826 | SelectObject(pGCPriv->hdcMem, hbmpOrig); | |
827 | break; | |
828 | ||
829 | default: | |
830 | ErrorF("winFillSpans - DRAWABLE_WINDOW - Unknown fillStyle\n"); | |
831 | break; | |
832 | } | |
833 | ||
834 | /* Reset clip region */ | |
835 | SelectClipRgn(pGCPriv->hdc, NULL); | |
836 | break; | |
837 | ||
838 | default: | |
839 | ErrorF("winFillSpans - Unknown drawable type\n"); | |
840 | break; | |
841 | } | |
842 | } |