Release 941227
[wine/multimedia.git] / windows / graphics.c
blob421328223d6169d594e8d98f85be9c39c3e54380
1 /*
2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993, 1994";
9 #include <math.h>
10 #include <stdlib.h>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/Intrinsic.h>
14 #ifndef PI
15 #define PI M_PI
16 #endif
17 #include "dc.h"
18 #include "gdi.h"
19 #include "metafile.h"
20 #include "syscolor.h"
21 #include "stddebug.h"
22 #include "color.h"
23 #include "debug.h"
25 static __inline__ void swap_int(int *a, int *b)
27 int c;
29 c = *a;
30 *a = *b;
31 *b = c;
34 /***********************************************************************
35 * LineTo (GDI.19)
37 BOOL LineTo( HDC hdc, short x, short y )
39 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
40 if (!dc)
42 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
43 if (!dc) return FALSE;
44 MF_MetaParam2(dc, META_LINETO, x, y);
45 return TRUE;
48 if (DC_SetupGCForPen( dc ))
49 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
50 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
51 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
52 dc->w.DCOrgX + XLPTODP( dc, x ),
53 dc->w.DCOrgY + YLPTODP( dc, y ) );
54 dc->w.CursPosX = x;
55 dc->w.CursPosY = y;
56 return TRUE;
60 /***********************************************************************
61 * MoveTo (GDI.20)
63 DWORD MoveTo( HDC hdc, short x, short y )
65 short oldx, oldy;
66 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
67 if (!dc)
69 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
70 if (!dc) return FALSE;
71 MF_MetaParam2(dc, META_MOVETO, x, y);
72 return 0;
75 oldx = dc->w.CursPosX;
76 oldy = dc->w.CursPosY;
77 dc->w.CursPosX = x;
78 dc->w.CursPosY = y;
79 return oldx | (oldy << 16);
83 /***********************************************************************
84 * MoveToEx (GDI.483)
86 BOOL MoveToEx( HDC hdc, short x, short y, LPPOINT pt )
88 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
89 if (!dc) return FALSE;
90 if (pt)
92 pt->x = dc->w.CursPosX;
93 pt->y = dc->w.CursPosY;
95 dc->w.CursPosX = x;
96 dc->w.CursPosY = y;
97 return TRUE;
101 /***********************************************************************
102 * GRAPH_DrawArc
104 * Helper functions for Arc(), Chord() and Pie().
105 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
107 static BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom,
108 int xstart, int ystart, int xend, int yend, int lines )
110 int xcenter, ycenter, istart_angle, idiff_angle;
111 double start_angle, end_angle;
112 XPoint points[3];
113 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
114 if (!dc)
116 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
117 if (!dc) return FALSE;
118 switch (lines)
120 case 0:
121 MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
122 xstart, ystart, xend, yend);
123 break;
125 case 1:
126 MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
127 xstart, ystart, xend, yend);
128 break;
130 case 2:
131 MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
132 xstart, ystart, xend, yend);
133 break;
135 return 0;
138 left = XLPTODP( dc, left );
139 top = YLPTODP( dc, top );
140 right = XLPTODP( dc, right );
141 bottom = YLPTODP( dc, bottom );
142 xstart = XLPTODP( dc, xstart );
143 ystart = YLPTODP( dc, ystart );
144 xend = XLPTODP( dc, xend );
145 yend = YLPTODP( dc, yend );
146 if ((left == right) || (top == bottom)) return FALSE;
148 xcenter = (right + left) / 2;
149 ycenter = (bottom + top) / 2;
150 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
151 (double)(xstart-xcenter)*(bottom-top) );
152 end_angle = atan2( (double)(ycenter-yend)*(right-left),
153 (double)(xend-xcenter)*(bottom-top) );
154 istart_angle = (int)(start_angle * 180 * 64 / PI);
155 idiff_angle = (int)((end_angle - start_angle) * 180 * 64 / PI );
156 if (idiff_angle <= 0) idiff_angle += 360 * 64;
157 if (left > right) swap_int( &left, &right );
158 if (top > bottom) swap_int( &top, &bottom );
160 /* Fill arc with brush if Chord() or Pie() */
162 if ((lines > 0) && DC_SetupGCForBrush( dc ))
164 XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
165 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
166 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
167 right-left-1, bottom-top-1, istart_angle, idiff_angle );
170 /* Draw arc and lines */
172 if (!DC_SetupGCForPen( dc )) return TRUE;
173 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
174 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
175 right-left-1, bottom-top-1, istart_angle, idiff_angle );
176 if (!lines) return TRUE;
178 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
179 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
180 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
181 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
182 if (lines == 2)
184 points[2] = points[1];
185 points[1].x = dc->w.DCOrgX + xcenter;
186 points[1].y = dc->w.DCOrgY + ycenter;
188 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
189 points, lines+1, CoordModeOrigin );
190 return TRUE;
194 /***********************************************************************
195 * Arc (GDI.23)
197 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
198 int xstart, int ystart, int xend, int yend )
200 return GRAPH_DrawArc( hdc, left, top, right, bottom,
201 xstart, ystart, xend, yend, 0 );
205 /***********************************************************************
206 * Pie (GDI.26)
208 BOOL Pie( HDC hdc, int left, int top, int right, int bottom,
209 int xstart, int ystart, int xend, int yend )
211 return GRAPH_DrawArc( hdc, left, top, right, bottom,
212 xstart, ystart, xend, yend, 2 );
216 /***********************************************************************
217 * Chord (GDI.348)
219 BOOL Chord( HDC hdc, int left, int top, int right, int bottom,
220 int xstart, int ystart, int xend, int yend )
222 return GRAPH_DrawArc( hdc, left, top, right, bottom,
223 xstart, ystart, xend, yend, 1 );
227 /***********************************************************************
228 * Ellipse (GDI.24)
230 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
232 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
233 if (!dc)
235 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
236 if (!dc) return FALSE;
237 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
238 return 0;
241 left = XLPTODP( dc, left );
242 top = YLPTODP( dc, top );
243 right = XLPTODP( dc, right );
244 bottom = YLPTODP( dc, bottom );
245 if ((left == right) || (top == bottom)) return FALSE;
247 if (right < left)
248 swap_int(&right, &left);
250 if (bottom < top)
251 swap_int(&bottom, &top);
253 if (DC_SetupGCForBrush( dc ))
254 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
255 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
256 right-left-1, bottom-top-1, 0, 360*64 );
257 if (DC_SetupGCForPen( dc ))
258 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
259 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
260 right-left-1, bottom-top-1, 0, 360*64 );
261 return TRUE;
265 /***********************************************************************
266 * Rectangle (GDI.27)
268 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
270 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
271 if (!dc)
273 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
274 if (!dc) return FALSE;
275 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
276 return TRUE;
278 left = XLPTODP( dc, left );
279 top = YLPTODP( dc, top );
280 right = XLPTODP( dc, right );
281 bottom = YLPTODP( dc, bottom );
283 if (right < left)
284 swap_int(&right, &left);
286 if (bottom < top)
287 swap_int(&bottom, &top);
289 if ((left == right) || (top == bottom)) {
290 if (DC_SetupGCForPen( dc ))
291 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
292 dc->w.DCOrgX + left,
293 dc->w.DCOrgY + top,
294 dc->w.DCOrgX + right,
295 dc->w.DCOrgY + bottom);
296 return TRUE;
299 if (DC_SetupGCForBrush( dc ))
300 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
301 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
302 right-left, bottom-top );
303 if (DC_SetupGCForPen( dc ))
304 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
305 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
306 right-left-1, bottom-top-1 );
307 return TRUE;
311 /***********************************************************************
312 * RoundRect (GDI.28)
314 BOOL RoundRect( HDC hDC, short left, short top, short right, short bottom,
315 short ell_width, short ell_height)
317 int x1, y1, x2, y2;
318 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
319 if (!dc)
321 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
322 if (!dc) return FALSE;
323 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
324 ell_width, ell_height);
325 return TRUE;
327 dprintf_graphics(stddeb, "RoundRect(%d %d %d %d %d %d\n",
328 left, top, right, bottom, ell_width, ell_height);
329 x1 = XLPTODP(dc, left);
330 y1 = YLPTODP(dc, top);
331 x2 = XLPTODP(dc, right - ell_width);
332 y2 = YLPTODP(dc, bottom - ell_height);
333 if (DC_SetupGCForBrush(dc)) {
334 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
335 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
336 ell_width, ell_height, 90 * 64, 90 * 64);
337 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
338 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
339 ell_width, ell_height, 180 * 64, 90 * 64);
340 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
341 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
342 ell_width, ell_height, 270 * 64, 90 * 64);
343 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
344 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
345 ell_width, ell_height, 0, 90 * 64);
346 ell_width /= 2; ell_height /= 2;
347 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
348 dc->w.DCOrgX + left + ell_width, dc->w.DCOrgY + top,
349 right - left - 2 * ell_width, bottom - top);
350 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
351 dc->w.DCOrgX + left, dc->w.DCOrgY + top + ell_height,
352 ell_width, bottom - top - 2 * ell_height);
353 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
354 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top + ell_height,
355 ell_width, bottom - top - 2 * ell_height);
356 ell_width *= 2; ell_height *= 2;
358 if (DC_SetupGCForPen(dc)) {
359 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
360 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
361 ell_width, ell_height, 90 * 64, 90 * 64);
362 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
363 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
364 ell_width, ell_height, 180 * 64, 90 * 64);
365 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
366 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
367 ell_width, ell_height, 270 * 64, 90 * 64);
368 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
369 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
370 ell_width, ell_height, 0, 90 * 64);
372 ell_width /= 2; ell_height /= 2;
373 MoveTo(hDC, left, top + ell_height);
374 LineTo(hDC, left, bottom - ell_height);
375 MoveTo(hDC, left + ell_width, bottom);
376 LineTo(hDC, right - ell_width, bottom);
377 MoveTo(hDC, right, bottom - ell_height);
378 LineTo(hDC, right, top + ell_height);
379 MoveTo(hDC, right - ell_width, top);
380 LineTo(hDC, left + ell_width, top);
381 return TRUE;
385 /***********************************************************************
386 * FillRect (USER.81)
388 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
390 HBRUSH prevBrush;
392 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
393 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
394 PatBlt( hdc, rect->left, rect->top,
395 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
396 SelectObject( hdc, prevBrush );
397 return 1;
401 /***********************************************************************
402 * InvertRect (USER.82)
404 void InvertRect( HDC hdc, LPRECT rect )
406 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
407 PatBlt( hdc, rect->left, rect->top,
408 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
412 /***********************************************************************
413 * FrameRect (USER.83)
415 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
417 HBRUSH prevBrush;
418 int left, top, right, bottom;
420 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
421 if (!dc) return FALSE;
423 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
424 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
426 left = XLPTODP( dc, rect->left );
427 top = YLPTODP( dc, rect->top );
428 right = XLPTODP( dc, rect->right );
429 bottom = YLPTODP( dc, rect->bottom );
431 if (DC_SetupGCForBrush( dc )) {
432 PatBlt( hdc, rect->left, rect->top, 1,
433 rect->bottom - rect->top, PATCOPY );
434 PatBlt( hdc, rect->right - 1, rect->top, 1,
435 rect->bottom - rect->top, PATCOPY );
436 PatBlt( hdc, rect->left, rect->top,
437 rect->right - rect->left, 1, PATCOPY );
438 PatBlt( hdc, rect->left, rect->bottom - 1,
439 rect->right - rect->left, 1, PATCOPY );
441 SelectObject( hdc, prevBrush );
442 return 1;
446 /***********************************************************************
447 * SetPixel (GDI.31)
449 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
451 Pixel pixel;
452 PALETTEENTRY entry;
454 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
455 if (!dc)
457 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
458 if (!dc) return 0;
459 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
460 return 1;
463 x = dc->w.DCOrgX + XLPTODP( dc, x );
464 y = dc->w.DCOrgY + YLPTODP( dc, y );
465 pixel = COLOR_ToPhysical( dc, color );
467 XSetForeground( display, dc->u.x.gc, pixel );
468 XSetFunction( display, dc->u.x.gc, GXcopy );
469 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
471 if (screenDepth <= 8)
473 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
474 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
476 else return (COLORREF)pixel;
480 /***********************************************************************
481 * GetPixel (GDI.83)
483 COLORREF GetPixel( HDC hdc, short x, short y )
485 PALETTEENTRY entry;
486 XImage * image;
487 WORD * mapping;
488 int pixel;
490 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
491 if (!dc) return 0;
493 #ifdef SOLITAIRE_SPEED_HACK
494 return 0;
495 #endif
497 if (!PtVisible( hdc, x, y )) return 0;
499 x = dc->w.DCOrgX + XLPTODP( dc, x );
500 y = dc->w.DCOrgY + YLPTODP( dc, y );
501 #if 0
502 if ((x < 0) || (y < 0)) return 0;
504 if (!(dc->w.flags & DC_MEMORY))
506 XWindowAttributes win_attr;
508 if (!XGetWindowAttributes( display, dc->u.x.drawable, &win_attr ))
509 return 0;
510 if (win_attr.map_state != IsViewable) return 0;
511 if ((x >= win_attr.width) || (y >= win_attr.height)) return 0;
513 #endif
514 image = XGetImage( display, dc->u.x.drawable, x, y,
515 1, 1, AllPlanes, ZPixmap );
516 pixel = XGetPixel( image, 0, 0 );
517 XDestroyImage( image );
519 if (screenDepth > 8) return pixel;
520 mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hRevMapping );
521 if (mapping) pixel = mapping[pixel];
522 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
523 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
527 /***********************************************************************
528 * PaintRgn (GDI.43)
530 BOOL PaintRgn( HDC hdc, HRGN hrgn )
532 RECT box;
533 HRGN tmpVisRgn, prevVisRgn;
534 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
535 if (!dc) return FALSE;
537 /* Modify visible region */
539 if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
540 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
542 RestoreVisRgn( hdc );
543 return FALSE;
545 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
546 SelectVisRgn( hdc, tmpVisRgn );
547 DeleteObject( tmpVisRgn );
549 /* Fill the region */
551 GetClipBox( hdc, &box );
552 if (DC_SetupGCForBrush( dc ))
553 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
554 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
555 box.right-box.left, box.bottom-box.top );
557 /* Restore the visible region */
559 RestoreVisRgn( hdc );
560 return TRUE;
564 /***********************************************************************
565 * FillRgn (GDI.40)
567 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
569 BOOL retval;
570 HBRUSH prevBrush = SelectObject( hdc, hbrush );
571 if (!prevBrush) return FALSE;
572 retval = PaintRgn( hdc, hrgn );
573 SelectObject( hdc, prevBrush );
574 return retval;
578 /***********************************************************************
579 * InvertRgn (GDI.42)
581 BOOL InvertRgn( HDC hdc, HRGN hrgn )
583 HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
584 WORD prevROP = SetROP2( hdc, R2_NOT );
585 BOOL retval = PaintRgn( hdc, hrgn );
586 SelectObject( hdc, prevBrush );
587 SetROP2( hdc, prevROP );
588 return retval;
592 /***********************************************************************
593 * DrawFocusRect (USER.466)
595 void DrawFocusRect( HDC hdc, LPRECT rc )
597 HPEN hOldPen;
598 int oldDrawMode, oldBkMode;
599 int left, top, right, bottom;
600 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
601 if (!dc) return;
603 left = XLPTODP( dc, rc->left );
604 top = YLPTODP( dc, rc->top );
605 right = XLPTODP( dc, rc->right );
606 bottom = YLPTODP( dc, rc->bottom );
608 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
609 oldDrawMode = SetROP2(hdc, R2_XORPEN);
610 oldBkMode = SetBkMode(hdc, TRANSPARENT);
612 if (DC_SetupGCForPen( dc ))
613 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
614 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
615 right-left-1, bottom-top-1 );
617 SetBkMode(hdc, oldBkMode);
618 SetROP2(hdc, oldDrawMode);
619 SelectObject(hdc, (HANDLE)hOldPen);
623 /**********************************************************************
624 * GRAPH_DrawBitmap
626 * Short-cut function to blit a bitmap into a device.
627 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
629 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
630 int xsrc, int ysrc, int width, int height, int rop )
632 XGCValues val;
633 BITMAPOBJ *bmp;
634 DC *dc;
636 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
637 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
638 return FALSE;
639 val.function = DC_XROPfunction[(rop >> 16) & 0x0f];
640 val.foreground = dc->w.textPixel;
641 val.background = dc->w.backgroundPixel;
642 XChangeGC(display, dc->u.x.gc, GCFunction|GCForeground|GCBackground, &val);
643 if (bmp->bitmap.bmBitsPixel == 1)
645 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
646 xsrc, ysrc, width, height,
647 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
648 return TRUE;
650 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
652 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
653 xsrc, ysrc, width, height,
654 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
655 return TRUE;
657 else return FALSE;
661 /**********************************************************************
662 * GRAPH_DrawReliefRect (Not a MSWin Call)
664 void GRAPH_DrawReliefRect( HDC hdc, RECT *rect, int highlight_size,
665 int shadow_size, BOOL pressed )
667 HBRUSH hbrushOld;
668 int i;
670 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
671 sysColorObjects.hbrushBtnHighlight );
672 for (i = 0; i < highlight_size; i++)
674 PatBlt( hdc, rect->left + i, rect->top,
675 1, rect->bottom - rect->top - i, PATCOPY );
676 PatBlt( hdc, rect->left, rect->top + i,
677 rect->right - rect->left - i, 1, PATCOPY );
680 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
681 sysColorObjects.hbrushBtnShadow );
682 for (i = 0; i < shadow_size; i++)
684 PatBlt( hdc, rect->right - i - 1, rect->top + i,
685 1, rect->bottom - rect->top - i, PATCOPY );
686 PatBlt( hdc, rect->left + i, rect->bottom - i - 1,
687 rect->right - rect->left - i, 1, PATCOPY );
690 SelectObject( hdc, hbrushOld );
694 /**********************************************************************
695 * Polyline (GDI.37)
697 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
699 register int i;
700 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
701 if (!dc)
703 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
704 if (!dc) return FALSE;
705 MF_MetaPoly(dc, META_POLYLINE, pt, count);
706 return TRUE;
709 if (DC_SetupGCForPen( dc ))
711 for (i = 0; i < count-1; i ++)
712 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
713 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
714 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
715 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
716 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
717 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
718 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
719 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
720 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
721 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
724 return (TRUE);
728 /**********************************************************************
729 * Polygon (GDI.36)
731 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
733 register int i;
734 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
735 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * (count+1));
737 if (!dc)
739 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
740 if (!dc) return FALSE;
741 MF_MetaPoly(dc, META_POLYGON, pt, count);
742 return TRUE;
745 for (i = 0; i < count; i++)
747 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
748 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
750 points[count] = points[0];
752 if (DC_SetupGCForBrush( dc ))
753 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
754 points, count+1, Complex, CoordModeOrigin);
756 if (DC_SetupGCForPen ( dc ))
757 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
758 points, count+1, CoordModeOrigin );
760 free( points );
761 return TRUE;
765 /**********************************************************************
766 * PolyPolygon (GDI.450)
768 BOOL PolyPolygon( HDC hdc, LPPOINT pt, LPINT counts, WORD polygons )
770 HRGN hrgn;
771 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
773 if (!dc)
775 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
776 if (!dc) return FALSE;
777 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
778 return TRUE;
780 /* The points should be converted to device coords before */
781 /* creating the region. But as CreatePolyPolygonRgn is not */
782 /* really correct either, it doesn't matter much... */
783 /* At least the outline will be correct :-) */
784 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->w.polyFillMode );
785 PaintRgn( hdc, hrgn );
786 DeleteObject( hrgn );
788 /* Draw the outline of the polygons */
790 if (DC_SetupGCForPen ( dc ))
792 int i, j, max = 0;
793 XPoint *points;
795 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
796 points = (XPoint *) malloc( sizeof(XPoint) * (max+1) );
798 for (i = 0; i < polygons; i++)
800 for (j = 0; j < counts[i]; j++)
802 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
803 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
804 pt++;
806 points[j] = points[0];
807 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
808 points, j + 1, CoordModeOrigin );
810 free( points );
812 return TRUE;
816 /**********************************************************************
817 * GRAPH_InternalFloodFill
819 * Internal helper function for flood fill.
820 * (xorg,yorg) is the origin of the X image relative to the drawable.
821 * (x,y) is relative to the origin of the X image.
823 static void GRAPH_InternalFloodFill( XImage *image, DC *dc,
824 int x, int y,
825 int xOrg, int yOrg,
826 Pixel pixel, WORD fillType )
828 int left, right;
830 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
831 (XGetPixel(image,x,y) != pixel) : \
832 (XGetPixel(image,x,y) == pixel))
834 if (!TO_FLOOD(x,y)) return;
836 /* Find left and right boundaries */
838 left = right = x;
839 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
840 while ((right < image->width) && TO_FLOOD( right, y )) right++;
841 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
842 xOrg + left, yOrg + y, right-left, 1 );
844 /* Set the pixels of this line so we don't fill it again */
846 for (x = left; x < right; x++)
848 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
849 else XPutPixel( image, x, y, ~pixel );
852 /* Fill the line above */
854 if (--y >= 0)
856 x = left;
857 while (x < right)
859 while ((x < right) && !TO_FLOOD(x,y)) x++;
860 if (x >= right) break;
861 while ((x < right) && TO_FLOOD(x,y)) x++;
862 GRAPH_InternalFloodFill( image, dc, x-1, y,
863 xOrg, yOrg, pixel, fillType );
867 /* Fill the line below */
869 if ((y += 2) < image->height)
871 x = left;
872 while (x < right)
874 while ((x < right) && !TO_FLOOD(x,y)) x++;
875 if (x >= right) break;
876 while ((x < right) && TO_FLOOD(x,y)) x++;
877 GRAPH_InternalFloodFill( image, dc, x-1, y,
878 xOrg, yOrg, pixel, fillType );
881 #undef TO_FLOOD
885 /**********************************************************************
886 * ExtFloodFill (GDI.372)
888 BOOL ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, WORD fillType )
890 RECT rect;
891 Pixel pixel;
892 XImage *image;
893 DC *dc;
895 dprintf_graphics( stddeb, "ExtFloodFill %x %d,%d %06lx %d\n",
896 hdc, x, y, color, fillType );
897 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
898 if (!dc)
900 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
901 if (!dc) return FALSE;
902 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(color),
903 LOWORD(color));
904 return TRUE;
907 if (!PtVisible( hdc, x, y )) return FALSE;
908 if (GetClipBox( hdc, &rect ) == ERROR) return FALSE;
909 pixel = COLOR_ToPhysical( dc, color );
911 if (!(image = XGetImage( display, dc->u.x.drawable,
912 dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
913 rect.right - rect.left, rect.bottom - rect.top,
914 AllPlanes, ZPixmap ))) return FALSE;
916 if (DC_SetupGCForBrush( dc ))
918 /* ROP mode is always GXcopy for flood-fill */
919 XSetFunction( display, dc->u.x.gc, GXcopy );
920 /* We can pass anything except 0 as a region */
921 GRAPH_InternalFloodFill( image, dc,
922 XLPTODP(dc,x) - rect.left,
923 YLPTODP(dc,y) - rect.top,
924 dc->w.DCOrgX + rect.left,
925 dc->w.DCOrgY + rect.top,
926 pixel, fillType );
929 XDestroyImage( image );
930 return TRUE;
934 /**********************************************************************
935 * FloodFill (GDI.25)
937 BOOL FloodFill( HDC hdc, INT x, INT y, COLORREF color )
939 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );