Release 961222
[wine/multimedia.git] / windows / graphics.c
blobcaf865e735ef2bf6fb491b4643a17784021dd57b
1 /*
2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
8 #include <math.h>
9 #include <stdlib.h>
10 #include <X11/Xlib.h>
11 #include <X11/Xutil.h>
12 #include <X11/Intrinsic.h>
13 #ifndef PI
14 #define PI M_PI
15 #endif
16 #include "graphics.h"
17 #include "dc.h"
18 #include "bitmap.h"
19 #include "callback.h"
20 #include "metafile.h"
21 #include "syscolor.h"
22 #include "stddebug.h"
23 #include "palette.h"
24 #include "color.h"
25 #include "region.h"
26 #include "debug.h"
27 #include "xmalloc.h"
29 /***********************************************************************
30 * LineTo16 (GDI.19)
32 BOOL16 LineTo16( HDC16 hdc, INT16 x, INT16 y )
34 return LineTo32( hdc, x, y );
38 /***********************************************************************
39 * LineTo32 (GDI32.249)
41 BOOL32 LineTo32( HDC32 hdc, INT32 x, INT32 y )
43 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
44 if (!dc)
46 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
47 if (!dc) return FALSE;
48 MF_MetaParam2(dc, META_LINETO, x, y);
49 return TRUE;
52 if (DC_SetupGCForPen( dc ))
53 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
54 dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
55 dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
56 dc->w.DCOrgX + XLPTODP( dc, x ),
57 dc->w.DCOrgY + YLPTODP( dc, y ) );
58 dc->w.CursPosX = x;
59 dc->w.CursPosY = y;
60 return TRUE;
64 /***********************************************************************
65 * MoveTo (GDI.20)
67 DWORD MoveTo( HDC16 hdc, INT16 x, INT16 y )
69 DWORD ret;
70 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
71 if (!dc)
73 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
74 if (!dc) return FALSE;
75 MF_MetaParam2(dc, META_MOVETO, x, y);
76 return 0;
78 ret = MAKELONG( dc->w.CursPosX, dc->w.CursPosY );
79 dc->w.CursPosX = x;
80 dc->w.CursPosY = y;
81 return ret;
85 /***********************************************************************
86 * MoveToEx16 (GDI.483)
88 BOOL16 MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
90 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
91 if (!dc) return FALSE;
92 if (pt)
94 pt->x = dc->w.CursPosX;
95 pt->y = dc->w.CursPosY;
97 dc->w.CursPosX = x;
98 dc->w.CursPosY = y;
99 return TRUE;
103 /***********************************************************************
104 * MoveToEx32 (GDI32.254)
106 BOOL32 MoveToEx32( HDC32 hdc, INT32 x, INT32 y, LPPOINT32 pt )
108 POINT16 pt16;
109 if (!MoveToEx16( (HDC16)hdc, (INT16)x, (INT16)y, &pt16 )) return FALSE;
110 if (pt) CONV_POINT16TO32( &pt16, pt );
111 return TRUE;
115 /***********************************************************************
116 * GRAPH_DrawArc
118 * Helper functions for Arc(), Chord() and Pie().
119 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
121 static BOOL32 GRAPH_DrawArc( HDC32 hdc, INT32 left, INT32 top, INT32 right,
122 INT32 bottom, INT32 xstart, INT32 ystart,
123 INT32 xend, INT32 yend, INT32 lines )
125 INT32 xcenter, ycenter, istart_angle, idiff_angle, tmp;
126 double start_angle, end_angle;
127 XPoint points[3];
128 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
129 if (!dc)
131 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
132 if (!dc) return FALSE;
133 switch (lines)
135 case 0:
136 MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
137 xstart, ystart, xend, yend);
138 break;
140 case 1:
141 MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
142 xstart, ystart, xend, yend);
143 break;
145 case 2:
146 MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
147 xstart, ystart, xend, yend);
148 break;
150 return 0;
153 left = XLPTODP( dc, left );
154 top = YLPTODP( dc, top );
155 right = XLPTODP( dc, right );
156 bottom = YLPTODP( dc, bottom );
157 xstart = XLPTODP( dc, xstart );
158 ystart = YLPTODP( dc, ystart );
159 xend = XLPTODP( dc, xend );
160 yend = YLPTODP( dc, yend );
161 if ((left == right) || (top == bottom)) return FALSE;
163 xcenter = (right + left) / 2;
164 ycenter = (bottom + top) / 2;
165 start_angle = atan2( (double)(ycenter-ystart)*(right-left),
166 (double)(xstart-xcenter)*(bottom-top) );
167 end_angle = atan2( (double)(ycenter-yend)*(right-left),
168 (double)(xend-xcenter)*(bottom-top) );
169 istart_angle = (INT32)(start_angle * 180 * 64 / PI);
170 idiff_angle = (INT32)((end_angle - start_angle) * 180 * 64 / PI );
171 if (idiff_angle <= 0) idiff_angle += 360 * 64;
172 if (left > right) { tmp=left; left=right; right=tmp; }
173 if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
175 /* Fill arc with brush if Chord() or Pie() */
177 if ((lines > 0) && DC_SetupGCForBrush( dc ))
179 XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
180 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
181 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
182 right-left-1, bottom-top-1, istart_angle, idiff_angle );
185 /* Draw arc and lines */
187 if (!DC_SetupGCForPen( dc )) return TRUE;
188 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
189 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
190 right-left-1, bottom-top-1, istart_angle, idiff_angle );
191 if (!lines) return TRUE;
193 points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
194 points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
195 points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
196 points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
197 if (lines == 2)
199 points[2] = points[1];
200 points[1].x = dc->w.DCOrgX + xcenter;
201 points[1].y = dc->w.DCOrgY + ycenter;
203 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
204 points, lines+1, CoordModeOrigin );
205 return TRUE;
209 /***********************************************************************
210 * Arc16 (GDI.23)
212 BOOL16 Arc16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
213 INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
215 return GRAPH_DrawArc( hdc, left, top, right, bottom,
216 xstart, ystart, xend, yend, 0 );
220 /***********************************************************************
221 * Arc32 (GDI32.7)
223 BOOL32 Arc32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
224 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
226 return GRAPH_DrawArc( hdc, left, top, right, bottom,
227 xstart, ystart, xend, yend, 0 );
231 /***********************************************************************
232 * Pie16 (GDI.26)
234 BOOL16 Pie16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
235 INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
237 return GRAPH_DrawArc( hdc, left, top, right, bottom,
238 xstart, ystart, xend, yend, 2 );
242 /***********************************************************************
243 * Pie32 (GDI32.262)
245 BOOL32 Pie32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
246 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
248 return GRAPH_DrawArc( hdc, left, top, right, bottom,
249 xstart, ystart, xend, yend, 2 );
253 /***********************************************************************
254 * Chord16 (GDI.348)
256 BOOL16 Chord16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
257 INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
259 return GRAPH_DrawArc( hdc, left, top, right, bottom,
260 xstart, ystart, xend, yend, 1 );
264 /***********************************************************************
265 * Chord32 (GDI32.14)
267 BOOL32 Chord32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
268 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
270 return GRAPH_DrawArc( hdc, left, top, right, bottom,
271 xstart, ystart, xend, yend, 1 );
275 /***********************************************************************
276 * Ellipse16 (GDI.24)
278 BOOL16 Ellipse16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom )
280 return Ellipse32( hdc, left, top, right, bottom );
284 /***********************************************************************
285 * Ellipse32 (GDI32.75)
287 BOOL32 Ellipse32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom )
289 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
290 if (!dc)
292 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
293 if (!dc) return FALSE;
294 MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
295 return 0;
298 left = XLPTODP( dc, left );
299 top = YLPTODP( dc, top );
300 right = XLPTODP( dc, right );
301 bottom = YLPTODP( dc, bottom );
302 if ((left == right) || (top == bottom)) return FALSE;
304 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
305 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
307 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
308 (dc->u.x.pen.width < right-left-1) &&
309 (dc->u.x.pen.width < bottom-top-1))
311 left += dc->u.x.pen.width / 2;
312 right -= (dc->u.x.pen.width + 1) / 2;
313 top += dc->u.x.pen.width / 2;
314 bottom -= (dc->u.x.pen.width + 1) / 2;
317 if (DC_SetupGCForBrush( dc ))
318 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
319 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
320 right-left-1, bottom-top-1, 0, 360*64 );
321 if (DC_SetupGCForPen( dc ))
322 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
323 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
324 right-left-1, bottom-top-1, 0, 360*64 );
325 return TRUE;
329 /***********************************************************************
330 * Rectangle16 (GDI.27)
332 BOOL16 Rectangle16(HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom)
334 return Rectangle32( hdc, left, top, right, bottom );
338 /***********************************************************************
339 * Rectangle32 (GDI32.283)
341 BOOL32 Rectangle32(HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom)
343 INT32 width;
344 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
345 if (!dc)
347 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
348 if (!dc) return FALSE;
349 MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
350 return TRUE;
352 left = XLPTODP( dc, left );
353 top = YLPTODP( dc, top );
354 right = XLPTODP( dc, right );
355 bottom = YLPTODP( dc, bottom );
357 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
358 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
360 if ((left == right) || (top == bottom))
362 if (DC_SetupGCForPen( dc ))
363 XDrawLine(display, dc->u.x.drawable, dc->u.x.gc,
364 dc->w.DCOrgX + left,
365 dc->w.DCOrgY + top,
366 dc->w.DCOrgX + right,
367 dc->w.DCOrgY + bottom);
368 return TRUE;
370 width = dc->u.x.pen.width;
371 if (!width) width = 1;
372 if(dc->u.x.pen.style == PS_NULL) width = 0;
374 if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
375 (width < right-left) && (width < bottom-top))
377 left += width / 2;
378 right -= (width + 1) / 2;
379 top += width / 2;
380 bottom -= (width + 1) / 2;
383 if (DC_SetupGCForBrush( dc ))
384 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
385 dc->w.DCOrgX + left + (width + 1) / 2,
386 dc->w.DCOrgY + top + (width + 1) / 2,
387 right-left-width-1, bottom-top-width-1);
388 if (DC_SetupGCForPen( dc ))
389 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
390 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
391 right-left-1, bottom-top-1 );
392 return TRUE;
396 /***********************************************************************
397 * RoundRect16 (GDI.28)
399 BOOL16 RoundRect16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
400 INT16 bottom, INT16 ell_width, INT16 ell_height )
402 return RoundRect32( hdc, left, top, right, bottom, ell_width, ell_height );
406 /***********************************************************************
407 * RoundRect32 (GDI32.291)
409 BOOL32 RoundRect32( HDC32 hdc, INT32 left, INT32 top, INT32 right,
410 INT32 bottom, INT32 ell_width, INT32 ell_height )
412 DC * dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
413 if (!dc)
415 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
416 if (!dc) return FALSE;
417 MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
418 ell_width, ell_height);
419 return TRUE;
421 dprintf_graphics(stddeb, "RoundRect(%d %d %d %d %d %d\n",
422 left, top, right, bottom, ell_width, ell_height);
424 left = XLPTODP( dc, left );
425 top = YLPTODP( dc, top );
426 right = XLPTODP( dc, right );
427 bottom = YLPTODP( dc, bottom );
428 ell_width = abs( ell_width * dc->vportExtX / dc->wndExtX );
429 ell_height = abs( ell_height * dc->vportExtY / dc->wndExtY );
431 /* Fix the coordinates */
433 if (right < left) { INT32 tmp = right; right = left; left = tmp; }
434 if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
435 if (ell_width > right - left) ell_width = right - left;
436 if (ell_height > bottom - top) ell_height = bottom - top;
438 if (DC_SetupGCForBrush( dc ))
440 if (ell_width && ell_height)
442 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
443 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
444 ell_width, ell_height, 90 * 64, 90 * 64 );
445 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
446 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
447 ell_width, ell_height, 180 * 64, 90 * 64 );
448 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
449 dc->w.DCOrgX + right - ell_width,
450 dc->w.DCOrgY + bottom - ell_height,
451 ell_width, ell_height, 270 * 64, 90 * 64 );
452 XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
453 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
454 ell_width, ell_height, 0, 90 * 64 );
456 if (ell_width < right - left)
458 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
459 dc->w.DCOrgX + left + ell_width / 2,
460 dc->w.DCOrgY + top,
461 right - left - ell_width, ell_height / 2 );
462 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
463 dc->w.DCOrgX + left + ell_width / 2,
464 dc->w.DCOrgY + bottom - (ell_height+1) / 2,
465 right - left - ell_width, (ell_height+1) / 2 );
467 if (ell_height < bottom - top)
469 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
470 dc->w.DCOrgX + left,
471 dc->w.DCOrgY + top + ell_height / 2,
472 right - left, bottom - top - ell_height );
475 if (DC_SetupGCForPen(dc))
477 if (ell_width && ell_height)
479 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
480 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
481 ell_width, ell_height, 90 * 64, 90 * 64 );
482 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
483 dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
484 ell_width, ell_height, 180 * 64, 90 * 64 );
485 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
486 dc->w.DCOrgX + right - ell_width,
487 dc->w.DCOrgY + bottom - ell_height,
488 ell_width, ell_height, 270 * 64, 90 * 64 );
489 XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
490 dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
491 ell_width, ell_height, 0, 90 * 64 );
493 if (ell_width < right - left)
495 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
496 dc->w.DCOrgX + left + ell_width / 2,
497 dc->w.DCOrgY + top,
498 dc->w.DCOrgX + right - ell_width / 2,
499 dc->w.DCOrgY + top );
500 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
501 dc->w.DCOrgX + left + ell_width / 2,
502 dc->w.DCOrgY + bottom,
503 dc->w.DCOrgX + right - ell_width / 2,
504 dc->w.DCOrgY + bottom );
506 if (ell_height < bottom - top)
508 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
509 dc->w.DCOrgX + right,
510 dc->w.DCOrgY + top + ell_height / 2,
511 dc->w.DCOrgX + right,
512 dc->w.DCOrgY + bottom - ell_height / 2 );
513 XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
514 dc->w.DCOrgX + left,
515 dc->w.DCOrgY + top + ell_height / 2,
516 dc->w.DCOrgX + left,
517 dc->w.DCOrgY + bottom - ell_height / 2 );
520 return TRUE;
524 /***********************************************************************
525 * FillRect16 (USER.81)
527 INT16 FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
529 HBRUSH16 prevBrush;
531 /* coordinates are logical so we cannot fast-check rectangle
532 * - do it in PatBlt() after LPtoDP().
535 if (!(prevBrush = SelectObject16( hdc, hbrush ))) return 0;
536 PatBlt32( hdc, rect->left, rect->top,
537 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
538 SelectObject16( hdc, prevBrush );
539 return 1;
543 /***********************************************************************
544 * FillRect32 (USER32.196)
546 INT32 FillRect32( HDC32 hdc, const RECT32 *rect, HBRUSH32 hbrush )
548 HBRUSH32 prevBrush;
550 if (!(prevBrush = SelectObject32( hdc, hbrush ))) return 0;
551 PatBlt32( hdc, rect->left, rect->top,
552 rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
553 SelectObject32( hdc, prevBrush );
554 return 1;
558 /***********************************************************************
559 * InvertRect16 (USER.82)
561 void InvertRect16( HDC16 hdc, const RECT16 *rect )
563 PatBlt32( hdc, rect->left, rect->top,
564 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
568 /***********************************************************************
569 * InvertRect32 (USER32.329)
571 void InvertRect32( HDC32 hdc, const RECT32 *rect )
573 PatBlt32( hdc, rect->left, rect->top,
574 rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
578 /***********************************************************************
579 * FrameRect16 (USER.83)
581 INT16 FrameRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
583 HBRUSH16 prevBrush;
584 int left, top, right, bottom;
586 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
587 if (!dc) return FALSE;
589 left = XLPTODP( dc, rect->left );
590 top = YLPTODP( dc, rect->top );
591 right = XLPTODP( dc, rect->right );
592 bottom = YLPTODP( dc, rect->bottom );
594 if ( (right <= left) || (bottom <= top) ) return 0;
595 if (!(prevBrush = SelectObject16( hdc, hbrush ))) return 0;
597 if (DC_SetupGCForBrush( dc ))
599 PatBlt32( hdc, rect->left, rect->top, 1,
600 rect->bottom - rect->top, PATCOPY );
601 PatBlt32( hdc, rect->right - 1, rect->top, 1,
602 rect->bottom - rect->top, PATCOPY );
603 PatBlt32( hdc, rect->left, rect->top,
604 rect->right - rect->left, 1, PATCOPY );
605 PatBlt32( hdc, rect->left, rect->bottom - 1,
606 rect->right - rect->left, 1, PATCOPY );
608 SelectObject16( hdc, prevBrush );
609 return 1;
613 /***********************************************************************
614 * FrameRect32 (USER32.202)
616 INT32 FrameRect32( HDC32 hdc, const RECT32 *rect, HBRUSH32 hbrush )
618 RECT16 rect16;
619 CONV_RECT32TO16( rect, &rect16 );
620 return FrameRect16( (HDC16)hdc, &rect16, (HBRUSH16)hbrush );
624 /***********************************************************************
625 * SetPixel16 (GDI.31)
627 COLORREF SetPixel16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
629 return SetPixel32( hdc, x, y, color );
633 /***********************************************************************
634 * SetPixel32 (GDI32.327)
636 COLORREF SetPixel32( HDC32 hdc, INT32 x, INT32 y, COLORREF color )
638 Pixel pixel;
640 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
641 if (!dc)
643 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
644 if (!dc) return 0;
645 MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color));
646 return 1;
649 x = dc->w.DCOrgX + XLPTODP( dc, x );
650 y = dc->w.DCOrgY + YLPTODP( dc, y );
651 pixel = COLOR_ToPhysical( dc, color );
653 XSetForeground( display, dc->u.x.gc, pixel );
654 XSetFunction( display, dc->u.x.gc, GXcopy );
655 XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
657 /* inefficient but simple... */
659 return COLOR_ToLogical(pixel);
663 /***********************************************************************
664 * GetPixel16 (GDI.83)
666 COLORREF GetPixel16( HDC16 hdc, INT16 x, INT16 y )
668 return GetPixel32( hdc, x, y );
672 /***********************************************************************
673 * GetPixel32 (GDI32.211)
675 COLORREF GetPixel32( HDC32 hdc, INT32 x, INT32 y )
677 static Pixmap pixmap = 0;
678 XImage * image;
679 int pixel;
681 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
682 if (!dc) return 0;
684 #ifdef SOLITAIRE_SPEED_HACK
685 return 0;
686 #endif
688 if (!PtVisible32( hdc, x, y )) return 0;
690 x = dc->w.DCOrgX + XLPTODP( dc, x );
691 y = dc->w.DCOrgY + YLPTODP( dc, y );
692 if (dc->w.flags & DC_MEMORY)
694 image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
695 AllPlanes, ZPixmap );
697 else
699 /* If we are reading from the screen, use a temporary copy */
700 /* to avoid a BadMatch error */
701 if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
702 1, 1, dc->w.bitsPerPixel );
703 XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
704 x, y, 1, 1, 0, 0 );
705 image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
707 pixel = XGetPixel( image, 0, 0 );
708 XDestroyImage( image );
710 return COLOR_ToLogical(pixel);
714 /***********************************************************************
715 * PaintRgn16 (GDI.43)
717 BOOL16 PaintRgn16( HDC16 hdc, HRGN16 hrgn )
719 return PaintRgn32( hdc, hrgn );
723 /***********************************************************************
724 * PaintRgn32 (GDI32.259)
726 BOOL32 PaintRgn32( HDC32 hdc, HRGN32 hrgn )
728 RECT32 box;
729 HRGN32 tmpVisRgn, prevVisRgn;
730 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
731 if (!dc) return FALSE;
733 /* Modify visible region */
735 if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
736 if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 )))
738 RestoreVisRgn( hdc );
739 return FALSE;
741 CombineRgn32( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
742 SelectVisRgn( hdc, tmpVisRgn );
743 DeleteObject32( tmpVisRgn );
745 /* Fill the region */
747 GetRgnBox32( dc->w.hGCClipRgn, &box );
748 if (DC_SetupGCForBrush( dc ))
749 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
750 dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
751 box.right-box.left, box.bottom-box.top );
753 /* Restore the visible region */
755 RestoreVisRgn( hdc );
756 return TRUE;
760 /***********************************************************************
761 * FillRgn16 (GDI.40)
763 BOOL16 FillRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush )
765 return FillRgn32( hdc, hrgn, hbrush );
769 /***********************************************************************
770 * FillRgn32 (GDI32.101)
772 BOOL32 FillRgn32( HDC32 hdc, HRGN32 hrgn, HBRUSH32 hbrush )
774 BOOL32 retval;
775 HBRUSH32 prevBrush = SelectObject32( hdc, hbrush );
776 if (!prevBrush) return FALSE;
777 retval = PaintRgn32( hdc, hrgn );
778 SelectObject32( hdc, prevBrush );
779 return retval;
783 /***********************************************************************
784 * FrameRgn16 (GDI.41)
786 BOOL16 FrameRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush,
787 INT16 nWidth, INT16 nHeight )
789 return FrameRgn32( hdc, hrgn, hbrush, nWidth, nHeight );
793 /***********************************************************************
794 * FrameRgn32 (GDI32.105)
796 BOOL32 FrameRgn32( HDC32 hdc, HRGN32 hrgn, HBRUSH32 hbrush,
797 INT32 nWidth, INT32 nHeight )
799 HRGN32 tmp = CreateRectRgn32( 0, 0, 0, 0 );
800 if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return FALSE;
801 FillRgn32( hdc, tmp, hbrush );
802 DeleteObject32( tmp );
803 return TRUE;
807 /***********************************************************************
808 * InvertRgn16 (GDI.42)
810 BOOL16 InvertRgn16( HDC16 hdc, HRGN16 hrgn )
812 return InvertRgn32( hdc, hrgn );
816 /***********************************************************************
817 * InvertRgn32 (GDI32.246)
819 BOOL32 InvertRgn32( HDC32 hdc, HRGN32 hrgn )
821 HBRUSH32 prevBrush = SelectObject32( hdc, GetStockObject32(BLACK_BRUSH) );
822 INT32 prevROP = SetROP232( hdc, R2_NOT );
823 BOOL32 retval = PaintRgn32( hdc, hrgn );
824 SelectObject32( hdc, prevBrush );
825 SetROP232( hdc, prevROP );
826 return retval;
830 /***********************************************************************
831 * DrawFocusRect16 (USER.466)
833 void DrawFocusRect16( HDC16 hdc, const RECT16* rc )
835 RECT32 rect32;
836 CONV_RECT16TO32( rc, &rect32 );
837 DrawFocusRect32( hdc, &rect32 );
841 /***********************************************************************
842 * DrawFocusRect32 (USER32.155)
844 void DrawFocusRect32( HDC32 hdc, const RECT32* rc )
846 HPEN32 hOldPen;
847 INT32 oldDrawMode, oldBkMode;
848 INT32 left, top, right, bottom;
850 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
851 if (!dc) return;
853 left = XLPTODP( dc, rc->left );
854 top = YLPTODP( dc, rc->top );
855 right = XLPTODP( dc, rc->right );
856 bottom = YLPTODP( dc, rc->bottom );
858 hOldPen = SelectObject32( hdc, sysColorObjects.hpenWindowText );
859 oldDrawMode = SetROP232(hdc, R2_XORPEN);
860 oldBkMode = SetBkMode32(hdc, TRANSPARENT);
862 /* Hack: make sure the XORPEN operation has an effect */
863 dc->u.x.pen.pixel = (1 << screenDepth) - 1;
865 if (DC_SetupGCForPen( dc ))
866 XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
867 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
868 right-left-1, bottom-top-1 );
870 SetBkMode32(hdc, oldBkMode);
871 SetROP232(hdc, oldDrawMode);
872 SelectObject32(hdc, hOldPen);
876 /**********************************************************************
877 * GRAPH_DrawBitmap
879 * Short-cut function to blit a bitmap into a device.
880 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
882 BOOL32 GRAPH_DrawBitmap( HDC32 hdc, HBITMAP32 hbitmap, int xdest, int ydest,
883 int xsrc, int ysrc, int width, int height )
885 BITMAPOBJ *bmp;
886 DC *dc;
888 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
889 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
890 return FALSE;
891 XSetFunction( display, dc->u.x.gc, GXcopy );
892 if (bmp->bitmap.bmBitsPixel == 1)
894 XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
895 XSetBackground( display, dc->u.x.gc, dc->w.textPixel );
896 XCopyPlane( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
897 xsrc, ysrc, width, height,
898 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest, 1 );
899 return TRUE;
901 else if (bmp->bitmap.bmBitsPixel == dc->w.bitsPerPixel)
903 XCopyArea( display, bmp->pixmap, dc->u.x.drawable, dc->u.x.gc,
904 xsrc, ysrc, width, height,
905 dc->w.DCOrgX + xdest, dc->w.DCOrgY + ydest );
906 return TRUE;
908 else return FALSE;
912 /**********************************************************************
913 * GRAPH_DrawReliefRect (Not a MSWin Call)
915 void GRAPH_DrawReliefRect( HDC32 hdc, const RECT32 *rect, INT32 highlight_size,
916 INT32 shadow_size, BOOL32 pressed )
918 HBRUSH32 hbrushOld;
919 INT32 i;
921 hbrushOld = SelectObject32(hdc, pressed ? sysColorObjects.hbrushBtnShadow :
922 sysColorObjects.hbrushBtnHighlight );
923 for (i = 0; i < highlight_size; i++)
925 PatBlt32( hdc, rect->left + i, rect->top,
926 1, rect->bottom - rect->top - i, PATCOPY );
927 PatBlt32( hdc, rect->left, rect->top + i,
928 rect->right - rect->left - i, 1, PATCOPY );
931 SelectObject32( hdc, pressed ? sysColorObjects.hbrushBtnHighlight :
932 sysColorObjects.hbrushBtnShadow );
933 for (i = 0; i < shadow_size; i++)
935 PatBlt32( hdc, rect->right - i - 1, rect->top + i,
936 1, rect->bottom - rect->top - i, PATCOPY );
937 PatBlt32( hdc, rect->left + i, rect->bottom - i - 1,
938 rect->right - rect->left - i, 1, PATCOPY );
941 SelectObject32( hdc, hbrushOld );
945 /**********************************************************************
946 * Polyline16 (GDI.37)
948 BOOL16 Polyline16( HDC16 hdc, LPPOINT16 pt, INT16 count )
950 register int i;
951 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
952 if (!dc)
954 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
955 if (!dc) return FALSE;
956 MF_MetaPoly(dc, META_POLYLINE, pt, count);
957 return TRUE;
960 if (DC_SetupGCForPen( dc ))
961 for (i = 0; i < count-1; i ++)
962 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
963 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
964 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
965 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
966 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
967 return TRUE;
971 /**********************************************************************
972 * Polyline32 (GDI32.276)
974 BOOL32 Polyline32( HDC32 hdc, const LPPOINT32 pt, INT32 count )
976 register int i;
977 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
978 if (!dc)
980 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
981 if (!dc) return FALSE;
982 fprintf( stderr, "Polyline32: Metafile Polyline not yet supported for Win32\n");
983 /* win 16 code was:
984 MF_MetaPoly(dc, META_POLYLINE, pt, count);
985 return TRUE;
987 return FALSE;
990 if (DC_SetupGCForPen( dc ))
991 for (i = 0; i < count-1; i ++)
992 XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,
993 dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
994 dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
995 dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
996 dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
997 return TRUE;
1001 /**********************************************************************
1002 * Polygon16 (GDI.36)
1004 BOOL16 Polygon16( HDC16 hdc, LPPOINT16 pt, INT16 count )
1006 register int i;
1007 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1008 XPoint *points;
1010 if (!dc)
1012 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1013 if (!dc) return FALSE;
1014 MF_MetaPoly(dc, META_POLYGON, pt, count);
1015 return TRUE;
1018 points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
1019 for (i = 0; i < count; i++)
1021 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
1022 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
1024 points[count] = points[0];
1026 if (DC_SetupGCForBrush( dc ))
1027 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
1028 points, count+1, Complex, CoordModeOrigin);
1030 if (DC_SetupGCForPen ( dc ))
1031 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
1032 points, count+1, CoordModeOrigin );
1034 free( points );
1035 return TRUE;
1039 /**********************************************************************
1040 * Polygon32 (GDI32.275)
1042 * This a copy of Polygon16 so that conversion of array of
1043 * LPPOINT32 to LPPOINT16 is not necessary
1046 BOOL32 Polygon32( HDC32 hdc, LPPOINT32 pt, INT32 count )
1048 register int i;
1049 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1050 XPoint *points;
1052 if (!dc)
1054 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1055 if (!dc) return FALSE;
1056 /* FIXME: MF_MetaPoly expects LPPOINT16 not 32 */
1057 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
1058 return TRUE;
1061 points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
1062 for (i = 0; i < count; i++)
1064 points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
1065 points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
1067 points[count] = points[0];
1069 if (DC_SetupGCForBrush( dc ))
1070 XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
1071 points, count+1, Complex, CoordModeOrigin);
1073 if (DC_SetupGCForPen ( dc ))
1074 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
1075 points, count+1, CoordModeOrigin );
1077 free( points );
1078 return TRUE;
1082 /**********************************************************************
1083 * PolyPolygon16 (GDI.450)
1085 BOOL16 PolyPolygon16( HDC16 hdc, LPPOINT16 pt, LPINT16 counts, UINT16 polygons)
1087 HRGN32 hrgn;
1088 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1090 if (!dc)
1092 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1093 if (!dc) return FALSE;
1094 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
1095 return TRUE;
1097 /* FIXME: The points should be converted to device coords before */
1098 /* creating the region. But as CreatePolyPolygonRgn is not */
1099 /* really correct either, it doesn't matter much... */
1100 /* At least the outline will be correct :-) */
1101 hrgn = CreatePolyPolygonRgn16( pt, counts, polygons, dc->w.polyFillMode );
1102 PaintRgn32( hdc, hrgn );
1103 DeleteObject32( hrgn );
1105 /* Draw the outline of the polygons */
1107 if (DC_SetupGCForPen ( dc ))
1109 int i, j, max = 0;
1110 XPoint *points;
1112 for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
1113 points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
1115 for (i = 0; i < polygons; i++)
1117 for (j = 0; j < counts[i]; j++)
1119 points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
1120 points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
1121 pt++;
1123 points[j] = points[0];
1124 XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
1125 points, j + 1, CoordModeOrigin );
1127 free( points );
1129 return TRUE;
1133 /**********************************************************************
1134 * GRAPH_InternalFloodFill
1136 * Internal helper function for flood fill.
1137 * (xorg,yorg) is the origin of the X image relative to the drawable.
1138 * (x,y) is relative to the origin of the X image.
1140 static void GRAPH_InternalFloodFill( XImage *image, DC *dc,
1141 int x, int y,
1142 int xOrg, int yOrg,
1143 Pixel pixel, WORD fillType )
1145 int left, right;
1147 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
1148 (XGetPixel(image,x,y) != pixel) : \
1149 (XGetPixel(image,x,y) == pixel))
1151 if (!TO_FLOOD(x,y)) return;
1153 /* Find left and right boundaries */
1155 left = right = x;
1156 while ((left > 0) && TO_FLOOD( left-1, y )) left--;
1157 while ((right < image->width) && TO_FLOOD( right, y )) right++;
1158 XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
1159 xOrg + left, yOrg + y, right-left, 1 );
1161 /* Set the pixels of this line so we don't fill it again */
1163 for (x = left; x < right; x++)
1165 if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
1166 else XPutPixel( image, x, y, ~pixel );
1169 /* Fill the line above */
1171 if (--y >= 0)
1173 x = left;
1174 while (x < right)
1176 while ((x < right) && !TO_FLOOD(x,y)) x++;
1177 if (x >= right) break;
1178 while ((x < right) && TO_FLOOD(x,y)) x++;
1179 GRAPH_InternalFloodFill( image, dc, x-1, y,
1180 xOrg, yOrg, pixel, fillType );
1184 /* Fill the line below */
1186 if ((y += 2) < image->height)
1188 x = left;
1189 while (x < right)
1191 while ((x < right) && !TO_FLOOD(x,y)) x++;
1192 if (x >= right) break;
1193 while ((x < right) && TO_FLOOD(x,y)) x++;
1194 GRAPH_InternalFloodFill( image, dc, x-1, y,
1195 xOrg, yOrg, pixel, fillType );
1198 #undef TO_FLOOD
1202 /**********************************************************************
1203 * GRAPH_DoFloodFill
1205 * Main flood-fill routine.
1207 static BOOL32 GRAPH_DoFloodFill( DC *dc, RECT32 *rect, INT32 x, INT32 y,
1208 COLORREF color, UINT32 fillType )
1210 XImage *image;
1212 if (!(image = XGetImage( display, dc->u.x.drawable,
1213 dc->w.DCOrgX + rect->left,
1214 dc->w.DCOrgY + rect->top,
1215 rect->right - rect->left,
1216 rect->bottom - rect->top,
1217 AllPlanes, ZPixmap ))) return FALSE;
1219 if (DC_SetupGCForBrush( dc ))
1221 /* ROP mode is always GXcopy for flood-fill */
1222 XSetFunction( display, dc->u.x.gc, GXcopy );
1223 GRAPH_InternalFloodFill( image, dc,
1224 XLPTODP(dc,x) - rect->left,
1225 YLPTODP(dc,y) - rect->top,
1226 dc->w.DCOrgX + rect->left,
1227 dc->w.DCOrgY + rect->top,
1228 COLOR_ToPhysical( dc, color ), fillType );
1231 XDestroyImage( image );
1232 return TRUE;
1236 /**********************************************************************
1237 * ExtFloodFill16 (GDI.372)
1239 BOOL16 ExtFloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color,
1240 UINT16 fillType )
1242 return ExtFloodFill32( hdc, x, y, color, fillType );
1246 /**********************************************************************
1247 * ExtFloodFill32 (GDI32.96)
1249 BOOL32 ExtFloodFill32( HDC32 hdc, INT32 x, INT32 y, COLORREF color,
1250 UINT32 fillType )
1252 RECT32 rect;
1253 DC *dc;
1255 dprintf_graphics( stddeb, "ExtFloodFill %04x %d,%d %06lx %d\n",
1256 hdc, x, y, color, fillType );
1257 dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
1258 if (!dc)
1260 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
1261 if (!dc) return FALSE;
1262 MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(color),
1263 LOWORD(color));
1264 return TRUE;
1267 if (!PtVisible32( hdc, x, y )) return FALSE;
1268 if (GetRgnBox32( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
1270 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill, 6,
1271 dc, &rect, x, y, color, fillType );
1275 /**********************************************************************
1276 * FloodFill16 (GDI.25)
1278 BOOL16 FloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
1280 return ExtFloodFill32( hdc, x, y, color, FLOODFILLBORDER );
1284 /**********************************************************************
1285 * FloodFill32 (GDI32.104)
1287 BOOL32 FloodFill32( HDC32 hdc, INT32 x, INT32 y, COLORREF color )
1289 return ExtFloodFill32( hdc, x, y, color, FLOODFILLBORDER );
1293 /**********************************************************************
1294 * DrawEdge16 (USER.659)
1296 BOOL16 DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
1298 RECT32 rect32;
1299 BOOL32 ret;
1301 CONV_RECT16TO32( rc, &rect32 );
1302 ret = DrawEdge32( hdc, &rect32, edge, flags );
1303 CONV_RECT32TO16( &rect32, rc );
1304 return ret;
1308 /**********************************************************************
1309 * DrawEdge32 (USER32.154)
1311 BOOL32 DrawEdge32( HDC32 hdc, LPRECT32 rc, UINT32 edge, UINT32 flags )
1313 HBRUSH32 hbrushOld;
1315 if (flags >= BF_DIAGONAL)
1316 fprintf( stderr, "DrawEdge: unsupported flags %04x\n", flags );
1318 dprintf_graphics( stddeb, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
1319 hdc, rc->left, rc->top, rc->right, rc->bottom,
1320 edge, flags );
1322 /* First do all the raised edges */
1324 hbrushOld = SelectObject32( hdc, sysColorObjects.hbrushBtnHighlight );
1325 if (edge & BDR_RAISEDOUTER)
1327 if (flags & BF_LEFT) PatBlt32( hdc, rc->left, rc->top,
1328 1, rc->bottom - rc->top - 1, PATCOPY );
1329 if (flags & BF_TOP) PatBlt32( hdc, rc->left, rc->top,
1330 rc->right - rc->left - 1, 1, PATCOPY );
1332 if (edge & BDR_SUNKENOUTER)
1334 if (flags & BF_RIGHT) PatBlt32( hdc, rc->right - 1, rc->top,
1335 1, rc->bottom - rc->top, PATCOPY );
1336 if (flags & BF_BOTTOM) PatBlt32( hdc, rc->left, rc->bottom - 1,
1337 rc->right - rc->left, 1, PATCOPY );
1339 if (edge & BDR_RAISEDINNER)
1341 if (flags & BF_LEFT) PatBlt32( hdc, rc->left + 1, rc->top + 1,
1342 1, rc->bottom - rc->top - 2, PATCOPY );
1343 if (flags & BF_TOP) PatBlt32( hdc, rc->left + 1, rc->top + 1,
1344 rc->right - rc->left - 2, 1, PATCOPY );
1346 if (edge & BDR_SUNKENINNER)
1348 if (flags & BF_RIGHT) PatBlt32( hdc, rc->right - 2, rc->top + 1,
1349 1, rc->bottom - rc->top - 2, PATCOPY );
1350 if (flags & BF_BOTTOM) PatBlt32( hdc, rc->left + 1, rc->bottom - 2,
1351 rc->right - rc->left - 2, 1, PATCOPY );
1354 /* Then do all the sunken edges */
1356 SelectObject32( hdc, sysColorObjects.hbrushBtnShadow );
1357 if (edge & BDR_SUNKENOUTER)
1359 if (flags & BF_LEFT) PatBlt32( hdc, rc->left, rc->top,
1360 1, rc->bottom - rc->top - 1, PATCOPY );
1361 if (flags & BF_TOP) PatBlt32( hdc, rc->left, rc->top,
1362 rc->right - rc->left - 1, 1, PATCOPY );
1364 if (edge & BDR_RAISEDOUTER)
1366 if (flags & BF_RIGHT) PatBlt32( hdc, rc->right - 1, rc->top,
1367 1, rc->bottom - rc->top, PATCOPY );
1368 if (flags & BF_BOTTOM) PatBlt32( hdc, rc->left, rc->bottom - 1,
1369 rc->right - rc->left, 1, PATCOPY );
1371 if (edge & BDR_SUNKENINNER)
1373 if (flags & BF_LEFT) PatBlt32( hdc, rc->left + 1, rc->top + 1,
1374 1, rc->bottom - rc->top - 2, PATCOPY );
1375 if (flags & BF_TOP) PatBlt32( hdc, rc->left + 1, rc->top + 1,
1376 rc->right - rc->left - 2, 1, PATCOPY );
1378 if (edge & BDR_RAISEDINNER)
1380 if (flags & BF_RIGHT) PatBlt32( hdc, rc->right - 2, rc->top + 1,
1381 1, rc->bottom - rc->top - 2, PATCOPY );
1382 if (flags & BF_BOTTOM) PatBlt32( hdc, rc->left + 1, rc->bottom - 2,
1383 rc->right - rc->left - 2, 1, PATCOPY );
1386 SelectObject32( hdc, hbrushOld );
1387 return TRUE;
1391 /**********************************************************************
1392 * DrawFrameControl16 (USER.656)
1394 BOOL16 DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
1396 fprintf( stdnimp,"DrawFrameControl16(%x,%p,%d,%x), empty stub!\n",
1397 hdc,rc,edge,flags );
1398 return TRUE;
1402 /**********************************************************************
1403 * DrawFrameControl32 (USER32.157)
1405 BOOL32 DrawFrameControl32( HDC32 hdc, LPRECT32 rc, UINT32 edge, UINT32 flags )
1407 fprintf( stdnimp,"DrawFrameControl32(%x,%p,%d,%x), empty stub!\n",
1408 hdc,rc,edge,flags );
1409 return TRUE;