Release 940714
[wine/multimedia.git] / windows / graphics.c
blob089e3cc652045dee431c092e5ba0943d3aaa6886
1 /*
2 * GDI graphics operations
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
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
18 #include "gdi.h"
19 #include "syscolor.h"
21 extern int COLOR_ToPhysical( DC *dc, COLORREF color );
23 static inline 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 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 if (!DC_SetupGCForPen( dc )) return TRUE;
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 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
161 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
162 right-left-1, bottom-top-1, istart_angle, idiff_angle );
163 if (!lines) return TRUE;
165 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
166 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
167 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
168 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
169 if (lines == 2)
171 points[2] = points[1];
172 points[1].x = dc->w.DCOrgX + xcenter;
173 points[1].y = dc->w.DCOrgY + ycenter;
175 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
176 points, lines+1, CoordModeOrigin );
177 return TRUE;
181 /***********************************************************************
182 * Arc (GDI.23)
184 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
185 int xstart, int ystart, int xend, int yend )
187 return GRAPH_DrawArc( hdc, left, top, right, bottom,
188 xstart, ystart, xend, yend, 0 );
192 /***********************************************************************
193 * Pie (GDI.26)
195 BOOL Pie( 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, 2 );
203 /***********************************************************************
204 * Chord (GDI.348)
206 BOOL Chord( 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, 1 );
214 /***********************************************************************
215 * Ellipse (GDI.24)
217 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
219 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
220 if (!dc)
222 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
223 if (!dc) return FALSE;
224 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
225 return 0;
228 left = XLPTODP( dc, left );
229 top = YLPTODP( dc, top );
230 right = XLPTODP( dc, right );
231 bottom = YLPTODP( dc, bottom );
232 if ((left == right) || (top == bottom)) return FALSE;
234 if (right < left)
235 swap_int(&right, &left);
237 if (bottom < top)
238 swap_int(&bottom, &top);
240 if (DC_SetupGCForBrush( dc ))
241 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
242 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
243 right-left-1, bottom-top-1, 0, 360*64 );
244 if (DC_SetupGCForPen( dc ))
245 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
246 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
247 right-left-1, bottom-top-1, 0, 360*64 );
248 return TRUE;
252 /***********************************************************************
253 * Rectangle (GDI.27)
255 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
257 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
258 if (!dc)
260 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
261 if (!dc) return FALSE;
262 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
263 return TRUE;
265 left = XLPTODP( dc, left );
266 top = YLPTODP( dc, top );
267 right = XLPTODP( dc, right );
268 bottom = YLPTODP( dc, bottom );
270 if (right < left)
271 swap_int(&right, &left);
273 if (bottom < top)
274 swap_int(&bottom, &top);
276 if ((left == right) || (top == bottom)) {
277 if (DC_SetupGCForPen( dc ))
278 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
279 dc->w.DCOrgX + left,
280 dc->w.DCOrgY + top,
281 dc->w.DCOrgX + right,
282 dc->w.DCOrgY + bottom);
283 return TRUE;
286 if (DC_SetupGCForBrush( dc ))
287 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
288 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
289 right-left, bottom-top );
290 if (DC_SetupGCForPen( dc ))
291 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
292 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
293 right-left-1, bottom-top-1 );
294 return TRUE;
298 /***********************************************************************
299 * RoundRect (GDI.28)
301 BOOL RoundRect( HDC hDC, short left, short top, short right, short bottom,
302 short ell_width, short ell_height)
304 int x1, y1, x2, y2;
305 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
306 if (!dc)
308 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
309 if (!dc) return FALSE;
310 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
311 ell_width, ell_height);
312 return TRUE;
315 printf("RoundRect(%d %d %d %d %d %d\n",
316 left, top, right, bottom, ell_width, ell_height);
318 x1 = XLPTODP(dc, left);
319 y1 = YLPTODP(dc, top);
320 x2 = XLPTODP(dc, right - ell_width);
321 y2 = YLPTODP(dc, bottom - ell_height);
322 if (DC_SetupGCForBrush(dc)) {
323 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
324 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
325 ell_width, ell_height, 90 * 64, 90 * 64);
326 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
327 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
328 ell_width, ell_height, 180 * 64, 90 * 64);
329 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
330 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
331 ell_width, ell_height, 270 * 64, 90 * 64);
332 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
333 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
334 ell_width, ell_height, 0, 90 * 64);
335 ell_width /= 2; ell_height /= 2;
336 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
337 dc->w.DCOrgX + left + ell_width, dc->w.DCOrgY + top,
338 right - left - 2 * ell_width, bottom - top);
339 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
340 dc->w.DCOrgX + left, dc->w.DCOrgY + top + ell_height,
341 ell_width, bottom - top - 2 * ell_height);
342 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
343 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top + ell_height,
344 ell_width, bottom - top - 2 * ell_height);
345 ell_width *= 2; ell_height *= 2;
347 if (DC_SetupGCForPen(dc)) {
348 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
349 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
350 ell_width, ell_height, 90 * 64, 90 * 64);
351 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
352 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
353 ell_width, ell_height, 180 * 64, 90 * 64);
354 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
355 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
356 ell_width, ell_height, 270 * 64, 90 * 64);
357 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
358 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
359 ell_width, ell_height, 0, 90 * 64);
361 ell_width /= 2; ell_height /= 2;
362 MoveTo(hDC, left, top + ell_height);
363 LineTo(hDC, left, bottom - ell_height);
364 MoveTo(hDC, left + ell_width, bottom);
365 LineTo(hDC, right - ell_width, bottom);
366 MoveTo(hDC, right, bottom - ell_height);
367 LineTo(hDC, right, top + ell_height);
368 MoveTo(hDC, right - ell_width, top);
369 LineTo(hDC, left + ell_width, top);
370 return TRUE;
374 /***********************************************************************
375 * FillRect (USER.81)
377 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
379 HBRUSH prevBrush;
381 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
382 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
383 PatBlt( hdc, rect->left, rect->top,
384 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
385 SelectObject( hdc, prevBrush );
386 return 1;
390 /***********************************************************************
391 * InvertRect (USER.82)
393 void InvertRect( HDC hdc, LPRECT rect )
395 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
396 PatBlt( hdc, rect->left, rect->top,
397 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
401 /***********************************************************************
402 * FrameRect (USER.83)
404 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
406 HBRUSH prevBrush;
407 int left, top, right, bottom;
409 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
410 if (!dc) return FALSE;
412 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
413 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
415 left = XLPTODP( dc, rect->left );
416 top = YLPTODP( dc, rect->top );
417 right = XLPTODP( dc, rect->right );
418 bottom = YLPTODP( dc, rect->bottom );
420 if (DC_SetupGCForBrush( dc )) {
421 PatBlt( hdc, rect->left, rect->top, 1,
422 rect->bottom - rect->top, PATCOPY );
423 PatBlt( hdc, rect->right - 1, rect->top, 1,
424 rect->bottom - rect->top, PATCOPY );
425 PatBlt( hdc, rect->left, rect->top,
426 rect->right - rect->left, 1, PATCOPY );
427 PatBlt( hdc, rect->left, rect->bottom - 1,
428 rect->right - rect->left, 1, PATCOPY );
430 SelectObject( hdc, prevBrush );
431 return 1;
435 /***********************************************************************
436 * SetPixel (GDI.31)
438 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
440 int pixel;
441 PALETTEENTRY entry;
443 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
444 if (!dc)
446 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
447 if (!dc) return 0;
448 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
449 return 1;
452 x = dc->w.DCOrgX + XLPTODP( dc, x );
453 y = dc->w.DCOrgY + YLPTODP( dc, y );
454 pixel = COLOR_ToPhysical( dc, color );
455 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
457 XSetForeground( display, dc->u.x.gc, pixel );
458 XSetFunction( display, dc->u.x.gc, GXcopy );
459 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
461 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
465 /***********************************************************************
466 * GetPixel (GDI.83)
468 COLORREF GetPixel( HDC hdc, short x, short y )
470 PALETTEENTRY entry;
471 XImage * image;
473 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
474 if (!dc) return 0;
476 x = dc->w.DCOrgX + XLPTODP( dc, x );
477 y = dc->w.DCOrgY + YLPTODP( dc, y );
478 if ((x < 0) || (y < 0)) return 0;
480 if (!(dc->w.flags & DC_MEMORY))
482 XWindowAttributes win_attr;
484 if (!XGetWindowAttributes( display, dc->u.x.drawable, &win_attr ))
485 return 0;
486 if (win_attr.map_state != IsViewable) return 0;
487 if ((x >= win_attr.width) || (y >= win_attr.height)) return 0;
490 image = XGetImage( display, dc->u.x.drawable, x, y,
491 1, 1, AllPlanes, ZPixmap );
492 GetPaletteEntries( dc->w.hPalette, XGetPixel( image, 0, 0 ), 1, &entry );
493 XDestroyImage( image );
494 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
498 /***********************************************************************
499 * PaintRgn (GDI.43)
501 BOOL PaintRgn( HDC hdc, HRGN hrgn )
503 RECT box;
504 HRGN tmpVisRgn, prevVisRgn;
505 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
506 if (!dc) return FALSE;
508 /* Modify visible region */
510 prevVisRgn = SaveVisRgn( hdc );
511 if (prevVisRgn)
513 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
515 RestoreVisRgn( hdc );
516 return FALSE;
518 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
519 SelectVisRgn( hdc, tmpVisRgn );
520 DeleteObject( tmpVisRgn );
522 else SelectVisRgn( hdc, hrgn );
524 /* Fill the region */
526 GetClipBox( hdc, &box );
527 if (DC_SetupGCForBrush( dc ))
528 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
529 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
530 box.right-box.left, box.bottom-box.top );
532 /* Restore the visible region */
534 if (prevVisRgn) RestoreVisRgn( hdc );
535 else SelectVisRgn( hdc, 0 );
536 return TRUE;
540 /***********************************************************************
541 * FillRgn (GDI.40)
543 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
545 BOOL retval;
546 HBRUSH prevBrush = SelectObject( hdc, hbrush );
547 if (!prevBrush) return FALSE;
548 retval = PaintRgn( hdc, hrgn );
549 SelectObject( hdc, prevBrush );
550 return retval;
554 /***********************************************************************
555 * DrawFocusRect (USER.466)
557 void DrawFocusRect( HDC hdc, LPRECT rc )
559 HPEN hOldPen;
560 int oldDrawMode, oldBkMode;
561 int left, top, right, bottom;
562 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
563 if (!dc) return;
565 left = XLPTODP( dc, rc->left );
566 top = YLPTODP( dc, rc->top );
567 right = XLPTODP( dc, rc->right );
568 bottom = YLPTODP( dc, rc->bottom );
570 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
571 oldDrawMode = SetROP2(hdc, R2_XORPEN);
572 oldBkMode = SetBkMode(hdc, TRANSPARENT);
574 if (DC_SetupGCForPen( dc ))
575 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
576 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
577 right-left-1, bottom-top-1 );
579 SetBkMode(hdc, oldBkMode);
580 SetROP2(hdc, oldDrawMode);
581 SelectObject(hdc, (HANDLE)hOldPen);
585 /**********************************************************************
586 * DrawReliefRect (Not a MSWin Call)
588 void DrawReliefRect( HDC hdc, RECT rect, int thickness, BOOL pressed )
590 HBRUSH hbrushOld;
591 int i;
593 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
594 sysColorObjects.hbrushBtnHighlight );
595 for (i = 0; i < thickness; i++)
597 PatBlt( hdc, rect.left + i, rect.top,
598 1, rect.bottom - rect.top - i, PATCOPY );
599 PatBlt( hdc, rect.left, rect.top + i,
600 rect.right - rect.left - i, 1, PATCOPY );
603 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
604 sysColorObjects.hbrushBtnShadow );
605 for (i = 0; i < thickness; i++)
607 PatBlt( hdc, rect.right - i - 1, rect.top + i,
608 1, rect.bottom - rect.top - i, PATCOPY );
609 PatBlt( hdc, rect.left + i, rect.bottom - i - 1,
610 rect.right - rect.left - i, 1, PATCOPY );
613 SelectObject( hdc, hbrushOld );
617 /**********************************************************************
618 * Polyline (GDI.37)
620 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
622 register int i;
623 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
624 if (!dc)
626 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
627 if (!dc) return FALSE;
628 MF_MetaPoly(dc, META_POLYLINE, pt, count);
629 return TRUE;
632 if (DC_SetupGCForPen( dc ))
634 for (i = 0; i < count-1; i ++)
635 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
636 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
637 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
638 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
639 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
640 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
641 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
642 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
643 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
644 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
647 return (TRUE);
651 /**********************************************************************
652 * Polygon (GDI.36)
654 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
656 register int i;
657 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
658 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * (count+1));
660 if (!dc)
662 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
663 if (!dc) return FALSE;
664 MF_MetaPoly(dc, META_POLYGON, pt, count);
665 return TRUE;
668 for (i = 0; i < count; i++)
670 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
671 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
673 points[count] = points[0];
675 if (DC_SetupGCForBrush( dc ))
676 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
677 points, count+1, Complex, CoordModeOrigin);
679 if (DC_SetupGCForPen ( dc ))
680 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
681 points, count+1, CoordModeOrigin );
683 free( points );
684 return TRUE;
688 /**********************************************************************
689 * PolyPolygon (GDI.450)
691 BOOL PolyPolygon( HDC hdc, LPPOINT pt, LPINT counts, WORD polygons )
693 int i;
694 HRGN hrgn;
695 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
697 if (!dc)
699 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
700 if (!dc) return FALSE;
701 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
702 return TRUE;
704 /* The points should be converted to device coords before */
705 /* creating the region. But as CreatePolyPolygonRgn is not */
706 /* really correct either, it doesn't matter much... */
707 /* At least the outline will be correct :-) */
708 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->w.polyFillMode );
709 PaintRgn( hdc, hrgn );
710 DeleteObject( hrgn );
712 /* Draw the outline of the polygons */
714 if (DC_SetupGCForPen ( dc ))
716 int i, j, max = 0;
717 XPoint *points;
719 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
720 points = (XPoint *) malloc( sizeof(XPoint) * (max+1) );
722 for (i = 0; i < polygons; i++)
724 for (j = 0; j < counts[i]; j++)
726 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
727 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
728 pt++;
730 points[j] = points[0];
731 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
732 points, j + 1, CoordModeOrigin );
734 free( points );
736 return TRUE;
740 /**********************************************************************
741 * FloodFill_rec -- FloodFill helper function
743 * Just does a recursive flood fill:
744 * this is /not/ efficent -- a better way would be to draw
745 * an entire line at a time, but this will do for now.
747 static BOOL FloodFill_rec(XImage *image, int x, int y,
748 int orgx, int orgy, int endx, int endy,
749 Pixel borderp, Pixel fillp)
751 Pixel testp;
753 if (x > endx || x < orgx || y > endy || y < orgy)
754 return FALSE;
755 XPutPixel(image, x, y, fillp);
757 if ((x+1 <= endx) && (y+1 <= endy)) {
758 testp = XGetPixel(image, x+1, y+1);
759 if (testp != borderp && testp != fillp)
760 FloodFill_rec(image, x+1, y+1, orgx, orgy,
761 endx, endy, borderp, fillp);
763 if ((x+1 <= endx) && (y-1 >= orgy)) {
764 testp = XGetPixel(image, x+1, y-1);
765 if (testp != borderp && testp != fillp)
766 FloodFill_rec(image, x+1, y-1, orgx, orgy,
767 endx, endy, borderp, fillp);
769 if ((x-1 >= orgx) && (y+1 <= endy)) {
770 testp = XGetPixel(image, x-1, y+1);
771 if (testp != borderp && testp != fillp)
772 FloodFill_rec(image, x-1, y+1, orgx, orgy,
773 endx, endy, borderp, fillp);
775 if ((x-1 >= orgx) && (y-1 >= orgy)) {
776 testp = XGetPixel(image, x-1, y-1);
777 if (testp != borderp && testp != fillp)
778 FloodFill_rec(image, x-1, y-1, orgx, orgy,
779 endx, endy, borderp, fillp);
781 return TRUE;
785 /**********************************************************************
786 * FloodFill (GDI.25)
788 BOOL FloodFill(HDC hdc, short x, short y, DWORD crColor)
790 Pixel boundrypixel;
791 int imagex, imagey;
792 XImage *image;
793 DC *dc;
795 #ifdef DEBUG_GRAPHICS
796 printf("FloodFill %x %d,%d %x\n", hdc, x, y, crColor);
797 #endif
798 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
799 if (!dc)
801 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
802 if (!dc) return FALSE;
803 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(crColor),
804 LOWORD(crColor));
805 return TRUE;
808 x = dc->w.DCOrgX + XLPTODP(dc, x);
809 y = dc->w.DCOrgY + YLPTODP(dc, y);
811 if (x < dc->w.DCOrgX || x > dc->w.DCOrgX + dc->w.DCSizeX ||
812 y < dc->w.DCOrgY || y > dc->w.DCOrgY + dc->w.DCSizeY)
813 return FALSE;
815 if (!DC_SetupGCForBrush(dc))
816 return FALSE;
818 boundrypixel = GetNearestPaletteIndex( dc->w.hPalette, crColor );
820 image = XGetImage(display, dc->u.x.drawable,
821 dc->w.DCOrgX, dc->w.DCOrgY,
822 dc->w.DCSizeX, dc->w.DCSizeY, AllPlanes, ZPixmap);
823 if (XGetPixel(image, x, y) == boundrypixel)
824 return FALSE;
825 if (!FloodFill_rec(image, x, y,
826 0, 0,
827 dc->w.DCSizeX-1,
828 dc->w.DCSizeY-1,
829 boundrypixel, dc->u.x.brush.pixel)) {
830 XDestroyImage(image);
831 return FALSE;
834 XPutImage(display, dc->u.x.drawable, dc->u.x.gc, image,
835 0, 0,
836 dc->w.DCOrgX, dc->w.DCOrgY,
837 dc->w.DCSizeX, dc->w.DCSizeY);
838 XDestroyImage(image);
840 return TRUE;