Release 940301
[wine/dcerpc.git] / objects / bitblt.c
blobbbfa3bd5e527f5e946517140216aaa86aa58dc4e
1 /*
2 * GDI bit-blit operations
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <X11/Xlib.h>
12 #include <X11/Intrinsic.h>
14 #include "gdi.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 /***********************************************************************
23 * PatBlt (GDI.29)
25 BOOL PatBlt( HDC hdc, short left, short top,
26 short width, short height, DWORD rop)
28 int x1, x2, y1, y2;
30 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
31 if (!dc) return FALSE;
32 #ifdef DEBUG_GDI
33 printf( "PatBlt: %d %d,%d %dx%d %06x\n",
34 hdc, left, top, width, height, rop );
35 #endif
37 rop >>= 16;
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) );
48 return TRUE;
52 /***********************************************************************
53 * BitBlt (GDI.34)
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;
60 DC *dcDest, *dcSrc;
62 #ifdef DEBUG_GDI
63 printf( "BitBlt: %d %d,%d %dx%d %d %d,%d %08x\n",
64 hdcDest, xDest, yDest, width, height, hdcSrc, xSrc, ySrc, rop );
65 #endif
67 if ((rop & 0xcc0000) == ((rop & 0x330000) << 2))
68 return PatBlt( hdcDest, xDest, yDest, width, height, rop );
70 rop >>= 16;
71 if ((rop & 0x0f) != (rop >> 4))
73 printf( "BitBlt: Unimplemented ROP %02x\n", rop );
74 return FALSE;
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) );
103 else
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 );
111 return TRUE;
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;
124 register int x, y;
125 Pixel whitep;
126 int totalx, totaly, xavgwhite, yavgwhite;
127 register int i;
128 int endx, endy;
130 deltax = (float)widthSrc/widthDest;
131 deltay = (float)heightSrc/heightDest;
132 whitep = WhitePixel(display, DefaultScreen(display));
134 oldsourcex = 0;
135 for (x=0, sourcex=0.0; x<widthDest;
136 x++, oldsourcex=sourcex, sourcex+=deltax) {
137 xavgwhite = 0;
138 if (deltax > 1.0) {
139 totalx = 0;
140 endx = (int)sourcex;
141 for (i=(int)oldsourcex; i<=endx; i++)
142 if (XGetPixel(sxi, i, (int)sourcey) == whitep)
143 totalx++;
144 xavgwhite = (totalx > (int)(deltax / 2.0));
145 } else {
146 xavgwhite = 0;
149 oldsourcey = 0;
150 for (y=0, sourcey=0.0; y<heightDest;
151 y++, oldsourcey=sourcey, sourcey+=deltay) {
152 yavgwhite = 0;
153 if (deltay > 1.0) {
154 totaly = 0;
155 endy = (int)sourcey;
156 for (i=(int)oldsourcey; i<=endy; i++)
157 if (XGetPixel(sxi, (int)sourcex, i) == whitep)
158 totaly++;
159 yavgwhite = (totaly > ((int)deltay / 2));
160 } else {
161 yavgwhite = 0;
163 if (xavgwhite && yavgwhite)
164 XPutPixel(dxi, x, y, whitep);
165 else
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;
181 register int x, y;
182 Pixel blackp;
183 int totalx, totaly, xavgblack, yavgblack;
184 register int i;
185 int endx, endy;
187 deltax = (float)widthSrc/widthDest;
188 deltay = (float)heightSrc/heightDest;
189 blackp = WhitePixel(display, DefaultScreen(display));
191 oldsourcex = 0;
192 for (x=0, sourcex=0.0; x<widthDest;
193 x++, oldsourcex=sourcex, sourcex+=deltax) {
194 xavgblack = 0;
195 if (deltax > 1.0) {
196 totalx = 0;
197 endx = (int)sourcex;
198 for (i=(int)oldsourcex; i<=endx; i++)
199 if (XGetPixel(sxi, i, (int)sourcey) == blackp)
200 totalx++;
201 xavgblack = (totalx > (int)(deltax / 2.0));
202 } else {
203 xavgblack = 0;
206 oldsourcey = 0;
207 for (y=0, sourcey=0.0; y<heightDest;
208 y++, oldsourcey=sourcey, sourcey+=deltay) {
209 yavgblack = 0;
210 if (deltay > 1.0) {
211 totaly = 0;
212 endy = (int)sourcey;
213 for (i=(int)oldsourcey; i<=endy; i++)
214 if (XGetPixel(sxi, (int)sourcex, i) == blackp)
215 totaly++;
216 yavgblack = (totaly > ((int)deltay / 2));
217 } else {
218 yavgblack = 0;
220 if (xavgblack && yavgblack)
221 XPutPixel(dxi, x, y, blackp);
222 else
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;
237 register int x, y;
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
255 * speed it up.
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;
264 DC *dcDest, *dcSrc;
265 XImage *sxi, *dxi;
266 WORD stretchmode;
268 #ifdef DEBUG_GDI
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);
274 #endif
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);
288 rop >>= 16;
289 if ((rop & 0x0f) != (rop >> 4))
291 printf( "StretchBlt: Unimplemented ROP %02x\n", rop );
292 return FALSE;
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
311 * the pixels
314 sxi = XGetImage(display, dcSrc->u.x.drawable, xs1, ys1,
315 widthSrc, heightSrc, AllPlanes, ZPixmap);
316 dxi = XCreateImage(display, DefaultVisualOfScreen(screen),
317 DefaultDepthOfScreen(screen), ZPixmap,
318 0, NULL, widthDest, heightDest,
319 32, 0);
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
326 * the future
329 switch (stretchmode) {
330 case BLACKONWHITE:
331 bonw_stretch(sxi, dxi, widthSrc, heightSrc,
332 widthDest, heightDest);
333 break;
334 case WHITEONBLACK:
335 wonb_stretch(sxi, dxi, widthSrc, heightSrc,
336 widthDest, heightDest);
337 break;
338 case COLORONCOLOR:
339 color_stretch(sxi, dxi, widthSrc, heightSrc,
340 widthDest, heightDest);
341 break;
342 default:
343 fprintf(stderr, "StretchBlt: unknown stretchmode '%d'\n",
344 stretchmode);
345 break;
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 */
356 XDestroyImage(sxi);
357 XDestroyImage(dxi);
359 return TRUE;