2 * GDI bit-blit operations
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Intrinsic.h>
17 extern const int DC_XROPfunction[];
19 #define MIN(a,b) ((a) < (b) ? (a) : (b))
20 #define MAX(a,b) ((a) > (b) ? (a) : (b))
23 /***********************************************************************
26 BOOL PatBlt( HDC hdc, short left, short top,
27 short width, short height, DWORD rop)
31 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
34 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
35 if (!dc) return FALSE;
36 MF_MetaParam6(dc, META_PATBLT, left, top, width, height,
37 HIWORD(rop), LOWORD(rop));
42 printf( "PatBlt: %d %d,%d %dx%d %06x\n",
43 hdc, left, top, width, height, rop );
47 if (!DC_SetupGCForBrush( dc )) rop &= 0x0f;
48 else rop = (rop & 0x03) | ((rop >> 4) & 0x0c);
49 XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[rop] );
51 x1 = dc->w.DCOrgX + XLPTODP( dc, left );
52 x2 = dc->w.DCOrgX + XLPTODP( dc, left + width );
53 y1 = dc->w.DCOrgY + YLPTODP( dc, top );
54 y2 = dc->w.DCOrgY + YLPTODP( dc, top + height );
55 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
56 MIN(x1,x2), MIN(y1,y2), abs(x2-x1), abs(y2-y1) );
61 /***********************************************************************
64 BOOL BitBlt( HDC hdcDest, short xDest, short yDest, short width, short height,
65 HDC hdcSrc, short xSrc, short ySrc, DWORD rop )
67 int xs1, xs2, ys1, ys2;
68 int xd1, xd2, yd1, yd2;
72 printf( "BitBlt: %d %d,%d %dx%d %d %d,%d %08x\n",
73 hdcDest, xDest, yDest, width, height, hdcSrc, xSrc, ySrc, rop );
75 if (width == 0 || height == 0) return FALSE;
76 if ((rop & 0xcc0000) == ((rop & 0x330000) << 2))
77 return PatBlt( hdcDest, xDest, yDest, width, height, rop );
80 if ((rop & 0x0f) != (rop >> 4))
82 printf( "BitBlt: Unimplemented ROP %02x\n", rop );
86 dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
87 if (!dcDest) return FALSE;
88 dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
89 if (!dcSrc) return FALSE;
91 xs1 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc );
92 xs2 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc + width );
93 ys1 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc );
94 ys2 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc + height );
95 xd1 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest );
96 xd2 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest + width );
97 yd1 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest );
98 yd2 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest + height );
100 if ((abs(xs2-xs1) != abs(xd2-xd1)) || (abs(ys2-ys1) != abs(yd2-yd1)))
101 return FALSE; /* Should call StretchBlt here */
103 DC_SetupGCForText( dcDest );
104 XSetFunction( XT_display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f] );
105 if (dcSrc->w.bitsPerPixel == dcDest->w.bitsPerPixel)
107 XCopyArea( XT_display, dcSrc->u.x.drawable,
108 dcDest->u.x.drawable, dcDest->u.x.gc,
109 MIN(xs1,xs2), MIN(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
110 MIN(xd1,xd2), MIN(yd1,yd2) );
114 if (dcSrc->w.bitsPerPixel != 1) return FALSE;
115 XCopyPlane( XT_display, dcSrc->u.x.drawable,
116 dcDest->u.x.drawable, dcDest->u.x.gc,
117 MIN(xs1,xs2), MIN(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
118 MIN(xd1,xd2), MIN(yd1,yd2), 1 );
125 /***********************************************************************
126 * black on white stretch -- favors color pixels over white
129 static void bonw_stretch(XImage *sxi, XImage *dxi,
130 short widthSrc, short heightSrc, short widthDest, short heightDest)
132 float deltax, deltay, sourcex, sourcey, oldsourcex, oldsourcey;
135 int totalx, totaly, xavgwhite, yavgwhite;
139 deltax = (float)widthSrc/widthDest;
140 deltay = (float)heightSrc/heightDest;
141 whitep = WhitePixel(display, DefaultScreen(display));
144 for (x=0, sourcex=0.0; x<widthDest;
145 x++, oldsourcex=sourcex, sourcex+=deltax) {
150 for (i=(int)oldsourcex; i<=endx; i++)
151 if (XGetPixel(sxi, i, (int)sourcey) == whitep)
153 xavgwhite = (totalx > (int)(deltax / 2.0));
159 for (y=0, sourcey=0.0; y<heightDest;
160 y++, oldsourcey=sourcey, sourcey+=deltay) {
165 for (i=(int)oldsourcey; i<=endy; i++)
166 if (XGetPixel(sxi, (int)sourcex, i) == whitep)
168 yavgwhite = (totaly > ((int)deltay / 2));
172 if (xavgwhite && yavgwhite)
173 XPutPixel(dxi, x, y, whitep);
175 XPutPixel(dxi, x, y, XGetPixel(sxi, (int)sourcex, (int)sourcey));
177 } /* for all y in dest */
178 } /* for all x in dest */
182 /***********************************************************************
183 * white on black stretch -- favors color pixels over black
186 static void wonb_stretch(XImage *sxi, XImage *dxi,
187 short widthSrc, short heightSrc, short widthDest, short heightDest)
189 float deltax, deltay, sourcex, sourcey, oldsourcex, oldsourcey;
192 int totalx, totaly, xavgblack, yavgblack;
196 deltax = (float)widthSrc/widthDest;
197 deltay = (float)heightSrc/heightDest;
198 blackp = WhitePixel(display, DefaultScreen(display));
201 for (x=0, sourcex=0.0; x<widthDest;
202 x++, oldsourcex=sourcex, sourcex+=deltax) {
207 for (i=(int)oldsourcex; i<=endx; i++)
208 if (XGetPixel(sxi, i, (int)sourcey) == blackp)
210 xavgblack = (totalx > (int)(deltax / 2.0));
216 for (y=0, sourcey=0.0; y<heightDest;
217 y++, oldsourcey=sourcey, sourcey+=deltay) {
222 for (i=(int)oldsourcey; i<=endy; i++)
223 if (XGetPixel(sxi, (int)sourcex, i) == blackp)
225 yavgblack = (totaly > ((int)deltay / 2));
229 if (xavgblack && yavgblack)
230 XPutPixel(dxi, x, y, blackp);
232 XPutPixel(dxi, x, y, XGetPixel(sxi, (int)sourcex, (int)sourcey));
234 } /* for all y in dest */
235 } /* for all x in dest */
238 /* We use the 32-bit to 64-bit multiply and 64-bit to 32-bit divide of the */
239 /* 386 (which gcc doesn't know well enough) to efficiently perform integer */
240 /* scaling without having to worry about overflows. */
242 /* ##### muldiv64() borrowed from svgalib 1.03 ##### */
243 static inline int muldiv64( int m1, int m2, int d )
245 /* int32 * int32 -> int64 / int32 -> int32 */
251 : "=a" (result) /* out */
252 : "a" (m1), "d" (m2), "g" (d) /* in */
253 : "ax", "dx" /* mod */
261 /***********************************************************************
262 * color stretch -- deletes unused pixels
265 static void color_stretch(XImage *sxi, XImage *dxi,
266 short widthSrc, short heightSrc, short widthDest, short heightDest)
268 register int x, y, sx, sy, xfactor, yfactor;
270 xfactor = muldiv64(widthSrc, 65536, widthDest);
271 yfactor = muldiv64(heightSrc, 65536, heightDest);
275 for (y = 0; y < heightDest;)
277 int sourcey = sy >> 16;
279 for (x = 0; x < widthDest; x++) {
280 XPutPixel(dxi, x, y, XGetPixel(sxi, sx >> 16, sourcey));
284 while (y < heightDest) {
290 if ((sy >> 16) != sourcey)
293 /* vertical stretch => copy previous line */
297 for (x = 0; x < widthDest; x++)
298 XPutPixel(dxi, x, y, XGetPixel(dxi, x, py));
304 /***********************************************************************
305 * StretchBlt (GDI.35)
307 * o StretchBlt is CPU intensive so we only call it if we have
308 * to. Checks are made to see if we can call BitBlt instead.
310 * o the stretching is slowish, some integer interpolation would
313 * o only black on white and color copy have been tested
315 BOOL StretchBlt( HDC hdcDest, short xDest, short yDest, short widthDest, short heightDest,
316 HDC hdcSrc, short xSrc, short ySrc, short widthSrc, short heightSrc, DWORD rop )
318 int xs1, xs2, ys1, ys2;
319 int xd1, xd2, yd1, yd2;
326 fprintf(stderr, "StretchBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
327 hdcDest, xDest, yDest, widthDest, heightDest, hdcSrc, xSrc,
328 ySrc, widthSrc, heightSrc, rop );
329 printf("StretchMode is %x\n",
330 ((DC *)GDI_GetObjPtr(hdcDest, DC_MAGIC))->w.stretchBltMode);
333 if (widthDest == 0 || heightDest == 0) return FALSE;
334 if (widthSrc == 0 || heightSrc == 0) return FALSE;
335 if ((rop & 0xcc0000) == ((rop & 0x330000) << 2))
336 return PatBlt( hdcDest, xDest, yDest, widthDest, heightDest, rop );
338 /* don't stretch the bitmap unless we have to; if we don't,
339 * call BitBlt for a performance boost
342 if (widthSrc == widthDest && heightSrc == heightDest) {
343 return BitBlt(hdcDest, xDest, yDest, widthSrc, heightSrc,
344 hdcSrc, xSrc, ySrc, rop);
348 if ((rop & 0x0f) != (rop >> 4))
350 printf( "StretchBlt: Unimplemented ROP %02x\n", rop );
354 dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
355 if (!dcDest) return FALSE;
356 dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
357 if (!dcSrc) return FALSE;
359 xs1 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc );
360 xs2 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc + widthSrc );
361 ys1 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc );
362 ys2 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc + heightSrc );
363 xd1 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest );
364 xd2 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest + widthDest );
365 yd1 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest );
366 yd2 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest + heightDest );
369 /* get a source and destination image so we can manipulate
373 sxi = XGetImage(display, dcSrc->u.x.drawable, xs1, ys1,
374 widthSrc, heightSrc, AllPlanes, ZPixmap);
375 dxi = XCreateImage(display, DefaultVisualOfScreen(screen),
376 screenDepth, ZPixmap,
377 0, NULL, widthDest, heightDest,
379 dxi->data = malloc(dxi->bytes_per_line * heightDest);
381 stretchmode = ((DC *)GDI_GetObjPtr(hdcDest, DC_MAGIC))->w.stretchBltMode;
383 /* the actual stretching is done here, we'll try to use
384 * some interolation to get some speed out of it in
388 switch (stretchmode) {
390 color_stretch(sxi, dxi, widthSrc, heightSrc,
391 widthDest, heightDest);
392 /* bonw_stretch(sxi, dxi, widthSrc, heightSrc,
393 widthDest, heightDest);
396 color_stretch(sxi, dxi, widthSrc, heightSrc,
397 widthDest, heightDest);
398 /* wonb_stretch(sxi, dxi, widthSrc, heightSrc,
399 widthDest, heightDest);
402 color_stretch(sxi, dxi, widthSrc, heightSrc,
403 widthDest, heightDest);
406 fprintf(stderr, "StretchBlt: unknown stretchmode '%d'\n",
411 DC_SetupGCForText(dcDest);
412 XSetFunction(display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f]);
413 XPutImage(display, dcDest->u.x.drawable, dcDest->u.x.gc,
414 dxi, 0, 0, MIN(xd1,xd2), MIN(yd1,yd2),
415 widthDest, heightDest);
417 /* now free the images we created */