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 /***********************************************************************
230 * color stretch -- deletes unused pixels
233 static void color_stretch(XImage
*sxi
, XImage
*dxi
,
234 short widthSrc
, short heightSrc
, short widthDest
, short heightDest
)
236 float deltax
, deltay
, sourcex
, sourcey
;
239 deltax
= (float)widthSrc
/widthDest
;
240 deltay
= (float)heightSrc
/heightDest
;
242 for (x
=0, sourcex
=0.0; x
<widthDest
; x
++, sourcex
+=deltax
)
243 for (y
=0, sourcey
=0.0; y
<heightDest
; y
++, sourcey
+=deltay
)
244 XPutPixel(dxi
, x
, y
, XGetPixel(sxi
, (int)sourcex
, (int)sourcey
));
248 /***********************************************************************
249 * StretchBlt (GDI.35)
251 * o StretchBlt is CPU intensive so we only call it if we have
252 * to. Checks are made to see if we can call BitBlt instead.
254 * o the stretching is slowish, some integer interpolation would
257 * o only black on white and color copy have been tested
259 BOOL
StretchBlt( HDC hdcDest
, short xDest
, short yDest
, short widthDest
, short heightDest
,
260 HDC hdcSrc
, short xSrc
, short ySrc
, short widthSrc
, short heightSrc
, DWORD rop
)
262 int xs1
, xs2
, ys1
, ys2
;
263 int xd1
, xd2
, yd1
, yd2
;
269 printf( "StretchBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
270 hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcSrc
, xSrc
,
271 ySrc
, widthSrc
, heightSrc
, rop
);
272 printf("StretchMode is %x\n",
273 ((DC
*)GDI_GetObjPtr(hdcDest
, DC_MAGIC
))->w
.stretchBltMode
);
276 if ((rop
& 0xcc0000) == ((rop
& 0x330000) << 2))
277 return PatBlt( hdcDest
, xDest
, yDest
, widthDest
, heightDest
, rop
);
279 /* don't stretch the bitmap unless we have to; if we don't,
280 * call BitBlt for a performance boost
283 if (widthSrc
== widthDest
&& heightSrc
== heightDest
) {
284 return BitBlt(hdcDest
, xDest
, yDest
, widthSrc
, heightSrc
,
285 hdcSrc
, xSrc
, ySrc
, rop
);
289 if ((rop
& 0x0f) != (rop
>> 4))
291 printf( "StretchBlt: Unimplemented ROP %02x\n", rop
);
295 dcDest
= (DC
*) GDI_GetObjPtr( hdcDest
, DC_MAGIC
);
296 if (!dcDest
) return FALSE
;
297 dcSrc
= (DC
*) GDI_GetObjPtr( hdcSrc
, DC_MAGIC
);
298 if (!dcSrc
) return FALSE
;
300 xs1
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
);
301 xs2
= dcSrc
->w
.DCOrgX
+ XLPTODP( dcSrc
, xSrc
+ widthSrc
);
302 ys1
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
);
303 ys2
= dcSrc
->w
.DCOrgY
+ YLPTODP( dcSrc
, ySrc
+ heightSrc
);
304 xd1
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
);
305 xd2
= dcDest
->w
.DCOrgX
+ XLPTODP( dcDest
, xDest
+ widthDest
);
306 yd1
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
);
307 yd2
= dcDest
->w
.DCOrgY
+ YLPTODP( dcDest
, yDest
+ heightDest
);
310 /* get a source and destination image so we can manipulate
314 sxi
= XGetImage(display
, dcSrc
->u
.x
.drawable
, xs1
, ys1
,
315 widthSrc
, heightSrc
, AllPlanes
, ZPixmap
);
316 dxi
= XCreateImage(display
, DefaultVisualOfScreen(screen
),
317 screenDepth
, ZPixmap
,
318 0, NULL
, widthDest
, heightDest
,
320 dxi
->data
= malloc(dxi
->bytes_per_line
* heightDest
);
322 stretchmode
= ((DC
*)GDI_GetObjPtr(hdcDest
, DC_MAGIC
))->w
.stretchBltMode
;
324 /* the actual stretching is done here, we'll try to use
325 * some interolation to get some speed out of it in
329 switch (stretchmode
) {
331 bonw_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
332 widthDest
, heightDest
);
335 wonb_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
336 widthDest
, heightDest
);
339 color_stretch(sxi
, dxi
, widthSrc
, heightSrc
,
340 widthDest
, heightDest
);
343 fprintf(stderr
, "StretchBlt: unknown stretchmode '%d'\n",
348 DC_SetupGCForText(dcDest
);
349 XSetFunction(display
, dcDest
->u
.x
.gc
, DC_XROPfunction
[rop
& 0x0f]);
350 XPutImage(display
, dcDest
->u
.x
.drawable
, dcDest
->u
.x
.gc
,
351 dxi
, 0, 0, MIN(xd1
,xd2
), MIN(yd1
,yd2
),
352 widthDest
, heightDest
);
354 /* now free the images we created */