Release 960712
[wine/multimedia.git] / windows / graphics.c
blobf1cb9e7a4fdc452a00193af4fcb3009d6b0376e0
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 "callback.h"
18 #include "metafile.h"
19 #include "syscolor.h"
20 #include "stddebug.h"
21 #include "color.h"
22 #include "region.h"
23 #include "debug.h"
24 #include "xmalloc.h"
26 /***********************************************************************
27 * LineTo (GDI.19)
29 BOOL LineTo( HDC hdc, short x, short y )
31 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
32 if (!dc)
34 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
35 if (!dc) return FALSE;
36 MF_MetaParam2(dc, META_LINETO, x, y);
37 return TRUE;
40 if (DC_SetupGCForPen( dc ))
41 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
42 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
43 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
44 dc->w.DCOrgX + XLPTODP( dc, x ),
45 dc->w.DCOrgY + YLPTODP( dc, y ) );
46 dc->w.CursPosX = x;
47 dc->w.CursPosY = y;
48 return TRUE;
52 /***********************************************************************
53 * MoveTo (GDI.20)
55 DWORD MoveTo( HDC hdc, short x, short y )
57 short oldx, oldy;
58 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
59 if (!dc)
61 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
62 if (!dc) return FALSE;
63 MF_MetaParam2(dc, META_MOVETO, x, y);
64 return 0;
67 oldx = dc->w.CursPosX;
68 oldy = dc->w.CursPosY;
69 dc->w.CursPosX = x;
70 dc->w.CursPosY = y;
71 return oldx | (oldy << 16);
75 /***********************************************************************
76 * MoveToEx16 (GDI.483)
78 BOOL16 MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
80 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
81 if (!dc) return FALSE;
82 if (pt)
84 pt->x = dc->w.CursPosX;
85 pt->y = dc->w.CursPosY;
87 dc->w.CursPosX = x;
88 dc->w.CursPosY = y;
89 return TRUE;
93 /***********************************************************************
94 * MoveToEx32 (GDI32.254)
96 BOOL32 MoveToEx32( HDC32 hdc, INT32 x, INT32 y, LPPOINT32 pt )
98 POINT16 pt16;
99 if (!MoveToEx16( (HDC16)hdc, (INT16)x, (INT16)y, &pt16 )) return FALSE;
100 if (pt) CONV_POINT16TO32( &pt16, pt );
101 return TRUE;
105 /***********************************************************************
106 * GRAPH_DrawArc
108 * Helper functions for Arc(), Chord() and Pie().
109 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
111 static BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom,
112 int xstart, int ystart, int xend, int yend, int lines )
114 int xcenter, ycenter, istart_angle, idiff_angle, tmp;
115 double start_angle, end_angle;
116 XPoint points[3];
117 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
118 if (!dc)
120 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
121 if (!dc) return FALSE;
122 switch (lines)
124 case 0:
125 MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
126 xstart, ystart, xend, yend);
127 break;
129 case 1:
130 MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
131 xstart, ystart, xend, yend);
132 break;
134 case 2:
135 MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
136 xstart, ystart, xend, yend);
137 break;
139 return 0;
142 left = XLPTODP( dc, left );
143 top = YLPTODP( dc, top );
144 right = XLPTODP( dc, right );
145 bottom = YLPTODP( dc, bottom );
146 xstart = XLPTODP( dc, xstart );
147 ystart = YLPTODP( dc, ystart );
148 xend = XLPTODP( dc, xend );
149 yend = YLPTODP( dc, yend );
150 if ((left == right) || (top == bottom)) return FALSE;
152 xcenter = (right + left) / 2;
153 ycenter = (bottom + top) / 2;
154 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
155 (double)(xstart-xcenter)*(bottom-top) );
156 end_angle = atan2( (double)(ycenter-yend)*(right-left),
157 (double)(xend-xcenter)*(bottom-top) );
158 istart_angle = (int)(start_angle * 180 * 64 / PI);
159 idiff_angle = (int)((end_angle - start_angle) * 180 * 64 / PI );
160 if (idiff_angle <= 0) idiff_angle += 360 * 64;
161 if (left > right) { tmp=left; left=right; right=tmp; }
162 if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
164 /* Fill arc with brush if Chord() or Pie() */
166 if ((lines > 0) && DC_SetupGCForBrush( dc ))
168 XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
169 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
170 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
171 right-left-1, bottom-top-1, istart_angle, idiff_angle );
174 /* Draw arc and lines */
176 if (!DC_SetupGCForPen( dc )) return TRUE;
177 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
178 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
179 right-left-1, bottom-top-1, istart_angle, idiff_angle );
180 if (!lines) return TRUE;
182 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
183 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
184 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
185 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
186 if (lines == 2)
188 points[2] = points[1];
189 points[1].x = dc->w.DCOrgX + xcenter;
190 points[1].y = dc->w.DCOrgY + ycenter;
192 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
193 points, lines+1, CoordModeOrigin );
194 return TRUE;
198 /***********************************************************************
199 * Arc (GDI.23)
201 BOOL Arc( HDC hdc, INT left, INT top, INT right, INT bottom,
202 INT xstart, INT ystart, INT xend, INT yend )
204 return GRAPH_DrawArc( hdc, left, top, right, bottom,
205 xstart, ystart, xend, yend, 0 );
209 /***********************************************************************
210 * Pie (GDI.26)
212 BOOL Pie( HDC hdc, INT left, INT top, INT right, INT bottom,
213 INT xstart, INT ystart, INT xend, INT yend )
215 return GRAPH_DrawArc( hdc, left, top, right, bottom,
216 xstart, ystart, xend, yend, 2 );
220 /***********************************************************************
221 * Chord (GDI.348)
223 BOOL Chord( HDC hdc, INT left, INT top, INT right, INT bottom,
224 INT xstart, INT ystart, INT xend, INT yend )
226 return GRAPH_DrawArc( hdc, left, top, right, bottom,
227 xstart, ystart, xend, yend, 1 );
231 /***********************************************************************
232 * Ellipse (GDI.24)
234 BOOL Ellipse( HDC hdc, INT left, INT top, INT right, INT bottom )
236 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
237 if (!dc)
239 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
240 if (!dc) return FALSE;
241 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
242 return 0;
245 left = XLPTODP( dc, left );
246 top = YLPTODP( dc, top );
247 right = XLPTODP( dc, right );
248 bottom = YLPTODP( dc, bottom );
249 if ((left == right) || (top == bottom)) return FALSE;
251 if (right < left) { INT tmp = right; right = left; left = tmp; }
252 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
254 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
255 (dc->u.x.pen.width < right-left-1) &&
256 (dc->u.x.pen.width < bottom-top-1))
258 left += dc->u.x.pen.width / 2;
259 right -= (dc->u.x.pen.width + 1) / 2;
260 top += dc->u.x.pen.width / 2;
261 bottom -= (dc->u.x.pen.width + 1) / 2;
264 if (DC_SetupGCForBrush( dc ))
265 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
266 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
267 right-left-1, bottom-top-1, 0, 360*64 );
268 if (DC_SetupGCForPen( dc ))
269 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
270 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
271 right-left-1, bottom-top-1, 0, 360*64 );
272 return TRUE;
276 /***********************************************************************
277 * Rectangle (GDI.27)
279 BOOL Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom )
281 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
282 if (!dc)
284 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
285 if (!dc) return FALSE;
286 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
287 return TRUE;
289 left = XLPTODP( dc, left );
290 top = YLPTODP( dc, top );
291 right = XLPTODP( dc, right );
292 bottom = YLPTODP( dc, bottom );
294 if (right < left) { INT tmp = right; right = left; left = tmp; }
295 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
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, INT left, INT top, INT right, INT bottom,
334 INT ell_width, INT ell_height )
336 DC * dc = (DC *) GDI_GetObjPtr(hDC, DC_MAGIC);
337 if (!dc)
339 dc = (DC *)GDI_GetObjPtr(hDC, METAFILE_DC_MAGIC);
340 if (!dc) return FALSE;
341 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
342 ell_width, ell_height);
343 return TRUE;
345 dprintf_graphics(stddeb, "RoundRect(%d %d %d %d %d %d\n",
346 left, top, right, bottom, ell_width, ell_height);
348 left = XLPTODP( dc, left );
349 top = YLPTODP( dc, top );
350 right = XLPTODP( dc, right );
351 bottom = YLPTODP( dc, bottom );
352 ell_width = abs( ell_width * dc->w.VportExtX / dc->w.WndExtX );
353 ell_height = abs( ell_height * dc->w.VportExtY / dc->w.WndExtY );
355 /* Fix the coordinates */
357 if (right < left) { INT tmp = right; right = left; left = tmp; }
358 if (bottom < top) { INT tmp = bottom; bottom = top; top = tmp; }
359 if (ell_width > right - left) ell_width = right - left;
360 if (ell_height > bottom - top) ell_height = bottom - top;
362 if (DC_SetupGCForBrush( dc ))
364 if (ell_width && ell_height)
366 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
367 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
368 ell_width, ell_height, 90 * 64, 90 * 64 );
369 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
370 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
371 ell_width, ell_height, 180 * 64, 90 * 64 );
372 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
373 dc->w.DCOrgX + right - ell_width,
374 dc->w.DCOrgY + bottom - ell_height,
375 ell_width, ell_height, 270 * 64, 90 * 64 );
376 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
377 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
378 ell_width, ell_height, 0, 90 * 64 );
380 if (ell_width < right - left)
382 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
383 dc->w.DCOrgX + left + ell_width / 2,
384 dc->w.DCOrgY + top,
385 right - left - ell_width, ell_height / 2 );
386 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
387 dc->w.DCOrgX + left + ell_width / 2,
388 dc->w.DCOrgY + bottom - (ell_height+1) / 2,
389 right - left - ell_width, (ell_height+1) / 2 );
391 if (ell_height < bottom - top)
393 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
394 dc->w.DCOrgX + left,
395 dc->w.DCOrgY + top + ell_height / 2,
396 right - left, bottom - top - ell_height );
399 if (DC_SetupGCForPen(dc))
401 if (ell_width && ell_height)
403 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
404 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
405 ell_width, ell_height, 90 * 64, 90 * 64 );
406 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
407 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
408 ell_width, ell_height, 180 * 64, 90 * 64 );
409 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
410 dc->w.DCOrgX + right - ell_width,
411 dc->w.DCOrgY + bottom - ell_height,
412 ell_width, ell_height, 270 * 64, 90 * 64 );
413 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
414 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
415 ell_width, ell_height, 0, 90 * 64 );
417 if (ell_width < right - left)
419 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
420 dc->w.DCOrgX + left + ell_width / 2,
421 dc->w.DCOrgY + top,
422 dc->w.DCOrgX + right - ell_width / 2,
423 dc->w.DCOrgY + top );
424 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
425 dc->w.DCOrgX + left + ell_width / 2,
426 dc->w.DCOrgY + bottom,
427 dc->w.DCOrgX + right - ell_width / 2,
428 dc->w.DCOrgY + bottom );
430 if (ell_height < bottom - top)
432 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
433 dc->w.DCOrgX + right,
434 dc->w.DCOrgY + top + ell_height / 2,
435 dc->w.DCOrgX + right,
436 dc->w.DCOrgY + bottom - ell_height / 2 );
437 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
438 dc->w.DCOrgX + left,
439 dc->w.DCOrgY + top + ell_height / 2,
440 dc->w.DCOrgX + left,
441 dc->w.DCOrgY + bottom - ell_height / 2 );
444 return TRUE;
448 /***********************************************************************
449 * FillRect16 (USER.81)
451 INT16 FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
453 HBRUSH prevBrush;
455 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
456 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
457 PatBlt( hdc, rect->left, rect->top,
458 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
459 SelectObject( hdc, prevBrush );
460 return 1;
464 /***********************************************************************
465 * FillRect32 (USER32.196)
467 INT32 FillRect32( HDC32 hdc, const RECT32 *rect, HBRUSH32 hbrush )
469 HBRUSH prevBrush;
471 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
472 if (!(prevBrush = SelectObject( hdc, (HBRUSH16)hbrush ))) return 0;
473 PatBlt( hdc, rect->left, rect->top,
474 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
475 SelectObject( hdc, prevBrush );
476 return 1;
480 /***********************************************************************
481 * InvertRect16 (USER.82)
483 void InvertRect16( HDC16 hdc, const RECT16 *rect )
485 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
486 PatBlt( hdc, rect->left, rect->top,
487 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
491 /***********************************************************************
492 * InvertRect32 (USER32.329)
494 void InvertRect32( HDC32 hdc, const RECT32 *rect )
496 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
497 PatBlt( hdc, rect->left, rect->top,
498 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
502 /***********************************************************************
503 * FrameRect16 (USER.83)
505 INT16 FrameRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
507 HBRUSH prevBrush;
508 int left, top, right, bottom;
510 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
511 if (!dc) return FALSE;
513 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
514 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
516 left = XLPTODP( dc, rect->left );
517 top = YLPTODP( dc, rect->top );
518 right = XLPTODP( dc, rect->right );
519 bottom = YLPTODP( dc, rect->bottom );
521 if (DC_SetupGCForBrush( dc ))
523 PatBlt( hdc, rect->left, rect->top, 1,
524 rect->bottom - rect->top, PATCOPY );
525 PatBlt( hdc, rect->right - 1, rect->top, 1,
526 rect->bottom - rect->top, PATCOPY );
527 PatBlt( hdc, rect->left, rect->top,
528 rect->right - rect->left, 1, PATCOPY );
529 PatBlt( hdc, rect->left, rect->bottom - 1,
530 rect->right - rect->left, 1, PATCOPY );
532 SelectObject( hdc, prevBrush );
533 return 1;
537 /***********************************************************************
538 * FrameRect32 (USER32.202)
540 INT32 FrameRect32( HDC32 hdc, const RECT32 *rect, HBRUSH32 hbrush )
542 RECT16 rect16;
543 CONV_RECT32TO16( rect, &rect16 );
544 return FrameRect16( (HDC16)hdc, &rect16, (HBRUSH16)hbrush );
548 /***********************************************************************
549 * SetPixel (GDI.31)
551 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
553 Pixel pixel;
554 PALETTEENTRY entry;
556 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
557 if (!dc)
559 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
560 if (!dc) return 0;
561 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
562 return 1;
565 x = dc->w.DCOrgX + XLPTODP( dc, x );
566 y = dc->w.DCOrgY + YLPTODP( dc, y );
567 pixel = COLOR_ToPhysical( dc, color );
569 XSetForeground( display, dc->u.x.gc, pixel );
570 XSetFunction( display, dc->u.x.gc, GXcopy );
571 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
573 if (screenDepth <= 8)
575 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
576 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
578 else return (COLORREF)pixel;
582 /***********************************************************************
583 * GetPixel (GDI.83)
585 COLORREF GetPixel( HDC hdc, short x, short y )
587 PALETTEENTRY entry;
588 XImage * image;
589 WORD * mapping;
590 int pixel;
592 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
593 if (!dc) return 0;
595 #ifdef SOLITAIRE_SPEED_HACK
596 return 0;
597 #endif
599 if (!PtVisible( hdc, x, y )) return 0;
601 x = dc->w.DCOrgX + XLPTODP( dc, x );
602 y = dc->w.DCOrgY + YLPTODP( dc, y );
603 image = XGetImage( display, dc->u.x.drawable, x, y,
604 1, 1, AllPlanes, ZPixmap );
605 pixel = XGetPixel( image, 0, 0 );
606 XDestroyImage( image );
608 if (screenDepth > 8) return pixel;
609 mapping = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hRevMapping );
610 if (mapping) pixel = mapping[pixel];
611 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
612 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
616 /***********************************************************************
617 * PaintRgn (GDI.43)
619 BOOL PaintRgn( HDC hdc, HRGN hrgn )
621 RECT16 box;
622 HRGN tmpVisRgn, prevVisRgn;
623 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
624 if (!dc) return FALSE;
626 /* Modify visible region */
628 if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
629 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
631 RestoreVisRgn( hdc );
632 return FALSE;
634 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
635 SelectVisRgn( hdc, tmpVisRgn );
636 DeleteObject( tmpVisRgn );
638 /* Fill the region */
640 GetRgnBox16( dc->w.hGCClipRgn, &box );
641 if (DC_SetupGCForBrush( dc ))
642 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
643 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
644 box.right-box.left, box.bottom-box.top );
646 /* Restore the visible region */
648 RestoreVisRgn( hdc );
649 return TRUE;
653 /***********************************************************************
654 * FillRgn (GDI.40)
656 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
658 BOOL retval;
659 HBRUSH prevBrush = SelectObject( hdc, hbrush );
660 if (!prevBrush) return FALSE;
661 retval = PaintRgn( hdc, hrgn );
662 SelectObject( hdc, prevBrush );
663 return retval;
666 /***********************************************************************
667 * FrameRgn (GDI.41)
669 BOOL FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, int nWidth, int nHeight )
671 HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
672 if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return 0;
673 FillRgn( hdc, tmp, hbrush );
674 DeleteObject( tmp );
675 return 1;
678 /***********************************************************************
679 * InvertRgn (GDI.42)
681 BOOL InvertRgn( HDC hdc, HRGN hrgn )
683 HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
684 WORD prevROP = SetROP2( hdc, R2_NOT );
685 BOOL retval = PaintRgn( hdc, hrgn );
686 SelectObject( hdc, prevBrush );
687 SetROP2( hdc, prevROP );
688 return retval;
692 /***********************************************************************
693 * DrawFocusRect16 (USER.466)
695 void DrawFocusRect16( HDC16 hdc, const RECT16* rc )
697 HPEN16 hOldPen;
698 int oldDrawMode, oldBkMode;
699 int left, top, right, bottom;
700 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
701 if (!dc) return;
703 left = XLPTODP( dc, rc->left );
704 top = YLPTODP( dc, rc->top );
705 right = XLPTODP( dc, rc->right );
706 bottom = YLPTODP( dc, rc->bottom );
708 hOldPen = (HPEN16)SelectObject(hdc, sysColorObjects.hpenWindowText );
709 oldDrawMode = SetROP2(hdc, R2_XORPEN);
710 oldBkMode = SetBkMode(hdc, TRANSPARENT);
712 /* Hack: make sure the XORPEN operation has an effect */
713 dc->u.x.pen.pixel = (1 << screenDepth) - 1;
715 if (DC_SetupGCForPen( dc ))
716 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
717 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
718 right-left-1, bottom-top-1 );
720 SetBkMode(hdc, oldBkMode);
721 SetROP2(hdc, oldDrawMode);
722 SelectObject(hdc, (HANDLE)hOldPen);
726 /***********************************************************************
727 * DrawFocusRect32 (USER32.155)
729 void DrawFocusRect32( HDC32 hdc, const RECT32* rect )
731 RECT16 rect16;
732 CONV_RECT32TO16( rect, &rect16 );
733 return DrawFocusRect16( (HDC16)hdc, &rect16 );
737 /**********************************************************************
738 * GRAPH_DrawBitmap
740 * Short-cut function to blit a bitmap into a device.
741 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
743 BOOL GRAPH_DrawBitmap( HDC hdc, HBITMAP hbitmap, int xdest, int ydest,
744 int xsrc, int ysrc, int width, int height )
746 BITMAPOBJ *bmp;
747 DC *dc;
749 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
750 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
751 return FALSE;
752 XSetFunction( display, dc->u.x.gc, GXcopy );
753 if (bmp->bitmap.bmBitsPixel == 1)
755 XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
756 XSetBackground( display, dc->u.x.gc, dc->w.textPixel );
757 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
758 xsrc, ysrc, width, height,
759 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
760 return TRUE;
762 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
764 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
765 xsrc, ysrc, width, height,
766 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
767 return TRUE;
769 else return FALSE;
773 /**********************************************************************
774 * GRAPH_DrawReliefRect (Not a MSWin Call)
776 void GRAPH_DrawReliefRect( HDC hdc, RECT16 *rect, int highlight_size,
777 int shadow_size, BOOL pressed )
779 HBRUSH hbrushOld;
780 int i;
782 hbrushOld = SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnShadow :
783 sysColorObjects.hbrushBtnHighlight );
784 for (i = 0; i < highlight_size; i++)
786 PatBlt( hdc, rect->left + i, rect->top,
787 1, rect->bottom - rect->top - i, PATCOPY );
788 PatBlt( hdc, rect->left, rect->top + i,
789 rect->right - rect->left - i, 1, PATCOPY );
792 SelectObject( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
793 sysColorObjects.hbrushBtnShadow );
794 for (i = 0; i < shadow_size; i++)
796 PatBlt( hdc, rect->right - i - 1, rect->top + i,
797 1, rect->bottom - rect->top - i, PATCOPY );
798 PatBlt( hdc, rect->left + i, rect->bottom - i - 1,
799 rect->right - rect->left - i, 1, PATCOPY );
802 SelectObject( hdc, hbrushOld );
806 /**********************************************************************
807 * Polyline16 (GDI.37)
809 BOOL16 Polyline16( HDC16 hdc, LPPOINT16 pt, INT16 count )
811 register int i;
812 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
813 if (!dc)
815 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
816 if (!dc) return FALSE;
817 MF_MetaPoly(dc, META_POLYLINE, pt, count);
818 return TRUE;
821 if (DC_SetupGCForPen( dc ))
822 for (i = 0; i < count-1; i ++)
823 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
824 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
825 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
826 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
827 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
828 return TRUE;
832 /**********************************************************************
833 * Polygon16 (GDI.36)
835 BOOL16 Polygon16( HDC16 hdc, LPPOINT16 pt, INT16 count )
837 register int i;
838 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
839 XPoint *points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
841 if (!dc)
843 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
844 if (!dc) return FALSE;
845 MF_MetaPoly(dc, META_POLYGON, pt, count);
846 return TRUE;
849 for (i = 0; i < count; i++)
851 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
852 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
854 points[count] = points[0];
856 if (DC_SetupGCForBrush( dc ))
857 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
858 points, count+1, Complex, CoordModeOrigin);
860 if (DC_SetupGCForPen ( dc ))
861 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
862 points, count+1, CoordModeOrigin );
864 free( points );
865 return TRUE;
869 /**********************************************************************
870 * PolyPolygon16 (GDI.450)
872 BOOL16 PolyPolygon16( HDC16 hdc, LPPOINT16 pt, LPINT16 counts, UINT16 polygons)
874 HRGN hrgn;
875 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
877 if (!dc)
879 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
880 if (!dc) return FALSE;
881 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
882 return TRUE;
884 /* FIXME: The points should be converted to device coords before */
885 /* creating the region. But as CreatePolyPolygonRgn is not */
886 /* really correct either, it doesn't matter much... */
887 /* At least the outline will be correct :-) */
888 hrgn = CreatePolyPolygonRgn16( pt, counts, polygons, dc->w.polyFillMode );
889 PaintRgn( hdc, hrgn );
890 DeleteObject( hrgn );
892 /* Draw the outline of the polygons */
894 if (DC_SetupGCForPen ( dc ))
896 int i, j, max = 0;
897 XPoint *points;
899 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
900 points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
902 for (i = 0; i < polygons; i++)
904 for (j = 0; j < counts[i]; j++)
906 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
907 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
908 pt++;
910 points[j] = points[0];
911 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
912 points, j + 1, CoordModeOrigin );
914 free( points );
916 return TRUE;
920 /**********************************************************************
921 * GRAPH_InternalFloodFill
923 * Internal helper function for flood fill.
924 * (xorg,yorg) is the origin of the X image relative to the drawable.
925 * (x,y) is relative to the origin of the X image.
927 static void GRAPH_InternalFloodFill( XImage *image, DC *dc,
928 int x, int y,
929 int xOrg, int yOrg,
930 Pixel pixel, WORD fillType )
932 int left, right;
934 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
935 (XGetPixel(image,x,y) != pixel) : \
936 (XGetPixel(image,x,y) == pixel))
938 if (!TO_FLOOD(x,y)) return;
940 /* Find left and right boundaries */
942 left = right = x;
943 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
944 while ((right < image->width) && TO_FLOOD( right, y )) right++;
945 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
946 xOrg + left, yOrg + y, right-left, 1 );
948 /* Set the pixels of this line so we don't fill it again */
950 for (x = left; x < right; x++)
952 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
953 else XPutPixel( image, x, y, ~pixel );
956 /* Fill the line above */
958 if (--y >= 0)
960 x = left;
961 while (x < right)
963 while ((x < right) && !TO_FLOOD(x,y)) x++;
964 if (x >= right) break;
965 while ((x < right) && TO_FLOOD(x,y)) x++;
966 GRAPH_InternalFloodFill( image, dc, x-1, y,
967 xOrg, yOrg, pixel, fillType );
971 /* Fill the line below */
973 if ((y += 2) < image->height)
975 x = left;
976 while (x < right)
978 while ((x < right) && !TO_FLOOD(x,y)) x++;
979 if (x >= right) break;
980 while ((x < right) && TO_FLOOD(x,y)) x++;
981 GRAPH_InternalFloodFill( image, dc, x-1, y,
982 xOrg, yOrg, pixel, fillType );
985 #undef TO_FLOOD
989 /**********************************************************************
990 * GRAPH_DoFloodFill
992 * Main flood-fill routine.
994 static BOOL16 GRAPH_DoFloodFill( DC *dc, RECT16 *rect, INT32 x, INT32 y,
995 COLORREF color, UINT32 fillType )
997 XImage *image;
999 if (!(image = XGetImage( display, dc->u.x.drawable,
1000 dc->w.DCOrgX + rect->left,
1001 dc->w.DCOrgY + rect->top,
1002 rect->right - rect->left,
1003 rect->bottom - rect->top,
1004 AllPlanes, ZPixmap ))) return FALSE;
1006 if (DC_SetupGCForBrush( dc ))
1008 /* ROP mode is always GXcopy for flood-fill */
1009 XSetFunction( display, dc->u.x.gc, GXcopy );
1010 GRAPH_InternalFloodFill( image, dc,
1011 XLPTODP(dc,x) - rect->left,
1012 YLPTODP(dc,y) - rect->top,
1013 dc->w.DCOrgX + rect->left,
1014 dc->w.DCOrgY + rect->top,
1015 COLOR_ToPhysical( dc, color ), fillType );
1018 XDestroyImage( image );
1019 return TRUE;
1023 /**********************************************************************
1024 * ExtFloodFill (GDI.372) (GDI32.96)
1026 BOOL16 ExtFloodFill( HDC32 hdc, INT32 x, INT32 y, COLORREF color,
1027 UINT32 fillType )
1029 RECT16 rect;
1030 DC *dc;
1032 dprintf_graphics( stddeb, "ExtFloodFill %04x %d,%d %06lx %d\n",
1033 hdc, x, y, color, fillType );
1034 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
1035 if (!dc)
1037 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1038 if (!dc) return FALSE;
1039 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(color),
1040 LOWORD(color));
1041 return TRUE;
1044 if (!PtVisible( hdc, x, y )) return FALSE;
1045 if (GetRgnBox16( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
1047 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill, 6,
1048 dc, &rect, x, y, color, fillType );
1052 /**********************************************************************
1053 * FloodFill (GDI.25) (GDI32.104)
1055 BOOL16 FloodFill( HDC32 hdc, INT32 x, INT32 y, COLORREF color )
1057 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
1061 /**********************************************************************
1062 * DrawEdge16 (USER.659)
1064 BOOL16 DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
1066 RECT32 rect32;
1067 BOOL32 ret;
1069 CONV_RECT16TO32( rc, &rect32 );
1070 ret = DrawEdge32( hdc, &rect32, edge, flags );
1071 CONV_RECT32TO16( &rect32, rc );
1072 return ret;
1076 /**********************************************************************
1077 * DrawEdge32 (USER32.154)
1079 BOOL32 DrawEdge32( HDC32 hdc, LPRECT32 rc, UINT32 edge, UINT32 flags )
1081 HBRUSH hbrushOld;
1083 if (flags >= BF_DIAGONAL)
1084 fprintf( stderr, "DrawEdge: unsupported flags %04x\n", flags );
1086 dprintf_graphics( stddeb, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
1087 hdc, rc->left, rc->top, rc->right, rc->bottom,
1088 edge, flags );
1090 /* First do all the raised edges */
1092 SelectObject( hdc, sysColorObjects.hbrushBtnHighlight );
1093 if (edge & BDR_RAISEDOUTER)
1095 if (flags & BF_LEFT) PatBlt( hdc, rc->left, rc->top,
1096 1, rc->bottom - rc->top - 1, PATCOPY );
1097 if (flags & BF_TOP) PatBlt( hdc, rc->left, rc->top,
1098 rc->right - rc->left - 1, 1, PATCOPY );
1100 if (edge & BDR_SUNKENOUTER)
1102 if (flags & BF_RIGHT) PatBlt( hdc, rc->right - 1, rc->top,
1103 1, rc->bottom - rc->top, PATCOPY );
1104 if (flags & BF_BOTTOM) PatBlt( hdc, rc->left, rc->bottom - 1,
1105 rc->right - rc->left, 1, PATCOPY );
1107 if (edge & BDR_RAISEDINNER)
1109 if (flags & BF_LEFT) PatBlt( hdc, rc->left + 1, rc->top + 1,
1110 1, rc->bottom - rc->top - 2, PATCOPY );
1111 if (flags & BF_TOP) PatBlt( hdc, rc->left + 1, rc->top + 1,
1112 rc->right - rc->left - 2, 1, PATCOPY );
1114 if (edge & BDR_SUNKENINNER)
1116 if (flags & BF_RIGHT) PatBlt( hdc, rc->right - 2, rc->top + 1,
1117 1, rc->bottom - rc->top - 2, PATCOPY );
1118 if (flags & BF_BOTTOM) PatBlt( hdc, rc->left + 1, rc->bottom - 2,
1119 rc->right - rc->left - 2, 1, PATCOPY );
1122 /* Then do all the sunken edges */
1124 hbrushOld = SelectObject( hdc, sysColorObjects.hbrushBtnShadow );
1125 if (edge & BDR_SUNKENOUTER)
1127 if (flags & BF_LEFT) PatBlt( hdc, rc->left, rc->top,
1128 1, rc->bottom - rc->top - 1, PATCOPY );
1129 if (flags & BF_TOP) PatBlt( hdc, rc->left, rc->top,
1130 rc->right - rc->left - 1, 1, PATCOPY );
1132 if (edge & BDR_RAISEDOUTER)
1134 if (flags & BF_RIGHT) PatBlt( hdc, rc->right - 1, rc->top,
1135 1, rc->bottom - rc->top, PATCOPY );
1136 if (flags & BF_BOTTOM) PatBlt( hdc, rc->left, rc->bottom - 1,
1137 rc->right - rc->left, 1, PATCOPY );
1139 if (edge & BDR_SUNKENINNER)
1141 if (flags & BF_LEFT) PatBlt( hdc, rc->left + 1, rc->top + 1,
1142 1, rc->bottom - rc->top - 2, PATCOPY );
1143 if (flags & BF_TOP) PatBlt( hdc, rc->left + 1, rc->top + 1,
1144 rc->right - rc->left - 2, 1, PATCOPY );
1146 if (edge & BDR_RAISEDINNER)
1148 if (flags & BF_RIGHT) PatBlt( hdc, rc->right - 2, rc->top + 1,
1149 1, rc->bottom - rc->top - 2, PATCOPY );
1150 if (flags & BF_BOTTOM) PatBlt( hdc, rc->left + 1, rc->bottom - 2,
1151 rc->right - rc->left - 2, 1, PATCOPY );
1154 SelectObject( hdc, hbrushOld );
1155 return TRUE;
1159 /**********************************************************************
1160 * DrawFrameControl16 (USER.656)
1162 BOOL16 DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
1164 fprintf( stdnimp,"DrawFrameControl16(%x,%p,%d,%x), empty stub!\n",
1165 hdc,rc,edge,flags );
1166 return TRUE;
1170 /**********************************************************************
1171 * DrawFrameControl32 (USER32.157)
1173 BOOL32 DrawFrameControl32( HDC32 hdc, LPRECT32 rc, UINT32 edge, UINT32 flags )
1175 fprintf( stdnimp,"DrawFrameControl32(%x,%p,%d,%x), empty stub!\n",
1176 hdc,rc,edge,flags );
1177 return TRUE;