2 * GDI bit-blit operations
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Intrinsic.h>
16 extern const int DC_XROPfunction
[];
18 #define MIN(a,b) ((a) < (b) ? (a) : (b))
19 #define MAX(a,b) ((a) > (b) ? (a) : (b))
22 /***********************************************************************
25 BOOL
PatBlt( HDC hdc
, short left
, short top
,
26 short width
, short height
, DWORD rop
)
30 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
31 if (!dc
) return FALSE
;
33 printf( "PatBlt: %d %d,%d %dx%d %06x\n",
34 hdc
, left
, top
, width
, height
, rop
);
38 if (!DC_SetupGCForBrush( dc
)) rop
&= 0x0f;
39 else rop
= (rop
& 0x03) | ((rop
>> 4) & 0x0c);
40 XSetFunction( XT_display
, dc
->u
.x
.gc
, DC_XROPfunction
[rop
] );
42 x1
= dc
->w
.DCOrgX
+ XLPTODP( dc
, left
);
43 x2
= dc
->w
.DCOrgX
+ XLPTODP( dc
, left
+ width
);
44 y1
= dc
->w
.DCOrgY
+ YLPTODP( dc
, top
);
45 y2
= dc
->w
.DCOrgY
+ YLPTODP( dc
, top
+ height
);
46 XFillRectangle( XT_display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
47 MIN(x1
,x2
), MIN(y1
,y2
), abs(x2
-x1
), abs(y2
-y1
) );
52 /***********************************************************************
55 BOOL
BitBlt( HDC hdcDest
, short xDest
, short yDest
, short width
, short height
,
56 HDC hdcSrc
, short xSrc
, short ySrc
, DWORD rop
)
58 int xs1
, xs2
, ys1
, ys2
;
59 int xd1
, xd2
, yd1
, yd2
;
63 printf( "BitBlt: %d %d,%d %dx%d %d %d,%d %08x\n",
64 hdcDest
, xDest
, yDest
, width
, height
, hdcSrc
, xSrc
, ySrc
, rop
);
67 if ((rop
& 0xcc0000) == ((rop
& 0x330000) << 2))
68 return PatBlt( hdcDest
, xDest
, yDest
, width
, height
, rop
);
71 if ((rop
& 0x0f) != (rop
>> 4))
73 printf( "BitBlt: Unimplemented ROP %02x\n", rop
);
77 dcDest
= (DC
*) GDI_GetObjPtr( hdcDest
, DC_MAGIC
);
78 if (!dcDest
) return FALSE
;
79 dcSrc
= (DC
*) GDI_GetObjPtr( hdcSrc
, DC_MAGIC
);
80 if (!dcSrc
) return FALSE
;
82 xs1
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
);
83 xs2
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
+ width
);
84 ys1
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
);
85 ys2
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
+ height
);
86 xd1
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
);
87 xd2
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
+ width
);
88 yd1
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
);
89 yd2
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
+ height
);
91 if ((abs(xs2
-xs1
) != abs(xd2
-xd1
)) || (abs(ys2
-ys1
) != abs(yd2
-yd1
)))
92 return FALSE
; /* Should call StretchBlt here */
94 DC_SetupGCForText( dcDest
);
95 XSetFunction( XT_display
, dcDest
->u
.x
.gc
, DC_XROPfunction
[rop
& 0x0f] );
96 if (dcSrc
->w
.bitsPerPixel
== dcDest
->w
.bitsPerPixel
)
98 XCopyArea( XT_display
, dcSrc
->u
.x
.drawable
,
99 dcDest
->u
.x
.drawable
, dcDest
->u
.x
.gc
,
100 MIN(xs1
,xs2
), MIN(ys1
,ys2
), abs(xs2
-xs1
), abs(ys2
-ys1
),
101 MIN(xd1
,xd2
), MIN(yd1
,yd2
) );
105 if (dcSrc
->w
.bitsPerPixel
!= 1) return FALSE
;
106 XCopyPlane( XT_display
, dcSrc
->u
.x
.drawable
,
107 dcDest
->u
.x
.drawable
, dcDest
->u
.x
.gc
,
108 MIN(xs1
,xs2
), MIN(ys1
,ys2
), abs(xs2
-xs1
), abs(ys2
-ys1
),
109 MIN(xd1
,xd2
), MIN(yd1
,yd2
), 1 );
116 /***********************************************************************
117 * black on white stretch -- favors color pixels over white
120 static void bonw_stretch(XImage
*sxi
, XImage
*dxi
,
121 short widthSrc
, short heightSrc
, short widthDest
, short heightDest
)
123 float deltax
, deltay
, sourcex
, sourcey
, oldsourcex
, oldsourcey
;
126 int totalx
, totaly
, xavgwhite
, yavgwhite
;
130 deltax
= (float)widthSrc
/widthDest
;
131 deltay
= (float)heightSrc
/heightDest
;
132 whitep
= WhitePixel(display
, DefaultScreen(display
));
135 for (x
=0, sourcex
=0.0; x
<widthDest
;
136 x
++, oldsourcex
=sourcex
, sourcex
+=deltax
) {
141 for (i
=(int)oldsourcex
; i
<=endx
; i
++)
142 if (XGetPixel(sxi
, i
, (int)sourcey
) == whitep
)
144 xavgwhite
= (totalx
> (int)(deltax
/ 2.0));
150 for (y
=0, sourcey
=0.0; y
<heightDest
;
151 y
++, oldsourcey
=sourcey
, sourcey
+=deltay
) {
156 for (i
=(int)oldsourcey
; i
<=endy
; i
++)
157 if (XGetPixel(sxi
, (int)sourcex
, i
) == whitep
)
159 yavgwhite
= (totaly
> ((int)deltay
/ 2));
163 if (xavgwhite
&& yavgwhite
)
164 XPutPixel(dxi
, x
, y
, whitep
);
166 XPutPixel(dxi
, x
, y
, XGetPixel(sxi
, (int)sourcex
, (int)sourcey
));
168 } /* for all y in dest */
169 } /* for all x in dest */
173 /***********************************************************************
174 * white on black stretch -- favors color pixels over black
177 static void wonb_stretch(XImage
*sxi
, XImage
*dxi
,
178 short widthSrc
, short heightSrc
, short widthDest
, short heightDest
)
180 float deltax
, deltay
, sourcex
, sourcey
, oldsourcex
, oldsourcey
;
183 int totalx
, totaly
, xavgblack
, yavgblack
;
187 deltax
= (float)widthSrc
/widthDest
;
188 deltay
= (float)heightSrc
/heightDest
;
189 blackp
= WhitePixel(display
, DefaultScreen(display
));
192 for (x
=0, sourcex
=0.0; x
<widthDest
;
193 x
++, oldsourcex
=sourcex
, sourcex
+=deltax
) {
198 for (i
=(int)oldsourcex
; i
<=endx
; i
++)
199 if (XGetPixel(sxi
, i
, (int)sourcey
) == blackp
)
201 xavgblack
= (totalx
> (int)(deltax
/ 2.0));
207 for (y
=0, sourcey
=0.0; y
<heightDest
;
208 y
++, oldsourcey
=sourcey
, sourcey
+=deltay
) {
213 for (i
=(int)oldsourcey
; i
<=endy
; i
++)
214 if (XGetPixel(sxi
, (int)sourcex
, i
) == blackp
)
216 yavgblack
= (totaly
> ((int)deltay
/ 2));
220 if (xavgblack
&& yavgblack
)
221 XPutPixel(dxi
, x
, y
, blackp
);
223 XPutPixel(dxi
, x
, y
, XGetPixel(sxi
, (int)sourcex
, (int)sourcey
));
225 } /* for all y in dest */
226 } /* for all x in dest */
229 /* We use the 32-bit to 64-bit multiply and 64-bit to 32-bit divide of the */
230 /* 386 (which gcc doesn't know well enough) to efficiently perform integer */
231 /* scaling without having to worry about overflows. */
233 /* ##### muldiv64() borrowed from svgalib 1.03 ##### */
234 static inline int muldiv64( int m1
, int m2
, int d
)
236 /* int32 * int32 -> int64 / int32 -> int32 */
242 : "=a" (result
) /* out */
243 : "a" (m1
), "d" (m2
), "g" (d
) /* in */
244 : "ax", "dx" /* mod */
252 /***********************************************************************
253 * color stretch -- deletes unused pixels
256 static void color_stretch(XImage
*sxi
, XImage
*dxi
,
257 short widthSrc
, short heightSrc
, short widthDest
, short heightDest
)
259 register int x
, y
, sx
, sy
, xfactor
, yfactor
;
261 xfactor
= muldiv64(widthSrc
, 65536, widthDest
);
262 yfactor
= muldiv64(heightSrc
, 65536, heightDest
);
266 for (y
= 0; y
< heightDest
;)
268 int sourcey
= sy
>> 16;
270 for (x
= 0; x
< widthDest
; x
++) {
271 XPutPixel(dxi
, x
, y
, XGetPixel(sxi
, sx
>> 16, sourcey
));
275 while (y
< heightDest
) {
281 if ((sy
>> 16) != sourcey
)
284 /* vertical stretch => copy previous line */
288 for (x
= 0; x
< widthDest
; x
++)
289 XPutPixel(dxi
, x
, y
, XGetPixel(dxi
, x
, py
));
295 /***********************************************************************
296 * StretchBlt (GDI.35)
298 * o StretchBlt is CPU intensive so we only call it if we have
299 * to. Checks are made to see if we can call BitBlt instead.
301 * o the stretching is slowish, some integer interpolation would
304 * o only black on white and color copy have been tested
306 BOOL
StretchBlt( HDC hdcDest
, short xDest
, short yDest
, short widthDest
, short heightDest
,
307 HDC hdcSrc
, short xSrc
, short ySrc
, short widthSrc
, short heightSrc
, DWORD rop
)
309 int xs1
, xs2
, ys1
, ys2
;
310 int xd1
, xd2
, yd1
, yd2
;
316 fprintf(stderr
, "StretchBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
317 hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcSrc
, xSrc
,
318 ySrc
, widthSrc
, heightSrc
, rop
);
319 printf("StretchMode is %x\n",
320 ((DC
*)GDI_GetObjPtr(hdcDest
, DC_MAGIC
))->w
.stretchBltMode
);
323 if ((rop
& 0xcc0000) == ((rop
& 0x330000) << 2))
324 return PatBlt( hdcDest
, xDest
, yDest
, widthDest
, heightDest
, rop
);
326 /* don't stretch the bitmap unless we have to; if we don't,
327 * call BitBlt for a performance boost
330 if (widthSrc
== widthDest
&& heightSrc
== heightDest
) {
331 return BitBlt(hdcDest
, xDest
, yDest
, widthSrc
, heightSrc
,
332 hdcSrc
, xSrc
, ySrc
, rop
);
336 if ((rop
& 0x0f) != (rop
>> 4))
338 printf( "StretchBlt: Unimplemented ROP %02x\n", rop
);
342 dcDest
= (DC
*) GDI_GetObjPtr( hdcDest
, DC_MAGIC
);
343 if (!dcDest
) return FALSE
;
344 dcSrc
= (DC
*) GDI_GetObjPtr( hdcSrc
, DC_MAGIC
);
345 if (!dcSrc
) return FALSE
;
347 xs1
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
);
348 xs2
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
+ widthSrc
);
349 ys1
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
);
350 ys2
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
+ heightSrc
);
351 xd1
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
);
352 xd2
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
+ widthDest
);
353 yd1
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
);
354 yd2
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
+ heightDest
);
357 /* get a source and destination image so we can manipulate
361 sxi
= XGetImage(display
, dcSrc
->u
.x
.drawable
, xs1
, ys1
,
362 widthSrc
, heightSrc
, AllPlanes
, ZPixmap
);
363 dxi
= XCreateImage(display
, DefaultVisualOfScreen(screen
),
364 screenDepth
, ZPixmap
,
365 0, NULL
, widthDest
, heightDest
,
367 dxi
->data
= malloc(dxi
->bytes_per_line
* heightDest
);
369 stretchmode
= ((DC
*)GDI_GetObjPtr(hdcDest
, DC_MAGIC
))->w
.stretchBltMode
;
371 /* the actual stretching is done here, we'll try to use
372 * some interolation to get some speed out of it in
376 switch (stretchmode
) {
378 color_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
379 widthDest
, heightDest
);
380 /* bonw_stretch(sxi, dxi, widthSrc, heightSrc,
381 widthDest, heightDest);
384 color_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
385 widthDest
, heightDest
);
386 /* wonb_stretch(sxi, dxi, widthSrc, heightSrc,
387 widthDest, heightDest);
390 color_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
391 widthDest
, heightDest
);
394 fprintf(stderr
, "StretchBlt: unknown stretchmode '%d'\n",
399 DC_SetupGCForText(dcDest
);
400 XSetFunction(display
, dcDest
->u
.x
.gc
, DC_XROPfunction
[rop
& 0x0f]);
401 XPutImage(display
, dcDest
->u
.x
.drawable
, dcDest
->u
.x
.gc
,
402 dxi
, 0, 0, MIN(xd1
,xd2
), MIN(yd1
,yd2
),
403 widthDest
, heightDest
);
405 /* now free the images we created */