Release 940912
[wine/multimedia.git] / windows / graphics.c
blobb3c9307252716ee83382333e42e4679ac75b5b1a
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 const int DC_XROPfunction[];
23 extern int COLOR_ToPhysical( DC *dc, COLORREF color );
25 static inline 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 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 if (!DC_SetupGCForPen( dc )) return TRUE;
150 xcenter = (right + left) / 2;
151 ycenter = (bottom + top) / 2;
152 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
153 (double)(xstart-xcenter)*(bottom-top) );
154 end_angle = atan2( (double)(ycenter-yend)*(right-left),
155 (double)(xend-xcenter)*(bottom-top) );
156 istart_angle = (int)(start_angle * 180 * 64 / PI);
157 idiff_angle = (int)((end_angle - start_angle) * 180 * 64 / PI );
158 if (idiff_angle <= 0) idiff_angle += 360 * 64;
159 if (left > right) swap_int( &left, &right );
160 if (top > bottom) swap_int( &top, &bottom );
162 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
163 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
164 right-left-1, bottom-top-1, istart_angle, idiff_angle );
165 if (!lines) return TRUE;
167 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
168 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
169 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
170 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
171 if (lines == 2)
173 points[2] = points[1];
174 points[1].x = dc->w.DCOrgX + xcenter;
175 points[1].y = dc->w.DCOrgY + ycenter;
177 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
178 points, lines+1, CoordModeOrigin );
179 return TRUE;
183 /***********************************************************************
184 * Arc (GDI.23)
186 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
187 int xstart, int ystart, int xend, int yend )
189 return GRAPH_DrawArc( hdc, left, top, right, bottom,
190 xstart, ystart, xend, yend, 0 );
194 /***********************************************************************
195 * Pie (GDI.26)
197 BOOL Pie( 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, 2 );
205 /***********************************************************************
206 * Chord (GDI.348)
208 BOOL Chord( 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, 1 );
216 /***********************************************************************
217 * Ellipse (GDI.24)
219 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
221 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
222 if (!dc)
224 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
225 if (!dc) return FALSE;
226 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
227 return 0;
230 left = XLPTODP( dc, left );
231 top = YLPTODP( dc, top );
232 right = XLPTODP( dc, right );
233 bottom = YLPTODP( dc, bottom );
234 if ((left == right) || (top == bottom)) return FALSE;
236 if (right < left)
237 swap_int(&right, &left);
239 if (bottom < top)
240 swap_int(&bottom, &top);
242 if (DC_SetupGCForBrush( dc ))
243 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
244 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
245 right-left-1, bottom-top-1, 0, 360*64 );
246 if (DC_SetupGCForPen( dc ))
247 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
248 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
249 right-left-1, bottom-top-1, 0, 360*64 );
250 return TRUE;
254 /***********************************************************************
255 * Rectangle (GDI.27)
257 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
259 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
260 if (!dc)
262 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
263 if (!dc) return FALSE;
264 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
265 return TRUE;
267 left = XLPTODP( dc, left );
268 top = YLPTODP( dc, top );
269 right = XLPTODP( dc, right );
270 bottom = YLPTODP( dc, bottom );
272 if (right < left)
273 swap_int(&right, &left);
275 if (bottom < top)
276 swap_int(&bottom, &top);
278 if ((left == right) || (top == bottom)) {
279 if (DC_SetupGCForPen( dc ))
280 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
281 dc->w.DCOrgX + left,
282 dc->w.DCOrgY + top,
283 dc->w.DCOrgX + right,
284 dc->w.DCOrgY + bottom);
285 return TRUE;
288 if (DC_SetupGCForBrush( dc ))
289 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
290 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
291 right-left, bottom-top );
292 if (DC_SetupGCForPen( dc ))
293 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
294 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
295 right-left-1, bottom-top-1 );
296 return TRUE;
300 /***********************************************************************
301 * RoundRect (GDI.28)
303 BOOL RoundRect( HDC hDC, short left, short top, short right, short bottom,
304 short ell_width, short ell_height)
306 int x1, y1, x2, y2;
307 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
308 if (!dc)
310 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
311 if (!dc) return FALSE;
312 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
313 ell_width, ell_height);
314 return TRUE;
317 printf("RoundRect(%d %d %d %d %d %d\n",
318 left, top, right, bottom, ell_width, ell_height);
320 x1 = XLPTODP(dc, left);
321 y1 = YLPTODP(dc, top);
322 x2 = XLPTODP(dc, right - ell_width);
323 y2 = YLPTODP(dc, bottom - ell_height);
324 if (DC_SetupGCForBrush(dc)) {
325 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
326 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
327 ell_width, ell_height, 90 * 64, 90 * 64);
328 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
329 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
330 ell_width, ell_height, 180 * 64, 90 * 64);
331 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
332 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
333 ell_width, ell_height, 270 * 64, 90 * 64);
334 XFillArc(display, dc->u.x.drawable, dc->u.x.gc,
335 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
336 ell_width, ell_height, 0, 90 * 64);
337 ell_width /= 2; ell_height /= 2;
338 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
339 dc->w.DCOrgX + left + ell_width, dc->w.DCOrgY + top,
340 right - left - 2 * ell_width, bottom - top);
341 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
342 dc->w.DCOrgX + left, dc->w.DCOrgY + top + ell_height,
343 ell_width, bottom - top - 2 * ell_height);
344 XFillRectangle(display, dc->u.x.drawable, dc->u.x.gc,
345 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top + ell_height,
346 ell_width, bottom - top - 2 * ell_height);
347 ell_width *= 2; ell_height *= 2;
349 if (DC_SetupGCForPen(dc)) {
350 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
351 dc->w.DCOrgX + x1, dc->w.DCOrgY + y1,
352 ell_width, ell_height, 90 * 64, 90 * 64);
353 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
354 dc->w.DCOrgX + x1, dc->w.DCOrgY + y2,
355 ell_width, ell_height, 180 * 64, 90 * 64);
356 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
357 dc->w.DCOrgX + x2, dc->w.DCOrgY + y2,
358 ell_width, ell_height, 270 * 64, 90 * 64);
359 XDrawArc(display, dc->u.x.drawable, dc->u.x.gc,
360 dc->w.DCOrgX + x2, dc->w.DCOrgY + y1,
361 ell_width, ell_height, 0, 90 * 64);
363 ell_width /= 2; ell_height /= 2;
364 MoveTo(hDC, left, top + ell_height);
365 LineTo(hDC, left, bottom - ell_height);
366 MoveTo(hDC, left + ell_width, bottom);
367 LineTo(hDC, right - ell_width, bottom);
368 MoveTo(hDC, right, bottom - ell_height);
369 LineTo(hDC, right, top + ell_height);
370 MoveTo(hDC, right - ell_width, top);
371 LineTo(hDC, left + ell_width, top);
372 return TRUE;
376 /***********************************************************************
377 * FillRect (USER.81)
379 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
381 HBRUSH prevBrush;
383 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
384 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
385 PatBlt( hdc, rect->left, rect->top,
386 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
387 SelectObject( hdc, prevBrush );
388 return 1;
392 /***********************************************************************
393 * InvertRect (USER.82)
395 void InvertRect( HDC hdc, LPRECT rect )
397 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
398 PatBlt( hdc, rect->left, rect->top,
399 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
403 /***********************************************************************
404 * FrameRect (USER.83)
406 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
408 HBRUSH prevBrush;
409 int left, top, right, bottom;
411 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
412 if (!dc) return FALSE;
414 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
415 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
417 left = XLPTODP( dc, rect->left );
418 top = YLPTODP( dc, rect->top );
419 right = XLPTODP( dc, rect->right );
420 bottom = YLPTODP( dc, rect->bottom );
422 if (DC_SetupGCForBrush( dc )) {
423 PatBlt( hdc, rect->left, rect->top, 1,
424 rect->bottom - rect->top, PATCOPY );
425 PatBlt( hdc, rect->right - 1, rect->top, 1,
426 rect->bottom - rect->top, PATCOPY );
427 PatBlt( hdc, rect->left, rect->top,
428 rect->right - rect->left, 1, PATCOPY );
429 PatBlt( hdc, rect->left, rect->bottom - 1,
430 rect->right - rect->left, 1, PATCOPY );
432 SelectObject( hdc, prevBrush );
433 return 1;
437 /***********************************************************************
438 * SetPixel (GDI.31)
440 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
442 int pixel;
443 PALETTEENTRY entry;
445 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
446 if (!dc)
448 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
449 if (!dc) return 0;
450 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
451 return 1;
454 x = dc->w.DCOrgX + XLPTODP( dc, x );
455 y = dc->w.DCOrgY + YLPTODP( dc, y );
456 pixel = COLOR_ToPhysical( dc, color );
457 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
459 XSetForeground( display, dc->u.x.gc, pixel );
460 XSetFunction( display, dc->u.x.gc, GXcopy );
461 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
463 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
467 /***********************************************************************
468 * GetPixel (GDI.83)
470 COLORREF GetPixel( HDC hdc, short x, short y )
472 PALETTEENTRY entry;
473 XImage * image;
475 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
476 if (!dc) return 0;
478 #ifdef SOLITAIRE_SPEED_HACK
479 return 0;
480 #endif
482 x = dc->w.DCOrgX + XLPTODP( dc, x );
483 y = dc->w.DCOrgY + YLPTODP( dc, y );
484 if ((x < 0) || (y < 0)) return 0;
486 if (!(dc->w.flags & DC_MEMORY))
488 XWindowAttributes win_attr;
490 if (!XGetWindowAttributes( display, dc->u.x.drawable, &win_attr ))
491 return 0;
492 if (win_attr.map_state != IsViewable) return 0;
493 if ((x >= win_attr.width) || (y >= win_attr.height)) return 0;
496 image = XGetImage( display, dc->u.x.drawable, x, y,
497 1, 1, AllPlanes, ZPixmap );
498 GetPaletteEntries( dc->w.hPalette, XGetPixel( image, 0, 0 ), 1, &entry );
499 XDestroyImage( image );
500 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
504 /***********************************************************************
505 * PaintRgn (GDI.43)
507 BOOL PaintRgn( HDC hdc, HRGN hrgn )
509 RECT box;
510 HRGN tmpVisRgn, prevVisRgn;
511 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
512 if (!dc) return FALSE;
514 /* Modify visible region */
516 prevVisRgn = SaveVisRgn( hdc );
517 if (prevVisRgn)
519 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
521 RestoreVisRgn( hdc );
522 return FALSE;
524 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
525 SelectVisRgn( hdc, tmpVisRgn );
526 DeleteObject( tmpVisRgn );
528 else SelectVisRgn( hdc, hrgn );
530 /* Fill the region */
532 GetClipBox( hdc, &box );
533 if (DC_SetupGCForBrush( dc ))
534 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
535 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
536 box.right-box.left, box.bottom-box.top );
538 /* Restore the visible region */
540 if (prevVisRgn) RestoreVisRgn( hdc );
541 else SelectVisRgn( hdc, 0 );
542 return TRUE;
546 /***********************************************************************
547 * FillRgn (GDI.40)
549 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
551 BOOL retval;
552 HBRUSH prevBrush = SelectObject( hdc, hbrush );
553 if (!prevBrush) return FALSE;
554 retval = PaintRgn( hdc, hrgn );
555 SelectObject( hdc, prevBrush );
556 return retval;
560 /***********************************************************************
561 * InvertRgn (GDI.42)
563 BOOL InvertRgn( HDC hdc, HRGN hrgn )
565 HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
566 WORD prevROP = SetROP2( hdc, R2_NOT );
567 BOOL retval = PaintRgn( hdc, hrgn );
568 SelectObject( hdc, prevBrush );
569 SetROP2( hdc, prevROP );
570 return retval;
574 /***********************************************************************
575 * DrawFocusRect (USER.466)
577 void DrawFocusRect( HDC hdc, LPRECT rc )
579 HPEN hOldPen;
580 int oldDrawMode, oldBkMode;
581 int left, top, right, bottom;
582 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
583 if (!dc) return;
585 left = XLPTODP( dc, rc->left );
586 top = YLPTODP( dc, rc->top );
587 right = XLPTODP( dc, rc->right );
588 bottom = YLPTODP( dc, rc->bottom );
590 hOldPen = (HPEN)SelectObject(hdc, sysColorObjects.hpenWindowText );
591 oldDrawMode = SetROP2(hdc, R2_XORPEN);
592 oldBkMode = SetBkMode(hdc, TRANSPARENT);
594 if (DC_SetupGCForPen( dc ))
595 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
596 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
597 right-left-1, bottom-top-1 );
599 SetBkMode(hdc, oldBkMode);
600 SetROP2(hdc, oldDrawMode);
601 SelectObject(hdc, (HANDLE)hOldPen);
605 /**********************************************************************
606 * GRAPH_DrawBitmap
608 * Short-cut function to blit a bitmap into a device.
609 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
611 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
612 int xsrc, int ysrc, int width, int height, int rop )
614 XGCValues val;
615 BITMAPOBJ *bmp;
616 DC *dc;
618 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
619 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
620 return FALSE;
621 val.function = DC_XROPfunction[(rop >> 16) & 0x0f];
622 val.foreground = dc->w.textPixel;
623 val.background = dc->w.backgroundPixel;
624 XChangeGC(display, dc->u.x.gc, GCFunction|GCForeground|GCBackground, &val);
625 if (bmp->bitmap.bmBitsPixel == 1)
627 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
628 xsrc, ysrc, width, height,
629 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
630 return TRUE;
632 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
634 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
635 xsrc, ysrc, width, height,
636 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
637 return TRUE;
639 else return FALSE;
643 /**********************************************************************
644 * DrawReliefRect (Not a MSWin Call)
646 void DrawReliefRect( HDC hdc, RECT rect, int thickness, BOOL pressed )
648 HBRUSH hbrushOld;
649 int i;
651 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
652 sysColorObjects.hbrushBtnHighlight );
653 for (i = 0; i < thickness; i++)
655 PatBlt( hdc, rect.left + i, rect.top,
656 1, rect.bottom - rect.top - i, PATCOPY );
657 PatBlt( hdc, rect.left, rect.top + i,
658 rect.right - rect.left - i, 1, PATCOPY );
661 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
662 sysColorObjects.hbrushBtnShadow );
663 for (i = 0; i < thickness; i++)
665 PatBlt( hdc, rect.right - i - 1, rect.top + i,
666 1, rect.bottom - rect.top - i, PATCOPY );
667 PatBlt( hdc, rect.left + i, rect.bottom - i - 1,
668 rect.right - rect.left - i, 1, PATCOPY );
671 SelectObject( hdc, hbrushOld );
675 /**********************************************************************
676 * Polyline (GDI.37)
678 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
680 register int i;
681 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
682 if (!dc)
684 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
685 if (!dc) return FALSE;
686 MF_MetaPoly(dc, META_POLYLINE, pt, count);
687 return TRUE;
690 if (DC_SetupGCForPen( dc ))
692 for (i = 0; i < count-1; i ++)
693 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
694 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
695 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
696 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
697 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
698 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
699 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
700 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
701 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
702 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
705 return (TRUE);
709 /**********************************************************************
710 * Polygon (GDI.36)
712 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
714 register int i;
715 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
716 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * (count+1));
718 if (!dc)
720 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
721 if (!dc) return FALSE;
722 MF_MetaPoly(dc, META_POLYGON, pt, count);
723 return TRUE;
726 for (i = 0; i < count; i++)
728 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
729 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
731 points[count] = points[0];
733 if (DC_SetupGCForBrush( dc ))
734 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
735 points, count+1, Complex, CoordModeOrigin);
737 if (DC_SetupGCForPen ( dc ))
738 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
739 points, count+1, CoordModeOrigin );
741 free( points );
742 return TRUE;
746 /**********************************************************************
747 * PolyPolygon (GDI.450)
749 BOOL PolyPolygon( HDC hdc, LPPOINT pt, LPINT counts, WORD polygons )
751 int i;
752 HRGN hrgn;
753 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
755 if (!dc)
757 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
758 if (!dc) return FALSE;
759 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
760 return TRUE;
762 /* The points should be converted to device coords before */
763 /* creating the region. But as CreatePolyPolygonRgn is not */
764 /* really correct either, it doesn't matter much... */
765 /* At least the outline will be correct :-) */
766 hrgn = CreatePolyPolygonRgn( pt, counts, polygons, dc->w.polyFillMode );
767 PaintRgn( hdc, hrgn );
768 DeleteObject( hrgn );
770 /* Draw the outline of the polygons */
772 if (DC_SetupGCForPen ( dc ))
774 int i, j, max = 0;
775 XPoint *points;
777 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
778 points = (XPoint *) malloc( sizeof(XPoint) * (max+1) );
780 for (i = 0; i < polygons; i++)
782 for (j = 0; j < counts[i]; j++)
784 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
785 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
786 pt++;
788 points[j] = points[0];
789 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
790 points, j + 1, CoordModeOrigin );
792 free( points );
794 return TRUE;
798 /**********************************************************************
799 * FloodFill_rec -- FloodFill helper function
801 * Just does a recursive flood fill:
802 * this is /not/ efficent -- a better way would be to draw
803 * an entire line at a time, but this will do for now.
805 static BOOL FloodFill_rec(XImage *image, int x, int y,
806 int orgx, int orgy, int endx, int endy,
807 Pixel borderp, Pixel fillp)
809 Pixel testp;
811 if (x > endx || x < orgx || y > endy || y < orgy)
812 return FALSE;
813 XPutPixel(image, x, y, fillp);
815 if ((x+1 <= endx) && (y+1 <= endy)) {
816 testp = XGetPixel(image, x+1, y+1);
817 if (testp != borderp && testp != fillp)
818 FloodFill_rec(image, x+1, y+1, orgx, orgy,
819 endx, endy, borderp, fillp);
821 if ((x+1 <= endx) && (y-1 >= orgy)) {
822 testp = XGetPixel(image, x+1, y-1);
823 if (testp != borderp && testp != fillp)
824 FloodFill_rec(image, x+1, y-1, orgx, orgy,
825 endx, endy, borderp, fillp);
827 if ((x-1 >= orgx) && (y+1 <= endy)) {
828 testp = XGetPixel(image, x-1, y+1);
829 if (testp != borderp && testp != fillp)
830 FloodFill_rec(image, x-1, y+1, orgx, orgy,
831 endx, endy, borderp, fillp);
833 if ((x-1 >= orgx) && (y-1 >= orgy)) {
834 testp = XGetPixel(image, x-1, y-1);
835 if (testp != borderp && testp != fillp)
836 FloodFill_rec(image, x-1, y-1, orgx, orgy,
837 endx, endy, borderp, fillp);
839 return TRUE;
843 /**********************************************************************
844 * FloodFill (GDI.25)
846 BOOL FloodFill(HDC hdc, short x, short y, DWORD crColor)
848 Pixel boundrypixel;
849 int imagex, imagey;
850 XImage *image;
851 DC *dc;
853 #ifdef DEBUG_GRAPHICS
854 printf("FloodFill %x %d,%d %x\n", hdc, x, y, crColor);
855 #endif
856 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
857 if (!dc)
859 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
860 if (!dc) return FALSE;
861 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(crColor),
862 LOWORD(crColor));
863 return TRUE;
866 x = dc->w.DCOrgX + XLPTODP(dc, x);
867 y = dc->w.DCOrgY + YLPTODP(dc, y);
869 if (x < dc->w.DCOrgX || x > dc->w.DCOrgX + dc->w.DCSizeX ||
870 y < dc->w.DCOrgY || y > dc->w.DCOrgY + dc->w.DCSizeY)
871 return FALSE;
873 if (!DC_SetupGCForBrush(dc))
874 return FALSE;
876 boundrypixel = GetNearestPaletteIndex( dc->w.hPalette, crColor );
878 image = XGetImage(display, dc->u.x.drawable,
879 dc->w.DCOrgX, dc->w.DCOrgY,
880 dc->w.DCSizeX, dc->w.DCSizeY, AllPlanes, ZPixmap);
881 if (XGetPixel(image, x, y) == boundrypixel)
882 return FALSE;
883 if (!FloodFill_rec(image, x, y,
884 0, 0,
885 dc->w.DCSizeX-1,
886 dc->w.DCSizeY-1,
887 boundrypixel, dc->u.x.brush.pixel)) {
888 XDestroyImage(image);
889 return FALSE;
892 XPutImage(display, dc->u.x.drawable, dc->u.x.gc, image,
893 0, 0,
894 dc->w.DCOrgX, dc->w.DCOrgY,
895 dc->w.DCSizeX, dc->w.DCSizeY);
896 XDestroyImage(image);
898 return TRUE;