Release 940201
[wine/gsoc-2012-control.git] / windows / graphics.c
blob1160d3fec8799f556fefd3923b44009011191f9c
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 #ifndef PI
14 #define PI M_PI
15 #endif
17 #include "gdi.h"
19 /***********************************************************************
20 * LineTo (GDI.19)
22 BOOL LineTo( HDC hdc, short x, short y )
24 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
25 if (!dc) return FALSE;
26 if (DC_SetupGCForPen( dc ))
27 XDrawLine(XT_display, dc->u.x.drawable, dc->u.x.gc,
28 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
29 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
30 dc->w.DCOrgX + XLPTODP( dc, x ),
31 dc->w.DCOrgY + YLPTODP( dc, y ) );
32 dc->w.CursPosX = x;
33 dc->w.CursPosY = y;
34 return TRUE;
38 /***********************************************************************
39 * MoveTo (GDI.20)
41 DWORD MoveTo( HDC hdc, short x, short y )
43 POINT pt;
44 if (MoveToEx( hdc, x, y, &pt )) return pt.x | (pt.y << 16);
45 else return 0;
49 /***********************************************************************
50 * MoveToEx (GDI.483)
52 BOOL MoveToEx( HDC hdc, short x, short y, LPPOINT pt )
54 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
55 if (!dc) return FALSE;
56 if (pt)
58 pt->x = dc->w.CursPosX;
59 pt->y = dc->w.CursPosY;
61 dc->w.CursPosX = x;
62 dc->w.CursPosY = y;
63 return TRUE;
67 /***********************************************************************
68 * GRAPH_DrawArc
70 * Helper functions for Arc(), Chord() and Pie().
71 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
73 BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom,
74 int xstart, int ystart, int xend, int yend, int lines )
76 int xcenter, ycenter;
77 double start_angle, end_angle, diff_angle;
78 XPoint points[3];
79 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
80 if (!dc) return FALSE;
82 left = XLPTODP( dc, left );
83 top = YLPTODP( dc, top );
84 right = XLPTODP( dc, right );
85 bottom = YLPTODP( dc, bottom );
86 xstart = XLPTODP( dc, xstart );
87 ystart = YLPTODP( dc, ystart );
88 xend = XLPTODP( dc, xend );
89 yend = YLPTODP( dc, yend );
90 if ((left == right) || (top == bottom)) return FALSE;
92 if (!DC_SetupGCForPen( dc )) return TRUE;
94 xcenter = (right + left) / 2;
95 ycenter = (bottom + top) / 2;
96 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
97 (double)(xstart-xcenter)*(bottom-top) );
98 end_angle = atan2( (double)(ycenter-yend)*(right-left),
99 (double)(xend-xcenter)*(bottom-top) );
100 diff_angle = end_angle - start_angle;
101 if (diff_angle < 0.0) diff_angle += 2*PI;
103 XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
104 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
105 right-left-1, bottom-top-1,
106 (int)(start_angle * 180 * 64 / PI),
107 (int)(diff_angle * 180 * 64 / PI) );
108 if (!lines) return TRUE;
110 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
111 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
112 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
113 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
114 if (lines == 2)
116 points[2] = points[1];
117 points[1].x = dc->w.DCOrgX + xcenter;
118 points[1].y = dc->w.DCOrgY + ycenter;
120 XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
121 points, lines+1, CoordModeOrigin );
122 return TRUE;
126 /***********************************************************************
127 * Arc (GDI.23)
129 BOOL Arc( HDC hdc, int left, int top, int right, int bottom,
130 int xstart, int ystart, int xend, int yend )
132 return GRAPH_DrawArc( hdc, left, top, right, bottom,
133 xstart, ystart, xend, yend, 0 );
137 /***********************************************************************
138 * Pie (GDI.26)
140 BOOL Pie( HDC hdc, int left, int top, int right, int bottom,
141 int xstart, int ystart, int xend, int yend )
143 return GRAPH_DrawArc( hdc, left, top, right, bottom,
144 xstart, ystart, xend, yend, 2 );
148 /***********************************************************************
149 * Chord (GDI.348)
151 BOOL Chord( HDC hdc, int left, int top, int right, int bottom,
152 int xstart, int ystart, int xend, int yend )
154 return GRAPH_DrawArc( hdc, left, top, right, bottom,
155 xstart, ystart, xend, yend, 1 );
159 /***********************************************************************
160 * Ellipse (GDI.24)
162 BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
164 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
165 if (!dc) return FALSE;
167 left = XLPTODP( dc, left );
168 top = YLPTODP( dc, top );
169 right = XLPTODP( dc, right );
170 bottom = YLPTODP( dc, bottom );
171 if ((left == right) || (top == bottom)) return FALSE;
173 if (DC_SetupGCForBrush( dc ))
174 XFillArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
175 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
176 right-left-1, bottom-top-1, 0, 360*64 );
177 if (DC_SetupGCForPen( dc ))
178 XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
179 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
180 right-left-1, bottom-top-1, 0, 360*64 );
181 return TRUE;
185 /***********************************************************************
186 * Rectangle (GDI.27)
188 BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
190 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
191 if (!dc) return FALSE;
193 left = XLPTODP( dc, left );
194 top = YLPTODP( dc, top );
195 right = XLPTODP( dc, right );
196 bottom = YLPTODP( dc, bottom );
198 if (DC_SetupGCForBrush( dc ))
199 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
200 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
201 right-left-1, bottom-top-1 );
202 if (DC_SetupGCForPen( dc ))
203 XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
204 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
205 right-left-1, bottom-top-1 );
206 return TRUE;
210 /***********************************************************************
211 * FillRect (USER.81)
213 int FillRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
215 HBRUSH prevBrush;
217 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
218 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
219 PatBlt( hdc, rect->left, rect->top,
220 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
221 SelectObject( hdc, prevBrush );
222 return 1;
226 /***********************************************************************
227 * InvertRect (USER.82)
229 void InvertRect( HDC hdc, LPRECT rect )
231 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return;
232 PatBlt( hdc, rect->left, rect->top,
233 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
237 /***********************************************************************
238 * FrameRect (USER.83)
240 int FrameRect( HDC hdc, LPRECT rect, HBRUSH hbrush )
242 HBRUSH prevBrush;
243 int left, top, right, bottom;
245 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
246 if (!dc) return FALSE;
248 if ((rect->right <= rect->left) || (rect->bottom <= rect->top)) return 0;
249 if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
251 left = XLPTODP( dc, rect->left );
252 top = YLPTODP( dc, rect->top );
253 right = XLPTODP( dc, rect->right );
254 bottom = YLPTODP( dc, rect->bottom );
256 if (DC_SetupGCForBrush( dc )) {
257 PatBlt( hdc, rect->left, rect->top, 1,
258 rect->bottom - rect->top, PATCOPY );
259 PatBlt( hdc, rect->right - 1, rect->top, 1,
260 rect->bottom - rect->top, PATCOPY );
261 PatBlt( hdc, rect->left, rect->top,
262 rect->right - rect->left, 1, PATCOPY );
263 PatBlt( hdc, rect->left, rect->bottom - 1,
264 rect->right - rect->left, 1, PATCOPY );
266 SelectObject( hdc, prevBrush );
267 return 1;
271 /***********************************************************************
272 * SetPixel (GDI.31)
274 COLORREF SetPixel( HDC hdc, short x, short y, COLORREF color )
276 int pixel;
277 PALETTEENTRY entry;
279 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
280 if (!dc) return 0;
282 x = dc->w.DCOrgX + XLPTODP( dc, x );
283 y = dc->w.DCOrgY + YLPTODP( dc, y );
284 pixel = GetNearestPaletteIndex( dc->w.hPalette, color );
285 GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
287 XSetForeground( XT_display, dc->u.x.gc, pixel );
288 XSetFunction( XT_display, dc->u.x.gc, GXcopy );
289 XDrawPoint( XT_display, dc->u.x.drawable, dc->u.x.gc, x, y );
291 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
295 /***********************************************************************
296 * GetPixel (GDI.83)
298 COLORREF GetPixel( HDC hdc, short x, short y )
300 PALETTEENTRY entry;
301 XImage * image;
303 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
304 if (!dc) return 0;
306 x = dc->w.DCOrgX + XLPTODP( dc, x );
307 y = dc->w.DCOrgY + YLPTODP( dc, y );
308 if ((x < 0) || (y < 0)) return 0;
310 if (!(dc->w.flags & DC_MEMORY))
312 XWindowAttributes win_attr;
314 if (!XGetWindowAttributes( XT_display, dc->u.x.drawable, &win_attr ))
315 return 0;
316 if (win_attr.map_state != IsViewable) return 0;
317 if ((x >= win_attr.width) || (y >= win_attr.height)) return 0;
320 image = XGetImage( XT_display, dc->u.x.drawable, x, y,
321 1, 1, AllPlanes, ZPixmap );
322 GetPaletteEntries( dc->w.hPalette, XGetPixel( image, 0, 0 ), 1, &entry );
323 XDestroyImage( image );
324 return RGB( entry.peRed, entry.peGreen, entry.peBlue );
328 /***********************************************************************
329 * PaintRgn (GDI.43)
331 BOOL PaintRgn( HDC hdc, HRGN hrgn )
333 RECT box;
334 HRGN tmpVisRgn, prevVisRgn;
335 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
336 if (!dc) return FALSE;
338 /* Modify visible region */
340 prevVisRgn = SaveVisRgn( hdc );
341 if (prevVisRgn)
343 if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 )))
345 RestoreVisRgn( hdc );
346 return FALSE;
348 CombineRgn( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
349 SelectVisRgn( hdc, tmpVisRgn );
350 DeleteObject( tmpVisRgn );
352 else SelectVisRgn( hdc, hrgn );
354 /* Fill the region */
356 GetClipBox( hdc, &box );
357 if (DC_SetupGCForBrush( dc ))
358 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
359 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
360 box.right-box.left, box.bottom-box.top );
362 /* Restore the visible region */
364 if (prevVisRgn) RestoreVisRgn( hdc );
365 else SelectVisRgn( hdc, 0 );
366 return TRUE;
370 /***********************************************************************
371 * FillRgn (GDI.40)
373 BOOL FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
375 BOOL retval;
376 HBRUSH prevBrush = SelectObject( hdc, hbrush );
377 if (!prevBrush) return FALSE;
378 retval = PaintRgn( hdc, hrgn );
379 SelectObject( hdc, prevBrush );
380 return retval;
384 /***********************************************************************
385 * DrawFocusRect (USER.466)
387 void DrawFocusRect( HDC hdc, LPRECT rc )
389 HPEN hPen, hOldPen;
390 int oldDrawMode, oldBkMode;
391 int left, top, right, bottom;
392 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
393 if (!dc) return;
395 left = XLPTODP( dc, rc->left );
396 top = YLPTODP( dc, rc->top );
397 right = XLPTODP( dc, rc->right );
398 bottom = YLPTODP( dc, rc->bottom );
400 hPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_WINDOWTEXT));
401 hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
402 oldDrawMode = SetROP2(hdc, R2_XORPEN);
403 oldBkMode = SetBkMode(hdc, TRANSPARENT);
405 if (DC_SetupGCForPen( dc ))
406 XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
407 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
408 right-left-1, bottom-top-1 );
410 SetBkMode(hdc, oldBkMode);
411 SetROP2(hdc, oldDrawMode);
412 SelectObject(hdc, (HANDLE)hOldPen);
413 DeleteObject((HANDLE)hPen);
417 /**********************************************************************
418 * DrawReliefRect (Not a MSWin Call)
420 void DrawReliefRect( HDC hdc, RECT rect, int thickness, BOOL pressed )
422 HBRUSH hbrushOld, hbrushShadow, hbrushHighlight;
423 int i;
425 hbrushShadow = CreateSolidBrush( GetSysColor(COLOR_BTNSHADOW) );
426 hbrushHighlight = CreateSolidBrush( GetSysColor(COLOR_BTNHIGHLIGHT) );
428 if (pressed) hbrushOld = SelectObject( hdc, hbrushShadow );
429 else hbrushOld = SelectObject( hdc, hbrushHighlight );
431 for (i = 0; i < thickness; i++)
433 PatBlt( hdc, rect.left + i, rect.top,
434 1, rect.bottom - rect.top - i, PATCOPY );
435 PatBlt( hdc, rect.left, rect.top + i,
436 rect.right - rect.left - i, 1, PATCOPY );
439 if (pressed) hbrushOld = SelectObject( hdc, hbrushHighlight );
440 else hbrushOld = SelectObject( hdc, hbrushShadow );
442 for (i = 0; i < thickness; i++)
444 PatBlt( hdc, rect.right - i - 1, rect.top + i,
445 1, rect.bottom - rect.top - i, PATCOPY );
446 PatBlt( hdc, rect.left + i, rect.bottom - i - 1,
447 rect.right - rect.left - i, 1, PATCOPY );
450 SelectObject( hdc, hbrushOld );
451 DeleteObject( hbrushShadow );
452 DeleteObject( hbrushHighlight );
456 /**********************************************************************
457 * Polyline (GDI.37)
459 BOOL Polyline (HDC hdc, LPPOINT pt, int count)
461 register int i;
462 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
464 if (DC_SetupGCForPen( dc ))
466 for (i = 0; i < count-1; i ++)
467 XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,
468 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
469 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
470 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
471 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
472 XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,
473 dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
474 dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
475 dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
476 dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
479 return (TRUE);
483 /**********************************************************************
484 * Polygon (GDI.36)
486 BOOL Polygon (HDC hdc, LPPOINT pt, int count)
488 register int i;
489 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
490 XPoint *points = (XPoint *) malloc (sizeof (XPoint) * count+1);
492 if (DC_SetupGCForBrush( dc ))
495 for (i = 0; i < count; i++)
497 points [i].x = dc->w.DCOrgX + XLPTODP(dc, pt [i].x);
498 points [i].y = dc->w.DCOrgY + YLPTODP(dc, pt [i].y);
500 points [count] = points [0];
502 XFillPolygon( XT_display, dc->u.x.drawable, dc->u.x.gc,
503 points, count, Complex, CoordModeOrigin);
505 if (DC_SetupGCForPen ( dc ))
507 XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
508 points, count, CoordModeOrigin );
511 free ((void *) points);
512 return (TRUE);