2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
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:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
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.
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.
28 * Authors: Harold L Hunt II
29 * Alan Hourihane <alanh@fairlite.demon.co.uk>
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
37 extern void ROP16(HDC hdc
, int rop
);
39 #define TRANSLATE_COLOR(color) \
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); \
52 /* See Porting Layer Definition - p. 54 */
54 winFillSpansNativeGDI(DrawablePtr pDrawable
,
57 DDXPointPtr pPoints
, int *piWidths
, int fSorted
)
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
;
73 RegionPtr pClip
= pGC
->pCompositeClip
;
76 int extentX1
, extentX2
, extentY1
, extentY2
;
77 int fullX1
, fullX2
, fullY1
;
78 HRGN hrgn
= NULL
, combined
= NULL
;
80 nbox
= RegionNumRects(pClip
);
81 pbox
= RegionRects(pClip
);
86 combined
= CreateRectRgn(pbox
->x1
, pbox
->y1
, pbox
->x2
, pbox
->y2
);
91 hrgn
= CreateRectRgn(pbox
->x1
, pbox
->y1
, pbox
->x2
, pbox
->y2
);
92 CombineRgn(combined
, combined
, hrgn
, RGN_OR
);
98 pextent
= RegionExtents(pClip
);
99 extentX1
= pextent
->x1
;
100 extentY1
= pextent
->y1
;
101 extentX2
= pextent
->x2
;
102 extentY2
= pextent
->y2
;
104 /* Branch on the type of drawable we have */
105 switch (pDrawable
->type
) {
106 case DRAWABLE_PIXMAP
:
108 SelectClipRgn(pGCPriv
->hdcMem
, combined
);
109 DeleteObject(combined
);
112 /* Get a pixmap pointer from the drawable pointer, and fetch privates */
113 pPixmap
= (PixmapPtr
) pDrawable
;
114 pPixmapPriv
= winGetPixmapPriv(pPixmap
);
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
);
123 /* Branch on the fill type */
124 switch (pGC
->fillStyle
) {
127 ROP16(pGCPriv
->hdcMem
, pGC
->alu
);
129 if (pDrawable
->depth
== 1) {
130 if (pGC
->fgPixel
== 0)
131 hPenOrig
= SelectObject(pGCPriv
->hdcMem
,
132 GetStockObject(BLACK_PEN
));
134 hPenOrig
= SelectObject(pGCPriv
->hdcMem
,
135 GetStockObject(WHITE_PEN
));
140 hPen
= CreatePen(PS_SOLID
, 0, fg
);
141 hPenOrig
= SelectObject(pGCPriv
->hdcMem
, hPen
);
147 fullX2
= fullX1
+ (int) *piWidths
;
151 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
154 if (fullX1
< extentX1
)
156 if (fullX2
> extentX2
)
159 if (fullX1
>= fullX2
)
162 MoveToEx(pGCPriv
->hdcMem
, fullX1
, fullY1
, NULL
);
163 LineTo(pGCPriv
->hdcMem
, fullX2
, fullY1
);
166 SetROP2(pGCPriv
->hdcMem
, R2_COPYPEN
);
168 /* Give back the Pen */
169 SelectObject(pGCPriv
->hdcMem
, hPenOrig
);
171 if (pDrawable
->depth
!= 1)
175 case FillOpaqueStippled
:
177 pStipple
= pGC
->stipple
;
178 pStipplePriv
= winGetPixmapPriv(pStipple
);
180 /* Create a device-dependent bitmap for the stipple */
181 hBitmap
= CreateDIBitmap(pGCPriv
->hdcMem
,
182 (BITMAPINFOHEADER
*) pStipplePriv
->pbmih
,
184 pStipplePriv
->pbBits
,
185 (BITMAPINFO
*) pStipplePriv
->pbmih
,
188 /* Create a memory DC to hold the stipple */
189 hdcStipple
= CreateCompatibleDC(pGCPriv
->hdcMem
);
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");
197 /* Make a temporary copy of the foreground and background colors */
201 /* Translate the depth-dependent colors to Win32 COLORREFs */
204 SetTextColor(pGCPriv
->hdcMem
, fg
);
205 SetBkColor(pGCPriv
->hdcMem
, bg
);
208 int width
= pStipple
->drawable
.width
;
212 fullX2
= fullX1
+ (int) *piWidths
;
216 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
219 if (fullX1
< extentX1
)
221 if (fullX2
> extentX2
)
224 if (fullX1
>= fullX2
)
227 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
230 if ((iX
+ pStipple
->drawable
.width
) > fullX2
)
233 width
= pStipple
->drawable
.width
;
239 (pGC
->patOrg
.x
% pStipple
->drawable
.width
) -
240 pStipple
->drawable
.width
)) %
241 pStipple
->drawable
.width
;
245 if (xoffset
+ width
> pStipple
->drawable
.width
)
246 width
= pStipple
->drawable
.width
- xoffset
;
248 BitBlt(pGCPriv
->hdcMem
,
255 (pGC
->patOrg
.y
% pStipple
->drawable
.height
) -
256 pStipple
->drawable
.height
)) %
257 pStipple
->drawable
.height
, g_copyROP
[pGC
->alu
]);
261 /* Clear the stipple HDC */
262 SelectObject(hdcStipple
, hbmpOrigStipple
);
263 DeleteDC(hdcStipple
);
265 /* Delete the device dependent stipple bitmap */
266 DeleteObject(hBitmap
);
271 pStipple
= pGC
->stipple
;
272 pStipplePriv
= winGetPixmapPriv(pStipple
);
274 /* Create a device-dependent bitmap for the stipple */
275 hBitmap
= CreateDIBitmap(pGCPriv
->hdcMem
,
276 (BITMAPINFOHEADER
*) pStipplePriv
->pbmih
,
278 pStipplePriv
->pbBits
,
279 (BITMAPINFO
*) pStipplePriv
->pbmih
,
282 /* Create a memory DC to hold the stipple */
283 hdcStipple
= CreateCompatibleDC(pGCPriv
->hdcMem
);
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");
291 /* Make a temporary copy of the foreground and background colors */
295 /* Translate the depth-dependent colors to Win32 COLORREFs */
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..
303 if (pGC
->bgPixel
!= -1 && pGC
->fgPixel
!= -1) {
304 SetTextColor(pGCPriv
->hdcMem
, fg
);
305 SetBkColor(pGCPriv
->hdcMem
, bg
);
308 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
309 hdcStipple
, 0, 0, 0x330008);
311 else if (pGC
->bgPixel
== -1) {
312 SetTextColor(pGCPriv
->hdcMem
, fg
);
313 SetBkMode(pGCPriv
->hdcMem
, TRANSPARENT
);
316 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
317 hdcStipple
, 0, 0, 0x330008);
319 else if (pGC
->fgPixel
== -1) {
320 SetTextColor(pGCPriv
->hdcMem
, bg
);
321 SetBkMode(pGCPriv
->hdcMem
, TRANSPARENT
);
325 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
326 hdcStipple
, 0, 0, 0x330008);
331 int width
= pStipple
->drawable
.width
;
335 fullX2
= fullX1
+ (int) *piWidths
;
339 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
342 if (fullX1
< extentX1
)
344 if (fullX2
> extentX2
)
347 if (fullX1
>= fullX2
)
350 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
353 if ((iX
+ pStipple
->drawable
.width
) > fullX2
)
356 width
= pStipple
->drawable
.width
;
362 (pGC
->patOrg
.x
% pStipple
->drawable
.width
) -
363 pStipple
->drawable
.width
)) %
364 pStipple
->drawable
.width
;
368 if (xoffset
+ width
> pStipple
->drawable
.width
)
369 width
= pStipple
->drawable
.width
- xoffset
;
371 BitBlt(pGCPriv
->hdcMem
,
378 (pGC
->patOrg
.y
% pStipple
->drawable
.height
) -
379 pStipple
->drawable
.height
)) %
380 pStipple
->drawable
.height
, g_copyROP
[pGC
->alu
]);
384 /* Clear the stipple HDC */
385 SelectObject(hdcStipple
, hbmpOrigStipple
);
386 DeleteDC(hdcStipple
);
388 /* Delete the device dependent stipple bitmap */
389 DeleteObject(hBitmap
);
391 /* Restore the background mode */
392 SetBkMode(pGCPriv
->hdcMem
, OPAQUE
);
397 /* Get a pixmap pointer from the tile pointer, and fetch privates */
398 pTile
= (PixmapPtr
) pGC
->tile
.pixmap
;
399 pTilePriv
= winGetPixmapPriv(pTile
);
401 /* Create a memory DC to hold the tile */
402 hdcTile
= CreateCompatibleDC(pGCPriv
->hdcMem
);
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");
411 int width
= pTile
->drawable
.width
;
415 fullX2
= fullX1
+ (int) *piWidths
;
419 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
422 if (fullX1
< extentX1
)
424 if (fullX2
> extentX2
)
427 if (fullX1
>= fullX2
)
430 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
433 if ((iX
+ pTile
->drawable
.width
) > fullX2
)
436 width
= pTile
->drawable
.width
;
442 (pGC
->patOrg
.x
% pTile
->drawable
.width
) -
443 pTile
->drawable
.width
)) % pTile
->drawable
.width
;
447 if (xoffset
+ width
> pTile
->drawable
.width
)
448 width
= pTile
->drawable
.width
- xoffset
;
450 BitBlt(pGCPriv
->hdcMem
,
457 (pGC
->patOrg
.y
% pTile
->drawable
.height
) -
458 pTile
->drawable
.height
)) % pTile
->drawable
.height
,
459 g_copyROP
[pGC
->alu
]);
463 /* Push the tile pixmap out of the memory HDC */
464 SelectObject(hdcTile
, hbmpOrig
);
466 /* Delete the tile */
471 ErrorF("winFillSpans - DRAWABLE_PIXMAP - Unknown fillStyle\n");
475 /* Reset clip region */
476 SelectClipRgn(pGCPriv
->hdcMem
, NULL
);
478 /* Push the drawable pixmap out of the GC HDC */
479 SelectObject(pGCPriv
->hdcMem
, hbmpOrig
);
482 case DRAWABLE_WINDOW
:
484 SelectClipRgn(pGCPriv
->hdc
, combined
);
485 DeleteObject(combined
);
488 /* Branch on fill style */
489 switch (pGC
->fillStyle
) {
492 ROP16(pGCPriv
->hdc
, pGC
->alu
);
494 if (pDrawable
->depth
== 1) {
495 if (pGC
->fgPixel
== 0)
496 hPenOrig
= SelectObject(pGCPriv
->hdc
,
497 GetStockObject(BLACK_PEN
));
499 hPenOrig
= SelectObject(pGCPriv
->hdc
,
500 GetStockObject(WHITE_PEN
));
505 hPen
= CreatePen(PS_SOLID
, 0, fg
);
506 hPenOrig
= SelectObject(pGCPriv
->hdc
, hPen
);
512 fullX2
= fullX1
+ (int) *piWidths
;
516 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
519 if (fullX1
< extentX1
)
521 if (fullX2
> extentX2
)
524 if (fullX1
>= fullX2
)
527 MoveToEx(pGCPriv
->hdc
, fullX1
, fullY1
, NULL
);
528 LineTo(pGCPriv
->hdc
, fullX2
, fullY1
);
531 SetROP2(pGCPriv
->hdc
, R2_COPYPEN
);
533 /* Give back the Brush */
534 SelectObject(pGCPriv
->hdc
, hPenOrig
);
536 if (pDrawable
->depth
!= 1)
540 case FillOpaqueStippled
:
542 pStipple
= pGC
->stipple
;
543 pStipplePriv
= winGetPixmapPriv(pStipple
);
545 /* Create a device-dependent bitmap for the stipple */
546 hBitmap
= CreateDIBitmap(pGCPriv
->hdc
,
547 (BITMAPINFOHEADER
*) pStipplePriv
->pbmih
,
549 pStipplePriv
->pbBits
,
550 (BITMAPINFO
*) pStipplePriv
->pbmih
,
553 /* Create a memory DC to hold the stipple */
554 hdcStipple
= CreateCompatibleDC(pGCPriv
->hdc
);
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");
562 /* Make a temporary copy of the foreground and background colors */
566 /* Translate the depth-dependent colors to Win32 COLORREFs */
569 SetTextColor(pGCPriv
->hdc
, fg
);
570 SetBkColor(pGCPriv
->hdc
, bg
);
573 int width
= pStipple
->drawable
.width
;
577 fullX2
= fullX1
+ (int) *piWidths
;
581 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
584 if (fullX1
< extentX1
)
586 if (fullX2
> extentX2
)
589 if (fullX1
>= fullX2
)
592 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
595 if ((iX
+ pStipple
->drawable
.width
) > fullX2
)
598 width
= pStipple
->drawable
.width
;
604 (pGC
->patOrg
.x
% pStipple
->drawable
.width
) -
605 pStipple
->drawable
.width
)) %
606 pStipple
->drawable
.width
;
610 if (xoffset
+ width
> pStipple
->drawable
.width
)
611 width
= pStipple
->drawable
.width
- xoffset
;
620 (pGC
->patOrg
.y
% pStipple
->drawable
.height
) -
621 pStipple
->drawable
.height
)) %
622 pStipple
->drawable
.height
, g_copyROP
[pGC
->alu
]);
626 /* Clear the stipple HDC */
627 SelectObject(hdcStipple
, hbmpOrigStipple
);
628 DeleteDC(hdcStipple
);
630 /* Delete the device dependent stipple bitmap */
631 DeleteObject(hBitmap
);
636 pStipple
= pGC
->stipple
;
637 pStipplePriv
= winGetPixmapPriv(pStipple
);
639 /* Create a device-dependent bitmap for the stipple */
640 hBitmap
= CreateDIBitmap(pGCPriv
->hdcMem
,
641 (BITMAPINFOHEADER
*) pStipplePriv
->pbmih
,
643 pStipplePriv
->pbBits
,
644 (BITMAPINFO
*) pStipplePriv
->pbmih
,
647 /* Create a memory DC to hold the stipple */
648 hdcStipple
= CreateCompatibleDC(pGCPriv
->hdc
);
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");
656 /* Make a temporary copy of the foreground and background colors */
660 /* Translate the depth-dependent colors to Win32 COLORREFs */
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..
668 if (pGC
->bgPixel
!= -1 && pGC
->fgPixel
!= -1) {
669 SetTextColor(pGCPriv
->hdc
, fg
);
670 SetBkColor(pGCPriv
->hdc
, bg
);
673 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
674 hdcStipple
, 0, 0, 0x330008);
676 else if (pGC
->bgPixel
== -1) {
677 SetTextColor(pGCPriv
->hdc
, fg
);
678 SetBkMode(pGCPriv
->hdc
, TRANSPARENT
);
681 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
682 hdcStipple
, 0, 0, 0x330008);
684 else if (pGC
->fgPixel
== -1) {
685 SetTextColor(pGCPriv
->hdc
, bg
);
686 SetBkMode(pGCPriv
->hdc
, TRANSPARENT
);
690 pStipple
->drawable
.width
, pStipple
->drawable
.height
,
691 hdcStipple
, 0, 0, 0x330008);
696 int width
= pStipple
->drawable
.width
;
700 fullX2
= fullX1
+ (int) *piWidths
;
704 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
707 if (fullX1
< extentX1
)
709 if (fullX2
> extentX2
)
712 if (fullX1
>= fullX2
)
715 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
718 if ((iX
+ pStipple
->drawable
.width
) > fullX2
)
721 width
= pStipple
->drawable
.width
;
727 (pGC
->patOrg
.x
% pStipple
->drawable
.width
) -
728 pStipple
->drawable
.width
)) %
729 pStipple
->drawable
.width
;
733 if (xoffset
+ width
> pStipple
->drawable
.width
)
734 width
= pStipple
->drawable
.width
- xoffset
;
743 (pGC
->patOrg
.y
% pStipple
->drawable
.height
) -
744 pStipple
->drawable
.height
)) %
745 pStipple
->drawable
.height
, g_copyROP
[pGC
->alu
]);
749 /* Clear the stipple HDC */
750 SelectObject(hdcStipple
, hbmpOrigStipple
);
751 DeleteDC(hdcStipple
);
753 /* Delete the device dependent stipple bitmap */
754 DeleteObject(hBitmap
);
756 /* Restore the background mode */
757 SetBkMode(pGCPriv
->hdc
, OPAQUE
);
762 /* Get a pixmap pointer from the tile pointer, and fetch privates */
763 pTile
= (PixmapPtr
) pGC
->tile
.pixmap
;
764 pTilePriv
= winGetPixmapPriv(pTile
);
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");
773 int width
= pTile
->drawable
.width
;
777 fullX2
= fullX1
+ (int) *piWidths
;
781 if (fullY1
< extentY1
|| extentY2
<= fullY1
)
784 if (fullX1
< extentX1
)
786 if (fullX2
> extentX2
)
789 if (fullX1
>= fullX2
)
792 for (iX
= fullX1
; iX
< fullX2
; iX
+= width
) {
795 if ((iX
+ pTile
->drawable
.width
) > fullX2
)
798 width
= pTile
->drawable
.width
;
804 (pGC
->patOrg
.x
% pTile
->drawable
.width
) -
805 pTile
->drawable
.width
)) % pTile
->drawable
.width
;
809 if (xoffset
+ width
> pTile
->drawable
.width
)
810 width
= pTile
->drawable
.width
- xoffset
;
819 (pGC
->patOrg
.y
% pTile
->drawable
.height
) -
820 pTile
->drawable
.height
)) % pTile
->drawable
.height
,
821 g_copyROP
[pGC
->alu
]);
825 /* Push the tile pixmap out of the memory HDC */
826 SelectObject(pGCPriv
->hdcMem
, hbmpOrig
);
830 ErrorF("winFillSpans - DRAWABLE_WINDOW - Unknown fillStyle\n");
834 /* Reset clip region */
835 SelectClipRgn(pGCPriv
->hdc
, NULL
);
839 ErrorF("winFillSpans - Unknown drawable type\n");