2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
25 static __inline__
void swap_int(int *a
, int *b
)
34 /***********************************************************************
37 BOOL
LineTo( HDC hdc
, short x
, short y
)
39 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
42 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
43 if (!dc
) return FALSE
;
44 MF_MetaParam2(dc
, META_LINETO
, x
, y
);
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
) );
60 /***********************************************************************
63 DWORD
MoveTo( HDC hdc
, short x
, short y
)
66 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
69 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
70 if (!dc
) return FALSE
;
71 MF_MetaParam2(dc
, META_MOVETO
, x
, y
);
75 oldx
= dc
->w
.CursPosX
;
76 oldy
= dc
->w
.CursPosY
;
79 return oldx
| (oldy
<< 16);
83 /***********************************************************************
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
;
92 pt
->x
= dc
->w
.CursPosX
;
93 pt
->y
= dc
->w
.CursPosY
;
101 /***********************************************************************
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 static 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
;
113 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
116 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
117 if (!dc
) return FALSE
;
121 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
122 xstart
, ystart
, xend
, yend
);
126 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
127 xstart
, ystart
, xend
, yend
);
131 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
132 xstart
, ystart
, xend
, yend
);
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 xcenter
= (right
+ left
) / 2;
149 ycenter
= (bottom
+ top
) / 2;
150 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
151 (double)(xstart
-xcenter
)*(bottom
-top
) );
152 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
153 (double)(xend
-xcenter
)*(bottom
-top
) );
154 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
155 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
156 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
157 if (left
> right
) swap_int( &left
, &right
);
158 if (top
> bottom
) swap_int( &top
, &bottom
);
160 /* Fill arc with brush if Chord() or Pie() */
162 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
164 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
165 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
166 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
167 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
170 /* Draw arc and lines */
172 if (!DC_SetupGCForPen( dc
)) return TRUE
;
173 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
174 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
175 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
176 if (!lines
) return TRUE
;
178 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
179 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
180 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
181 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
184 points
[2] = points
[1];
185 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
186 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
188 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
189 points
, lines
+1, CoordModeOrigin
);
194 /***********************************************************************
197 BOOL
Arc( 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
, 0 );
205 /***********************************************************************
208 BOOL
Pie( 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
, 2 );
216 /***********************************************************************
219 BOOL
Chord( HDC hdc
, int left
, int top
, int right
, int bottom
,
220 int xstart
, int ystart
, int xend
, int yend
)
222 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
223 xstart
, ystart
, xend
, yend
, 1 );
227 /***********************************************************************
230 BOOL
Ellipse( HDC hdc
, int left
, int top
, int right
, int bottom
)
232 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
235 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
236 if (!dc
) return FALSE
;
237 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
241 left
= XLPTODP( dc
, left
);
242 top
= YLPTODP( dc
, top
);
243 right
= XLPTODP( dc
, right
);
244 bottom
= YLPTODP( dc
, bottom
);
245 if ((left
== right
) || (top
== bottom
)) return FALSE
;
248 swap_int(&right
, &left
);
251 swap_int(&bottom
, &top
);
253 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
254 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
255 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
257 left
+= dc
->u
.x
.pen
.width
/ 2;
258 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
259 top
+= dc
->u
.x
.pen
.width
/ 2;
260 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
263 if (DC_SetupGCForBrush( dc
))
264 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
265 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
266 right
-left
-1, bottom
-top
-1, 0, 360*64 );
267 if (DC_SetupGCForPen( dc
))
268 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
269 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
270 right
-left
-1, bottom
-top
-1, 0, 360*64 );
275 /***********************************************************************
278 BOOL
Rectangle( HDC hdc
, int left
, int top
, int right
, int bottom
)
280 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
283 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
284 if (!dc
) return FALSE
;
285 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
288 left
= XLPTODP( dc
, left
);
289 top
= YLPTODP( dc
, top
);
290 right
= XLPTODP( dc
, right
);
291 bottom
= YLPTODP( dc
, bottom
);
294 swap_int(&right
, &left
);
297 swap_int(&bottom
, &top
);
299 if ((left
== right
) || (top
== bottom
))
301 if (DC_SetupGCForPen( dc
))
302 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
305 dc
->w
.DCOrgX
+ right
,
306 dc
->w
.DCOrgY
+ bottom
);
310 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
311 (dc
->u
.x
.pen
.width
< right
-left
) &&
312 (dc
->u
.x
.pen
.width
< bottom
-top
))
314 left
+= dc
->u
.x
.pen
.width
/ 2;
315 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
316 top
+= dc
->u
.x
.pen
.width
/ 2;
317 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
320 if (DC_SetupGCForBrush( dc
))
321 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
322 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
323 right
-left
, bottom
-top
);
324 if (DC_SetupGCForPen( dc
))
325 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
326 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
327 right
-left
-1, bottom
-top
-1 );
332 /***********************************************************************
335 BOOL
RoundRect( HDC hDC
, short left
, short top
, short right
, short bottom
,
336 short ell_width
, short ell_height
)
338 DC
* dc
= (DC
*) GDI_GetObjPtr(hDC
, DC_MAGIC
);
341 dc
= (DC
*)GDI_GetObjPtr(hDC
, METAFILE_DC_MAGIC
);
342 if (!dc
) return FALSE
;
343 MF_MetaParam6(dc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
344 ell_width
, ell_height
);
347 dprintf_graphics(stddeb
, "RoundRect(%d %d %d %d %d %d\n",
348 left
, top
, right
, bottom
, ell_width
, ell_height
);
350 left
= XLPTODP( dc
, left
);
351 top
= YLPTODP( dc
, top
);
352 right
= XLPTODP( dc
, right
);
353 bottom
= YLPTODP( dc
, bottom
);
354 ell_width
= abs( ell_width
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
);
355 ell_height
= abs( ell_height
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
357 /* Fix the coordinates */
359 if (left
> right
) { short t
= left
; left
= right
; right
= t
; }
360 if (top
> bottom
) { short t
= top
; top
= bottom
; bottom
= t
; }
361 if (ell_width
> right
- left
) ell_width
= right
- left
;
362 if (ell_height
> bottom
- top
) ell_height
= bottom
- top
;
364 if (DC_SetupGCForBrush( dc
))
366 if (ell_width
&& ell_height
)
368 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
369 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
370 ell_width
, ell_height
, 90 * 64, 90 * 64 );
371 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
372 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
373 ell_width
, ell_height
, 180 * 64, 90 * 64 );
374 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
375 dc
->w
.DCOrgX
+ right
- ell_width
,
376 dc
->w
.DCOrgY
+ bottom
- ell_height
,
377 ell_width
, ell_height
, 270 * 64, 90 * 64 );
378 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
379 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
380 ell_width
, ell_height
, 0, 90 * 64 );
382 if (ell_width
< right
- left
)
384 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
385 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
387 right
- left
- ell_width
, ell_height
/ 2 );
388 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
389 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
390 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2,
391 right
- left
- ell_width
, (ell_height
+1) / 2 );
393 if (ell_height
< bottom
- top
)
395 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
397 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
398 right
- left
, bottom
- top
- ell_height
);
401 if (DC_SetupGCForPen(dc
))
403 if (ell_width
&& ell_height
)
405 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
406 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
407 ell_width
, ell_height
, 90 * 64, 90 * 64 );
408 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
409 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
410 ell_width
, ell_height
, 180 * 64, 90 * 64 );
411 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
412 dc
->w
.DCOrgX
+ right
- ell_width
,
413 dc
->w
.DCOrgY
+ bottom
- ell_height
,
414 ell_width
, ell_height
, 270 * 64, 90 * 64 );
415 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
416 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
417 ell_width
, ell_height
, 0, 90 * 64 );
419 if (ell_width
< right
- left
)
421 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
422 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
424 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
425 dc
->w
.DCOrgY
+ top
);
426 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
427 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
428 dc
->w
.DCOrgY
+ bottom
,
429 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
430 dc
->w
.DCOrgY
+ bottom
);
432 if (ell_height
< bottom
- top
)
434 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
435 dc
->w
.DCOrgX
+ right
,
436 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
437 dc
->w
.DCOrgX
+ right
,
438 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
439 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
441 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
443 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
450 /***********************************************************************
453 int FillRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
457 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
458 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
459 PatBlt( hdc
, rect
->left
, rect
->top
,
460 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
461 SelectObject( hdc
, prevBrush
);
466 /***********************************************************************
467 * InvertRect (USER.82)
469 void InvertRect( HDC hdc
, LPRECT rect
)
471 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
472 PatBlt( hdc
, rect
->left
, rect
->top
,
473 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
477 /***********************************************************************
478 * FrameRect (USER.83)
480 int FrameRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
483 int left
, top
, right
, bottom
;
485 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
486 if (!dc
) return FALSE
;
488 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
489 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
491 left
= XLPTODP( dc
, rect
->left
);
492 top
= YLPTODP( dc
, rect
->top
);
493 right
= XLPTODP( dc
, rect
->right
);
494 bottom
= YLPTODP( dc
, rect
->bottom
);
496 if (DC_SetupGCForBrush( dc
))
498 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
499 rect
->bottom
- rect
->top
, PATCOPY
);
500 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
501 rect
->bottom
- rect
->top
, PATCOPY
);
502 PatBlt( hdc
, rect
->left
, rect
->top
,
503 rect
->right
- rect
->left
, 1, PATCOPY
);
504 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
505 rect
->right
- rect
->left
, 1, PATCOPY
);
507 SelectObject( hdc
, prevBrush
);
512 /***********************************************************************
515 COLORREF
SetPixel( HDC hdc
, short x
, short y
, COLORREF color
)
520 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
523 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
525 MF_MetaParam4(dc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
));
529 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
530 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
531 pixel
= COLOR_ToPhysical( dc
, color
);
533 XSetForeground( display
, dc
->u
.x
.gc
, pixel
);
534 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
535 XDrawPoint( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
, x
, y
);
537 if (screenDepth
<= 8)
539 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
540 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
542 else return (COLORREF
)pixel
;
546 /***********************************************************************
549 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
556 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
559 #ifdef SOLITAIRE_SPEED_HACK
563 if (!PtVisible( hdc
, x
, y
)) return 0;
565 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
566 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
567 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
,
568 1, 1, AllPlanes
, ZPixmap
);
569 pixel
= XGetPixel( image
, 0, 0 );
570 XDestroyImage( image
);
572 if (screenDepth
> 8) return pixel
;
573 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hRevMapping
);
574 if (mapping
) pixel
= mapping
[pixel
];
575 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
576 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
580 /***********************************************************************
583 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
586 HRGN tmpVisRgn
, prevVisRgn
;
587 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
588 if (!dc
) return FALSE
;
590 /* Modify visible region */
592 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
593 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
595 RestoreVisRgn( hdc
);
598 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
599 SelectVisRgn( hdc
, tmpVisRgn
);
600 DeleteObject( tmpVisRgn
);
602 /* Fill the region */
604 GetRgnBox( dc
->w
.hGCClipRgn
, &box
);
605 if (DC_SetupGCForBrush( dc
))
606 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
607 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
608 box
.right
-box
.left
, box
.bottom
-box
.top
);
610 /* Restore the visible region */
612 RestoreVisRgn( hdc
);
617 /***********************************************************************
620 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
623 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
624 if (!prevBrush
) return FALSE
;
625 retval
= PaintRgn( hdc
, hrgn
);
626 SelectObject( hdc
, prevBrush
);
630 /***********************************************************************
633 BOOL
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, int nWidth
, int nHeight
)
635 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
636 if(!REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
)) return 0;
637 FillRgn( hdc
, tmp
, hbrush
);
642 /***********************************************************************
645 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
647 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
648 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
649 BOOL retval
= PaintRgn( hdc
, hrgn
);
650 SelectObject( hdc
, prevBrush
);
651 SetROP2( hdc
, prevROP
);
656 /***********************************************************************
657 * DrawFocusRect (USER.466)
659 void DrawFocusRect( HDC hdc
, LPRECT rc
)
662 int oldDrawMode
, oldBkMode
;
663 int left
, top
, right
, bottom
;
664 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
667 left
= XLPTODP( dc
, rc
->left
);
668 top
= YLPTODP( dc
, rc
->top
);
669 right
= XLPTODP( dc
, rc
->right
);
670 bottom
= YLPTODP( dc
, rc
->bottom
);
672 hOldPen
= (HPEN
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
673 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
674 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
676 if (DC_SetupGCForPen( dc
))
677 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
678 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
679 right
-left
-1, bottom
-top
-1 );
681 SetBkMode(hdc
, oldBkMode
);
682 SetROP2(hdc
, oldDrawMode
);
683 SelectObject(hdc
, (HANDLE
)hOldPen
);
687 /**********************************************************************
690 * Short-cut function to blit a bitmap into a device.
691 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
693 BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
694 int xsrc
, int ysrc
, int width
, int height
)
699 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
700 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
702 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
703 if (bmp
->bitmap
.bmBitsPixel
== 1)
705 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
706 XSetBackground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
707 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
708 xsrc
, ysrc
, width
, height
,
709 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
712 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
714 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
715 xsrc
, ysrc
, width
, height
,
716 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
723 /**********************************************************************
724 * GRAPH_DrawReliefRect (Not a MSWin Call)
726 void GRAPH_DrawReliefRect( HDC hdc
, RECT
*rect
, int highlight_size
,
727 int shadow_size
, BOOL pressed
)
732 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
733 sysColorObjects
.hbrushBtnHighlight
);
734 for (i
= 0; i
< highlight_size
; i
++)
736 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
737 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
738 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
739 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
742 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
743 sysColorObjects
.hbrushBtnShadow
);
744 for (i
= 0; i
< shadow_size
; i
++)
746 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
747 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
748 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
749 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
752 SelectObject( hdc
, hbrushOld
);
756 /**********************************************************************
759 BOOL
Polyline (HDC hdc
, LPPOINT pt
, int count
)
762 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
765 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
766 if (!dc
) return FALSE
;
767 MF_MetaPoly(dc
, META_POLYLINE
, pt
, count
);
771 if (DC_SetupGCForPen( dc
))
772 for (i
= 0; i
< count
-1; i
++)
773 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
774 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
775 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
776 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
777 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
782 /**********************************************************************
785 BOOL
Polygon (HDC hdc
, LPPOINT pt
, int count
)
788 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
789 XPoint
*points
= (XPoint
*) malloc (sizeof (XPoint
) * (count
+1));
793 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
794 if (!dc
) return FALSE
;
795 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
799 for (i
= 0; i
< count
; i
++)
801 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
802 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
804 points
[count
] = points
[0];
806 if (DC_SetupGCForBrush( dc
))
807 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
808 points
, count
+1, Complex
, CoordModeOrigin
);
810 if (DC_SetupGCForPen ( dc
))
811 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
812 points
, count
+1, CoordModeOrigin
);
819 /**********************************************************************
820 * PolyPolygon (GDI.450)
822 BOOL
PolyPolygon( HDC hdc
, LPPOINT pt
, LPINT counts
, WORD polygons
)
825 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
829 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
830 if (!dc
) return FALSE
;
831 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
834 /* FIXME: The points should be converted to device coords before */
835 /* creating the region. But as CreatePolyPolygonRgn is not */
836 /* really correct either, it doesn't matter much... */
837 /* At least the outline will be correct :-) */
838 hrgn
= CreatePolyPolygonRgn( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
839 PaintRgn( hdc
, hrgn
);
840 DeleteObject( hrgn
);
842 /* Draw the outline of the polygons */
844 if (DC_SetupGCForPen ( dc
))
849 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
850 points
= (XPoint
*) malloc( sizeof(XPoint
) * (max
+1) );
852 for (i
= 0; i
< polygons
; i
++)
854 for (j
= 0; j
< counts
[i
]; j
++)
856 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
857 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
860 points
[j
] = points
[0];
861 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
862 points
, j
+ 1, CoordModeOrigin
);
870 /**********************************************************************
871 * GRAPH_InternalFloodFill
873 * Internal helper function for flood fill.
874 * (xorg,yorg) is the origin of the X image relative to the drawable.
875 * (x,y) is relative to the origin of the X image.
877 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
880 Pixel pixel
, WORD fillType
)
884 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
885 (XGetPixel(image,x,y) != pixel) : \
886 (XGetPixel(image,x,y) == pixel))
888 if (!TO_FLOOD(x
,y
)) return;
890 /* Find left and right boundaries */
893 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
894 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
895 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
896 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
898 /* Set the pixels of this line so we don't fill it again */
900 for (x
= left
; x
< right
; x
++)
902 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
903 else XPutPixel( image
, x
, y
, ~pixel
);
906 /* Fill the line above */
913 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
914 if (x
>= right
) break;
915 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
916 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
917 xOrg
, yOrg
, pixel
, fillType
);
921 /* Fill the line below */
923 if ((y
+= 2) < image
->height
)
928 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
929 if (x
>= right
) break;
930 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
931 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
932 xOrg
, yOrg
, pixel
, fillType
);
939 /**********************************************************************
942 * Main flood-fill routine.
944 static BOOL
GRAPH_DoFloodFill( DC
*dc
, RECT
*rect
, INT x
, INT y
,
945 COLORREF color
, WORD fillType
)
949 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
950 dc
->w
.DCOrgX
+ rect
->left
,
951 dc
->w
.DCOrgY
+ rect
->top
,
952 rect
->right
- rect
->left
,
953 rect
->bottom
- rect
->top
,
954 AllPlanes
, ZPixmap
))) return FALSE
;
956 if (DC_SetupGCForBrush( dc
))
958 /* ROP mode is always GXcopy for flood-fill */
959 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
960 GRAPH_InternalFloodFill( image
, dc
,
961 XLPTODP(dc
,x
) - rect
->left
,
962 YLPTODP(dc
,y
) - rect
->top
,
963 dc
->w
.DCOrgX
+ rect
->left
,
964 dc
->w
.DCOrgY
+ rect
->top
,
965 COLOR_ToPhysical( dc
, color
), fillType
);
968 XDestroyImage( image
);
973 /**********************************************************************
974 * ExtFloodFill (GDI.372)
976 BOOL
ExtFloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
, WORD fillType
)
981 dprintf_graphics( stddeb
, "ExtFloodFill "NPFMT
" %d,%d %06lx %d\n",
982 hdc
, x
, y
, color
, fillType
);
983 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
986 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
987 if (!dc
) return FALSE
;
988 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
993 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
994 if (GetRgnBox( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
996 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill
, 6,
997 dc
, &rect
, x
, y
, color
, fillType
);
1001 /**********************************************************************
1002 * FloodFill (GDI.25)
1004 BOOL
FloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
)
1006 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);