Release 950216
[wine.git] / windows / graphics.c
blob8ed3f8c117b4424d423f813b444c411b76baa856
1 /*
2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <math.h>
8 #include <stdlib.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
12 #ifndef PI
13 #define PI M_PI
14 #endif
15 #include "dc.h"
16 #include "bitmap.h"
17 #include "metafile.h"
18 #include "syscolor.h"
19 #include "stddebug.h"
20 #include "color.h"
21 #include "debug.h"
23 static __inline__ void swap_int(int *a, int *b)
25 int c;
27 c = *a;
28 *a = *b;
29 *b = c;
32 /***********************************************************************
33 * LineTo (GDI.19)
35 BOOL LineTo( HDC hdc, short x, short y )
37 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
38 if (!dc)
40 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
41 if (!dc) return FALSE;
42 MF_MetaParam2(dc, META_LINETO, x, y);
43 return TRUE;
46 if (DC_SetupGCForPen( dc ))
47 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
48 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
49 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
50 dc->w.DCOrgX + XLPTODP( dc, x ),
51 dc->w.DCOrgY + YLPTODP( dc, y ) );
52 dc->w.CursPosX = x;
53 dc->w.CursPosY = y;
54 return TRUE;
58 /***********************************************************************
59 * MoveTo (GDI.20)
61 DWORD MoveTo( HDC hdc, short x, short y )
63 short oldx, oldy;
64 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
65 if (!dc)
67 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
68 if (!dc) return FALSE;
69 MF_MetaParam2(dc, META_MOVETO, x, y);
70 return 0;
73 oldx = dc->w.CursPosX;
74 oldy = dc->w.CursPosY;
75 dc->w.CursPosX = x;
76 dc->w.CursPosY = y;
77 return oldx | (oldy << 16);
81 /***********************************************************************
82 * MoveToEx (GDI.483)
84 BOOL MoveToEx( HDC hdc, short x, short y, LPPOINT pt )
86 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
87 if (!dc) return FALSE;
88 if (pt)
90 pt->x = dc->w.CursPosX;
91 pt->y = dc->w.CursPosY;
93 dc->w.CursPosX = x;
94 dc->w.CursPosY = y;
95 return TRUE;
99 /***********************************************************************
100 * GRAPH_DrawArc
102 * Helper functions for Arc(), Chord() and Pie().
103 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
105 static BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom,
106 int xstart, int ystart, int xend, int yend, int lines )
108 int xcenter, ycenter, istart_angle, idiff_angle;
109 double start_angle, end_angle;
110 XPoint points[3];
111 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
112 if (!dc)
114 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
115 if (!dc) return FALSE;
116 switch (lines)
118 case 0:
119 MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
120 xstart, ystart, xend, yend);
121 break;
123 case 1:
124 MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
125 xstart, ystart, xend, yend);
126 break;
128 case 2:
129 MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
130 xstart, ystart, xend, yend);
131 break;
133 return 0;
136 left = XLPTODP( dc, left );
137 top = YLPTODP( dc, top );
138 right = XLPTODP( dc, right );
139 bottom = YLPTODP( dc, bottom );
140 xstart = XLPTODP( dc, xstart );
141 ystart = YLPTODP( dc, ystart );
142 xend = XLPTODP( dc, xend );
143 yend = YLPTODP( dc, yend );
144 if ((left == right) || (top == bottom)) return FALSE;
146 xcenter = (right + left) / 2;
147 ycenter = (bottom + top) / 2;
148 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
149 (double)(xstart-xcenter)*(bottom-top) );
150 end_angle = atan2( (double)(ycenter-yend)*(right-left),
151 (double)(xend-xcenter)*(bottom-top) );
152 istart_angle = (int)(start_angle * 180 * 64 / PI);
153 idiff_angle = (int)((end_angle - start_angle) * 180 * 64 / PI );
154 if (idiff_angle <= 0) idiff_angle += 360 * 64;
155 if (left > right) swap_int( &left, &right );
156 if (top > bottom) swap_int( &top, &bottom );
158 /* Fill arc with brush if Chord() or Pie() */
160 if ((lines > 0) && DC_SetupGCForBrush( dc ))
162 XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
163 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
164 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
165 right-left-1, bottom-top-1, istart_angle, idiff_angle );
168 /* Draw arc and lines */
170 if (!DC_SetupGCForPen( dc )) return TRUE;
171 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
172 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
173 right-left-1, bottom-top-1, istart_angle, idiff_angle );
174 if (!lines) return TRUE;
176 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
177 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
178 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
179 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
180 if (lines == 2)
182 points[2] = points[1];
183 points[1].x = dc->w.DCOrgX + xcenter;
184 points[1].y = dc->w.DCOrgY + ycenter;
186 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
187 points, lines+1, CoordModeOrigin );
188 return TRUE;
192 /***********************************************************************
193 * Arc (GDI.23)
195 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
196 int xstart, int ystart, int xend, int yend )
198 return GRAPH_DrawArc( hdc, left, top, right, bottom,
199 xstart, ystart, xend, yend, 0 );
203 /***********************************************************************
204 * Pie (GDI.26)
206 BOOL Pie( HDC hdc, int left, int top, int right, int bottom,
207 int xstart, int ystart, int xend, int yend )
209 return GRAPH_DrawArc( hdc, left, top, right, bottom,
210 xstart, ystart, xend, yend, 2 );
214 /***********************************************************************
215 * Chord (GDI.348)
217 BOOL Chord( HDC hdc, int left, int top, int right, int bottom,
218 int xstart, int ystart, int xend, int yend )
220 return GRAPH_DrawArc( hdc, left, top, right, bottom,
221 xstart, ystart, xend, yend, 1 );
225 /***********************************************************************
226 * Ellipse (GDI.24)
228 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
230 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
231 if (!dc)
233 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
234 if (!dc) return FALSE;
235 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
236 return 0;
239 left = XLPTODP( dc, left );
240 top = YLPTODP( dc, top );
241 right = XLPTODP( dc, right );
242 bottom = YLPTODP( dc, bottom );
243 if ((left == right) || (top == bottom)) return FALSE;
245 if (right < left)
246 swap_int(&right, &left);
248 if (bottom < top)
249 swap_int(&bottom, &top);
251 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
252 (dc->u.x.pen.width < right-left-1) &&
253 (dc->u.x.pen.width < bottom-top-1))
255 left += dc->u.x.pen.width / 2;
256 right -= (dc->u.x.pen.width + 1) / 2;
257 top += dc->u.x.pen.width / 2;
258 bottom -= (dc->u.x.pen.width + 1) / 2;
261 if (DC_SetupGCForBrush( dc ))
262 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
263 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
264 right-left-1, bottom-top-1, 0, 360*64 );
265 if (DC_SetupGCForPen( dc ))
266 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
267 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
268 right-left-1, bottom-top-1, 0, 360*64 );
269 return TRUE;
273 /***********************************************************************
274 * Rectangle (GDI.27)
276 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
278 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
279 if (!dc)
281 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
282 if (!dc) return FALSE;
283 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
284 return TRUE;
286 left = XLPTODP( dc, left );
287 top = YLPTODP( dc, top );
288 right = XLPTODP( dc, right );
289 bottom = YLPTODP( dc, bottom );
291 if (right < left)
292 swap_int(&right, &left);
294 if (bottom < top)
295 swap_int(&bottom, &top);
297 if ((left == right) || (top == bottom))
299 if (DC_SetupGCForPen( dc ))
300 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
301 dc->w.DCOrgX + left,
302 dc->w.DCOrgY + top,
303 dc->w.DCOrgX + right,
304 dc->w.DCOrgY + bottom);
305 return TRUE;
308 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
309 (dc->u.x.pen.width < right-left) &&
310 (dc->u.x.pen.width < bottom-top))
312 left += dc->u.x.pen.width / 2;
313 right -= (dc->u.x.pen.width + 1) / 2;
314 top += dc->u.x.pen.width / 2;
315 bottom -= (dc->u.x.pen.width + 1) / 2;
318 if (DC_SetupGCForBrush( dc ))
319 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
320 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
321 right-left, bottom-top );
322 if (DC_SetupGCForPen( dc ))
323 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
324 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
325 right-left-1, bottom-top-1 );
326 return TRUE;
330 /***********************************************************************
331 * RoundRect (GDI.28)
333 BOOL RoundRect( HDC hDC, short left, short top, short right, short bottom,
334 short ell_width, short ell_height)
336 int x1, y1, x2, y2;
337 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
338 if (!dc)
340 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
341 if (!dc) return FALSE;
342 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
343 ell_width, ell_height);
344 return TRUE;
346 dprintf_graphics(stddeb, "RoundRect(%d %d %d %d %d %d\n",
347 left, top, right, bottom, ell_width, ell_height);
348 x1 = XLPTODP(dc, left);
349 y1 = YLPTODP(dc, top);
350 x2 = XLPTODP(dc, right - ell_width);
351 y2 = YLPTODP(dc, bottom - ell_height);
352 if (DC_SetupGCForBrush( dc ))
354 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
355 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
356 ell_width, ell_height, 90 * 64, 90 * 64);
357 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
358 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
359 ell_width, ell_height, 180 * 64, 90 * 64);
360 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
361 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
362 ell_width, ell_height, 270 * 64, 90 * 64);
363 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
364 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
365 ell_width, ell_height, 0, 90 * 64);
366 ell_width /= 2; ell_height /= 2;
367 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
368 dc->w.DCOrgX + left + ell_width, dc->w.DCOrgY + top,
369 right - left - 2 * ell_width, bottom - top);
370 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
371 dc->w.DCOrgX + left, dc->w.DCOrgY + top + ell_height,
372 ell_width, bottom - top - 2 * ell_height);
373 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
374 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top + ell_height,
375 ell_width, bottom - top - 2 * ell_height);
376 ell_width *= 2; ell_height *= 2;
378 if (DC_SetupGCForPen(dc)) {
379 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
380 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
381 ell_width, ell_height, 90 * 64, 90 * 64);
382 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
383 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
384 ell_width, ell_height, 180 * 64, 90 * 64);
385 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
386 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
387 ell_width, ell_height, 270 * 64, 90 * 64);
388 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
389 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
390 ell_width, ell_height, 0, 90 * 64);
392 ell_width /= 2; ell_height /= 2;
393 MoveTo(hDC, left, top + ell_height);
394 LineTo(hDC, left, bottom - ell_height);
395 MoveTo(hDC, left + ell_width, bottom);
396 LineTo(hDC, right - ell_width, bottom);
397 MoveTo(hDC, right, bottom - ell_height);
398 LineTo(hDC, right, top + ell_height);
399 MoveTo(hDC, right - ell_width, top);
400 LineTo(hDC, left + ell_width, top);
401 return TRUE;
405 /***********************************************************************
406 * FillRect (USER.81)
408 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
410 HBRUSH prevBrush;
412 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
413 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
414 PatBlt( hdc, rect->left, rect->top,
415 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
416 SelectObject( hdc, prevBrush );
417 return 1;
421 /***********************************************************************
422 * InvertRect (USER.82)
424 void InvertRect( HDC hdc, LPRECT rect )
426 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
427 PatBlt( hdc, rect->left, rect->top,
428 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
432 /***********************************************************************
433 * FrameRect (USER.83)
435 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
437 HBRUSH prevBrush;
438 int left, top, right, bottom;
440 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
441 if (!dc) return FALSE;
443 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
444 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
446 left = XLPTODP( dc, rect->left );
447 top = YLPTODP( dc, rect->top );
448 right = XLPTODP( dc, rect->right );
449 bottom = YLPTODP( dc, rect->bottom );
451 if (DC_SetupGCForBrush( dc ))
453 PatBlt( hdc, rect->left, rect->top, 1,
454 rect->bottom - rect->top, PATCOPY );
455 PatBlt( hdc, rect->right - 1, rect->top, 1,
456 rect->bottom - rect->top, PATCOPY );
457 PatBlt( hdc, rect->left, rect->top,
458 rect->right - rect->left, 1, PATCOPY );
459 PatBlt( hdc, rect->left, rect->bottom - 1,
460 rect->right - rect->left, 1, PATCOPY );
462 SelectObject( hdc, prevBrush );
463 return 1;
467 /***********************************************************************
468 * SetPixel (GDI.31)
470 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
472 Pixel pixel;
473 PALETTEENTRY entry;
475 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
476 if (!dc)
478 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
479 if (!dc) return 0;
480 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
481 return 1;
484 x = dc->w.DCOrgX + XLPTODP( dc, x );
485 y = dc->w.DCOrgY + YLPTODP( dc, y );
486 pixel = COLOR_ToPhysical( dc, color );
488 XSetForeground( display, dc->u.x.gc, pixel );
489 XSetFunction( display, dc->u.x.gc, GXcopy );
490 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
492 if (screenDepth <= 8)
494 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
495 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
497 else return (COLORREF)pixel;
501 /***********************************************************************
502 * GetPixel (GDI.83)
504 COLORREF GetPixel( HDC hdc, short x, short y )
506 PALETTEENTRY entry;
507 XImage * image;
508 WORD * mapping;
509 int pixel;
511 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
512 if (!dc) return 0;
514 #ifdef SOLITAIRE_SPEED_HACK
515 return 0;
516 #endif
518 if (!PtVisible( hdc, x, y )) return 0;
520 x = dc->w.DCOrgX + XLPTODP( dc, x );
521 y = dc->w.DCOrgY + YLPTODP( dc, y );
522 image = XGetImage( display, dc->u.x.drawable, x, y,
523 1, 1, AllPlanes, ZPixmap );
524 pixel = XGetPixel( image, 0, 0 );
525 XDestroyImage( image );
527 if (screenDepth > 8) return pixel;
528 mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hRevMapping );
529 if (mapping) pixel = mapping[pixel];
530 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
531 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
535 /***********************************************************************
536 * PaintRgn (GDI.43)
538 BOOL PaintRgn( HDC hdc, HRGN hrgn )
540 RECT box;
541 HRGN tmpVisRgn, prevVisRgn;
542 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
543 if (!dc) return FALSE;
545 /* Modify visible region */
547 if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
548 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
550 RestoreVisRgn( hdc );
551 return FALSE;
553 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
554 SelectVisRgn( hdc, tmpVisRgn );
555 DeleteObject( tmpVisRgn );
557 /* Fill the region */
559 GetRgnBox( dc->w.hGCClipRgn, &box );
560 if (DC_SetupGCForBrush( dc ))
561 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
562 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
563 box.right-box.left, box.bottom-box.top );
565 /* Restore the visible region */
567 RestoreVisRgn( hdc );
568 return TRUE;
572 /***********************************************************************
573 * FillRgn (GDI.40)
575 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
577 BOOL retval;
578 HBRUSH prevBrush = SelectObject( hdc, hbrush );
579 if (!prevBrush) return FALSE;
580 retval = PaintRgn( hdc, hrgn );
581 SelectObject( hdc, prevBrush );
582 return retval;
586 /***********************************************************************
587 * InvertRgn (GDI.42)
589 BOOL InvertRgn( HDC hdc, HRGN hrgn )
591 HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
592 WORD prevROP = SetROP2( hdc, R2_NOT );
593 BOOL retval = PaintRgn( hdc, hrgn );
594 SelectObject( hdc, prevBrush );
595 SetROP2( hdc, prevROP );
596 return retval;
600 /***********************************************************************
601 * DrawFocusRect (USER.466)
603 void DrawFocusRect( HDC hdc, LPRECT rc )
605 HPEN hOldPen;
606 int oldDrawMode, oldBkMode;
607 int left, top, right, bottom;
608 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
609 if (!dc) return;
611 left = XLPTODP( dc, rc->left );
612 top = YLPTODP( dc, rc->top );
613 right = XLPTODP( dc, rc->right );
614 bottom = YLPTODP( dc, rc->bottom );
616 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
617 oldDrawMode = SetROP2(hdc, R2_XORPEN);
618 oldBkMode = SetBkMode(hdc, TRANSPARENT);
620 if (DC_SetupGCForPen( dc ))
621 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
622 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
623 right-left-1, bottom-top-1 );
625 SetBkMode(hdc, oldBkMode);
626 SetROP2(hdc, oldDrawMode);
627 SelectObject(hdc, (HANDLE)hOldPen);
631 /**********************************************************************
632 * GRAPH_DrawBitmap
634 * Short-cut function to blit a bitmap into a device.
635 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
637 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
638 int xsrc, int ysrc, int width, int height )
640 XGCValues val;
641 BITMAPOBJ *bmp;
642 DC *dc;
644 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
645 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
646 return FALSE;
647 val.function = GXcopy;
648 val.foreground = dc->w.textPixel;
649 val.background = dc->w.backgroundPixel;
650 XChangeGC(display, dc->u.x.gc, GCFunction|GCForeground|GCBackground, &val);
651 if (bmp->bitmap.bmBitsPixel == 1)
653 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
654 xsrc, ysrc, width, height,
655 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
656 return TRUE;
658 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
660 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
661 xsrc, ysrc, width, height,
662 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
663 return TRUE;
665 else return FALSE;
669 /**********************************************************************
670 * GRAPH_DrawReliefRect (Not a MSWin Call)
672 void GRAPH_DrawReliefRect( HDC hdc, RECT *rect, int highlight_size,
673 int shadow_size, BOOL pressed )
675 HBRUSH hbrushOld;
676 int i;
678 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
679 sysColorObjects.hbrushBtnHighlight );
680 for (i = 0; i < highlight_size; i++)
682 PatBlt( hdc, rect->left + i, rect->top,
683 1, rect->bottom - rect->top - i, PATCOPY );
684 PatBlt( hdc, rect->left, rect->top + i,
685 rect->right - rect->left - i, 1, PATCOPY );
688 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
689 sysColorObjects.hbrushBtnShadow );
690 for (i = 0; i < shadow_size; i++)
692 PatBlt( hdc, rect->right - i - 1, rect->top + i,
693 1, rect->bottom - rect->top - i, PATCOPY );
694 PatBlt( hdc, rect->left + i, rect->bottom - i - 1,
695 rect->right - rect->left - i, 1, PATCOPY );
698 SelectObject( hdc, hbrushOld );
702 /**********************************************************************
703 * Polyline (GDI.37)
705 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
707 register int i;
708 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
709 if (!dc)
711 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
712 if (!dc) return FALSE;
713 MF_MetaPoly(dc, META_POLYLINE, pt, count);
714 return TRUE;
717 if (DC_SetupGCForPen( dc ))
718 for (i = 0; i < count-1; i ++)
719 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
720 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
721 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
722 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
723 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].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 /* FIXME: 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 (GetRgnBox( dc->w.hGCClipRgn, &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 );