Release 950109
[wine/multimedia.git] / windows / graphics.c
blobcd8013b6e7c882b10996e6babde6494cab8d1fa7
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 /* FIXME: the region is supposed to be in logical coordinates */
547 /* Modify visible region */
549 if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
550 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
552 RestoreVisRgn( hdc );
553 return FALSE;
555 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
556 SelectVisRgn( hdc, tmpVisRgn );
557 DeleteObject( tmpVisRgn );
559 /* Fill the region */
561 GetClipBox( hdc, &box );
562 if (DC_SetupGCForBrush( dc ))
563 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
564 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
565 box.right-box.left, box.bottom-box.top );
567 /* Restore the visible region */
569 RestoreVisRgn( hdc );
570 return TRUE;
574 /***********************************************************************
575 * FillRgn (GDI.40)
577 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
579 BOOL retval;
580 HBRUSH prevBrush = SelectObject( hdc, hbrush );
581 if (!prevBrush) return FALSE;
582 retval = PaintRgn( hdc, hrgn );
583 SelectObject( hdc, prevBrush );
584 return retval;
588 /***********************************************************************
589 * InvertRgn (GDI.42)
591 BOOL InvertRgn( HDC hdc, HRGN hrgn )
593 HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
594 WORD prevROP = SetROP2( hdc, R2_NOT );
595 BOOL retval = PaintRgn( hdc, hrgn );
596 SelectObject( hdc, prevBrush );
597 SetROP2( hdc, prevROP );
598 return retval;
602 /***********************************************************************
603 * DrawFocusRect (USER.466)
605 void DrawFocusRect( HDC hdc, LPRECT rc )
607 HPEN hOldPen;
608 int oldDrawMode, oldBkMode;
609 int left, top, right, bottom;
610 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
611 if (!dc) return;
613 left = XLPTODP( dc, rc->left );
614 top = YLPTODP( dc, rc->top );
615 right = XLPTODP( dc, rc->right );
616 bottom = YLPTODP( dc, rc->bottom );
618 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
619 oldDrawMode = SetROP2(hdc, R2_XORPEN);
620 oldBkMode = SetBkMode(hdc, TRANSPARENT);
622 if (DC_SetupGCForPen( dc ))
623 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
624 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
625 right-left-1, bottom-top-1 );
627 SetBkMode(hdc, oldBkMode);
628 SetROP2(hdc, oldDrawMode);
629 SelectObject(hdc, (HANDLE)hOldPen);
633 /**********************************************************************
634 * GRAPH_DrawBitmap
636 * Short-cut function to blit a bitmap into a device.
637 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
639 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
640 int xsrc, int ysrc, int width, int height )
642 XGCValues val;
643 BITMAPOBJ *bmp;
644 DC *dc;
646 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
647 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
648 return FALSE;
649 val.function = GXcopy;
650 val.foreground = dc->w.textPixel;
651 val.background = dc->w.backgroundPixel;
652 XChangeGC(display, dc->u.x.gc, GCFunction|GCForeground|GCBackground, &val);
653 if (bmp->bitmap.bmBitsPixel == 1)
655 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
656 xsrc, ysrc, width, height,
657 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
658 return TRUE;
660 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
662 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
663 xsrc, ysrc, width, height,
664 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
665 return TRUE;
667 else return FALSE;
671 /**********************************************************************
672 * GRAPH_DrawReliefRect (Not a MSWin Call)
674 void GRAPH_DrawReliefRect( HDC hdc, RECT *rect, int highlight_size,
675 int shadow_size, BOOL pressed )
677 HBRUSH hbrushOld;
678 int i;
680 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
681 sysColorObjects.hbrushBtnHighlight );
682 for (i = 0; i < highlight_size; i++)
684 PatBlt( hdc, rect->left + i, rect->top,
685 1, rect->bottom - rect->top - i, PATCOPY );
686 PatBlt( hdc, rect->left, rect->top + i,
687 rect->right - rect->left - i, 1, PATCOPY );
690 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
691 sysColorObjects.hbrushBtnShadow );
692 for (i = 0; i < shadow_size; i++)
694 PatBlt( hdc, rect->right - i - 1, rect->top + i,
695 1, rect->bottom - rect->top - i, PATCOPY );
696 PatBlt( hdc, rect->left + i, rect->bottom - i - 1,
697 rect->right - rect->left - i, 1, PATCOPY );
700 SelectObject( hdc, hbrushOld );
704 /**********************************************************************
705 * Polyline (GDI.37)
707 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
709 register int i;
710 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
711 if (!dc)
713 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
714 if (!dc) return FALSE;
715 MF_MetaPoly(dc, META_POLYLINE, pt, count);
716 return TRUE;
719 if (DC_SetupGCForPen( dc ))
721 for (i = 0; i < count-1; i ++)
722 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
723 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
724 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
725 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
726 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
727 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
728 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
729 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
730 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
731 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
734 return (TRUE);
738 /**********************************************************************
739 * Polygon (GDI.36)
741 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
743 register int i;
744 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
745 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * (count+1));
747 if (!dc)
749 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
750 if (!dc) return FALSE;
751 MF_MetaPoly(dc, META_POLYGON, pt, count);
752 return TRUE;
755 for (i = 0; i < count; i++)
757 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
758 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
760 points[count] = points[0];
762 if (DC_SetupGCForBrush( dc ))
763 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
764 points, count+1, Complex, CoordModeOrigin);
766 if (DC_SetupGCForPen ( dc ))
767 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
768 points, count+1, CoordModeOrigin );
770 free( points );
771 return TRUE;
775 /**********************************************************************
776 * PolyPolygon (GDI.450)
778 BOOL PolyPolygon( HDC hdc, LPPOINT pt, LPINT counts, WORD polygons )
780 HRGN hrgn;
781 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
783 if (!dc)
785 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
786 if (!dc) return FALSE;
787 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
788 return TRUE;
790 /* FIXME: The points should be converted to device coords before */
791 /* creating the region. But as CreatePolyPolygonRgn is not */
792 /* really correct either, it doesn't matter much... */
793 /* At least the outline will be correct :-) */
794 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->w.polyFillMode );
795 PaintRgn( hdc, hrgn );
796 DeleteObject( hrgn );
798 /* Draw the outline of the polygons */
800 if (DC_SetupGCForPen ( dc ))
802 int i, j, max = 0;
803 XPoint *points;
805 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
806 points = (XPoint *) malloc( sizeof(XPoint) * (max+1) );
808 for (i = 0; i < polygons; i++)
810 for (j = 0; j < counts[i]; j++)
812 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
813 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
814 pt++;
816 points[j] = points[0];
817 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
818 points, j + 1, CoordModeOrigin );
820 free( points );
822 return TRUE;
826 /**********************************************************************
827 * GRAPH_InternalFloodFill
829 * Internal helper function for flood fill.
830 * (xorg,yorg) is the origin of the X image relative to the drawable.
831 * (x,y) is relative to the origin of the X image.
833 static void GRAPH_InternalFloodFill( XImage *image, DC *dc,
834 int x, int y,
835 int xOrg, int yOrg,
836 Pixel pixel, WORD fillType )
838 int left, right;
840 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
841 (XGetPixel(image,x,y) != pixel) : \
842 (XGetPixel(image,x,y) == pixel))
844 if (!TO_FLOOD(x,y)) return;
846 /* Find left and right boundaries */
848 left = right = x;
849 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
850 while ((right < image->width) && TO_FLOOD( right, y )) right++;
851 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
852 xOrg + left, yOrg + y, right-left, 1 );
854 /* Set the pixels of this line so we don't fill it again */
856 for (x = left; x < right; x++)
858 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
859 else XPutPixel( image, x, y, ~pixel );
862 /* Fill the line above */
864 if (--y >= 0)
866 x = left;
867 while (x < right)
869 while ((x < right) && !TO_FLOOD(x,y)) x++;
870 if (x >= right) break;
871 while ((x < right) && TO_FLOOD(x,y)) x++;
872 GRAPH_InternalFloodFill( image, dc, x-1, y,
873 xOrg, yOrg, pixel, fillType );
877 /* Fill the line below */
879 if ((y += 2) < image->height)
881 x = left;
882 while (x < right)
884 while ((x < right) && !TO_FLOOD(x,y)) x++;
885 if (x >= right) break;
886 while ((x < right) && TO_FLOOD(x,y)) x++;
887 GRAPH_InternalFloodFill( image, dc, x-1, y,
888 xOrg, yOrg, pixel, fillType );
891 #undef TO_FLOOD
895 /**********************************************************************
896 * ExtFloodFill (GDI.372)
898 BOOL ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, WORD fillType )
900 RECT rect;
901 Pixel pixel;
902 XImage *image;
903 DC *dc;
905 dprintf_graphics( stddeb, "ExtFloodFill %x %d,%d %06lx %d\n",
906 hdc, x, y, color, fillType );
907 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
908 if (!dc)
910 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
911 if (!dc) return FALSE;
912 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(color),
913 LOWORD(color));
914 return TRUE;
917 if (!PtVisible( hdc, x, y )) return FALSE;
918 if (GetClipBox( hdc, &rect ) == ERROR) return FALSE;
919 pixel = COLOR_ToPhysical( dc, color );
921 if (!(image = XGetImage( display, dc->u.x.drawable,
922 dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
923 rect.right - rect.left, rect.bottom - rect.top,
924 AllPlanes, ZPixmap ))) return FALSE;
926 if (DC_SetupGCForBrush( dc ))
928 /* ROP mode is always GXcopy for flood-fill */
929 XSetFunction( display, dc->u.x.gc, GXcopy );
930 /* We can pass anything except 0 as a region */
931 GRAPH_InternalFloodFill( image, dc,
932 XLPTODP(dc,x) - rect.left,
933 YLPTODP(dc,y) - rect.top,
934 dc->w.DCOrgX + rect.left,
935 dc->w.DCOrgY + rect.top,
936 pixel, fillType );
939 XDestroyImage( image );
940 return TRUE;
944 /**********************************************************************
945 * FloodFill (GDI.25)
947 BOOL FloodFill( HDC hdc, INT x, INT y, COLORREF color )
949 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );