2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
26 /***********************************************************************
29 BOOL
LineTo( HDC hdc
, short x
, short y
)
31 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
34 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
35 if (!dc
) return FALSE
;
36 MF_MetaParam2(dc
, META_LINETO
, x
, y
);
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
) );
52 /***********************************************************************
55 DWORD
MoveTo( HDC hdc
, short x
, short y
)
58 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
61 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
62 if (!dc
) return FALSE
;
63 MF_MetaParam2(dc
, META_MOVETO
, x
, y
);
67 oldx
= dc
->w
.CursPosX
;
68 oldy
= dc
->w
.CursPosY
;
71 return oldx
| (oldy
<< 16);
75 /***********************************************************************
78 BOOL
MoveToEx( HDC hdc
, short x
, short y
, LPPOINT pt
)
80 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
81 if (!dc
) return FALSE
;
84 pt
->x
= dc
->w
.CursPosX
;
85 pt
->y
= dc
->w
.CursPosY
;
93 /***********************************************************************
96 * Helper functions for Arc(), Chord() and Pie().
97 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
99 static BOOL
GRAPH_DrawArc( HDC hdc
, int left
, int top
, int right
, int bottom
,
100 int xstart
, int ystart
, int xend
, int yend
, int lines
)
102 int xcenter
, ycenter
, istart_angle
, idiff_angle
, tmp
;
103 double start_angle
, end_angle
;
105 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
108 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
109 if (!dc
) return FALSE
;
113 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
114 xstart
, ystart
, xend
, yend
);
118 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
119 xstart
, ystart
, xend
, yend
);
123 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
124 xstart
, ystart
, xend
, yend
);
130 left
= XLPTODP( dc
, left
);
131 top
= YLPTODP( dc
, top
);
132 right
= XLPTODP( dc
, right
);
133 bottom
= YLPTODP( dc
, bottom
);
134 xstart
= XLPTODP( dc
, xstart
);
135 ystart
= YLPTODP( dc
, ystart
);
136 xend
= XLPTODP( dc
, xend
);
137 yend
= YLPTODP( dc
, yend
);
138 if ((left
== right
) || (top
== bottom
)) return FALSE
;
140 xcenter
= (right
+ left
) / 2;
141 ycenter
= (bottom
+ top
) / 2;
142 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
143 (double)(xstart
-xcenter
)*(bottom
-top
) );
144 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
145 (double)(xend
-xcenter
)*(bottom
-top
) );
146 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
147 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
148 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
149 if (left
> right
) { tmp
=left
; left
=right
; right
=tmp
; }
150 if (top
> bottom
) { tmp
=top
; top
=bottom
; bottom
=tmp
; }
152 /* Fill arc with brush if Chord() or Pie() */
154 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
156 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
157 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
158 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
159 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
162 /* Draw arc and lines */
164 if (!DC_SetupGCForPen( dc
)) return TRUE
;
165 XDrawArc( 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
);
168 if (!lines
) return TRUE
;
170 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
171 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
172 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
173 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
176 points
[2] = points
[1];
177 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
178 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
180 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
181 points
, lines
+1, CoordModeOrigin
);
186 /***********************************************************************
189 BOOL
Arc( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
190 INT xstart
, INT ystart
, INT xend
, INT yend
)
192 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
193 xstart
, ystart
, xend
, yend
, 0 );
197 /***********************************************************************
200 BOOL
Pie( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
201 INT xstart
, INT ystart
, INT xend
, INT yend
)
203 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
204 xstart
, ystart
, xend
, yend
, 2 );
208 /***********************************************************************
211 BOOL
Chord( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
212 INT xstart
, INT ystart
, INT xend
, INT yend
)
214 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
215 xstart
, ystart
, xend
, yend
, 1 );
219 /***********************************************************************
222 BOOL
Ellipse( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
224 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
227 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
228 if (!dc
) return FALSE
;
229 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
233 left
= XLPTODP( dc
, left
);
234 top
= YLPTODP( dc
, top
);
235 right
= XLPTODP( dc
, right
);
236 bottom
= YLPTODP( dc
, bottom
);
237 if ((left
== right
) || (top
== bottom
)) return FALSE
;
239 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
240 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
242 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
243 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
244 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
246 left
+= dc
->u
.x
.pen
.width
/ 2;
247 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
248 top
+= dc
->u
.x
.pen
.width
/ 2;
249 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
252 if (DC_SetupGCForBrush( dc
))
253 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
254 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
255 right
-left
-1, bottom
-top
-1, 0, 360*64 );
256 if (DC_SetupGCForPen( dc
))
257 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
258 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
259 right
-left
-1, bottom
-top
-1, 0, 360*64 );
264 /***********************************************************************
267 BOOL
Rectangle( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
269 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
272 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
273 if (!dc
) return FALSE
;
274 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
277 left
= XLPTODP( dc
, left
);
278 top
= YLPTODP( dc
, top
);
279 right
= XLPTODP( dc
, right
);
280 bottom
= YLPTODP( dc
, bottom
);
282 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
283 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
285 if ((left
== right
) || (top
== bottom
))
287 if (DC_SetupGCForPen( dc
))
288 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
291 dc
->w
.DCOrgX
+ right
,
292 dc
->w
.DCOrgY
+ bottom
);
296 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
297 (dc
->u
.x
.pen
.width
< right
-left
) &&
298 (dc
->u
.x
.pen
.width
< bottom
-top
))
300 left
+= dc
->u
.x
.pen
.width
/ 2;
301 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
302 top
+= dc
->u
.x
.pen
.width
/ 2;
303 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
306 if (DC_SetupGCForBrush( dc
))
307 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
308 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
309 right
-left
, bottom
-top
);
310 if (DC_SetupGCForPen( dc
))
311 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
312 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
313 right
-left
-1, bottom
-top
-1 );
318 /***********************************************************************
321 BOOL
RoundRect( HDC hDC
, INT left
, INT top
, INT right
, INT bottom
,
322 INT ell_width
, INT ell_height
)
324 DC
* dc
= (DC
*) GDI_GetObjPtr(hDC
, DC_MAGIC
);
327 dc
= (DC
*)GDI_GetObjPtr(hDC
, METAFILE_DC_MAGIC
);
328 if (!dc
) return FALSE
;
329 MF_MetaParam6(dc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
330 ell_width
, ell_height
);
333 dprintf_graphics(stddeb
, "RoundRect(%d %d %d %d %d %d\n",
334 left
, top
, right
, bottom
, ell_width
, ell_height
);
336 left
= XLPTODP( dc
, left
);
337 top
= YLPTODP( dc
, top
);
338 right
= XLPTODP( dc
, right
);
339 bottom
= YLPTODP( dc
, bottom
);
340 ell_width
= abs( ell_width
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
);
341 ell_height
= abs( ell_height
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
343 /* Fix the coordinates */
345 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
346 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
347 if (ell_width
> right
- left
) ell_width
= right
- left
;
348 if (ell_height
> bottom
- top
) ell_height
= bottom
- top
;
350 if (DC_SetupGCForBrush( dc
))
352 if (ell_width
&& ell_height
)
354 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
355 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
356 ell_width
, ell_height
, 90 * 64, 90 * 64 );
357 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
358 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
359 ell_width
, ell_height
, 180 * 64, 90 * 64 );
360 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
361 dc
->w
.DCOrgX
+ right
- ell_width
,
362 dc
->w
.DCOrgY
+ bottom
- ell_height
,
363 ell_width
, ell_height
, 270 * 64, 90 * 64 );
364 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
365 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
366 ell_width
, ell_height
, 0, 90 * 64 );
368 if (ell_width
< right
- left
)
370 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
371 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
373 right
- left
- ell_width
, ell_height
/ 2 );
374 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
375 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
376 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2,
377 right
- left
- ell_width
, (ell_height
+1) / 2 );
379 if (ell_height
< bottom
- top
)
381 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
383 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
384 right
- left
, bottom
- top
- ell_height
);
387 if (DC_SetupGCForPen(dc
))
389 if (ell_width
&& ell_height
)
391 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
392 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
393 ell_width
, ell_height
, 90 * 64, 90 * 64 );
394 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
395 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
396 ell_width
, ell_height
, 180 * 64, 90 * 64 );
397 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
398 dc
->w
.DCOrgX
+ right
- ell_width
,
399 dc
->w
.DCOrgY
+ bottom
- ell_height
,
400 ell_width
, ell_height
, 270 * 64, 90 * 64 );
401 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
402 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
403 ell_width
, ell_height
, 0, 90 * 64 );
405 if (ell_width
< right
- left
)
407 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
408 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
410 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
411 dc
->w
.DCOrgY
+ top
);
412 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
413 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
414 dc
->w
.DCOrgY
+ bottom
,
415 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
416 dc
->w
.DCOrgY
+ bottom
);
418 if (ell_height
< bottom
- top
)
420 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
421 dc
->w
.DCOrgX
+ right
,
422 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
423 dc
->w
.DCOrgX
+ right
,
424 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
425 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
427 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
429 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
436 /***********************************************************************
439 int FillRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
443 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
444 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
445 PatBlt( hdc
, rect
->left
, rect
->top
,
446 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
447 SelectObject( hdc
, prevBrush
);
452 /***********************************************************************
453 * InvertRect (USER.82)
455 void InvertRect( HDC hdc
, LPRECT rect
)
457 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
458 PatBlt( hdc
, rect
->left
, rect
->top
,
459 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
463 /***********************************************************************
464 * FrameRect (USER.83)
466 int FrameRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
469 int left
, top
, right
, bottom
;
471 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
472 if (!dc
) return FALSE
;
474 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
475 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
477 left
= XLPTODP( dc
, rect
->left
);
478 top
= YLPTODP( dc
, rect
->top
);
479 right
= XLPTODP( dc
, rect
->right
);
480 bottom
= YLPTODP( dc
, rect
->bottom
);
482 if (DC_SetupGCForBrush( dc
))
484 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
485 rect
->bottom
- rect
->top
, PATCOPY
);
486 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
487 rect
->bottom
- rect
->top
, PATCOPY
);
488 PatBlt( hdc
, rect
->left
, rect
->top
,
489 rect
->right
- rect
->left
, 1, PATCOPY
);
490 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
491 rect
->right
- rect
->left
, 1, PATCOPY
);
493 SelectObject( hdc
, prevBrush
);
498 /***********************************************************************
501 COLORREF
SetPixel( HDC hdc
, short x
, short y
, COLORREF color
)
506 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
509 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
511 MF_MetaParam4(dc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
));
515 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
516 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
517 pixel
= COLOR_ToPhysical( dc
, color
);
519 XSetForeground( display
, dc
->u
.x
.gc
, pixel
);
520 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
521 XDrawPoint( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
, x
, y
);
523 if (screenDepth
<= 8)
525 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
526 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
528 else return (COLORREF
)pixel
;
532 /***********************************************************************
535 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
542 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
545 #ifdef SOLITAIRE_SPEED_HACK
549 if (!PtVisible( hdc
, x
, y
)) return 0;
551 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
552 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
553 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
,
554 1, 1, AllPlanes
, ZPixmap
);
555 pixel
= XGetPixel( image
, 0, 0 );
556 XDestroyImage( image
);
558 if (screenDepth
> 8) return pixel
;
559 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hRevMapping
);
560 if (mapping
) pixel
= mapping
[pixel
];
561 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
562 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
566 /***********************************************************************
569 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
572 HRGN tmpVisRgn
, prevVisRgn
;
573 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
574 if (!dc
) return FALSE
;
576 /* Modify visible region */
578 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
579 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
581 RestoreVisRgn( hdc
);
584 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
585 SelectVisRgn( hdc
, tmpVisRgn
);
586 DeleteObject( tmpVisRgn
);
588 /* Fill the region */
590 GetRgnBox( dc
->w
.hGCClipRgn
, &box
);
591 if (DC_SetupGCForBrush( dc
))
592 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
593 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
594 box
.right
-box
.left
, box
.bottom
-box
.top
);
596 /* Restore the visible region */
598 RestoreVisRgn( hdc
);
603 /***********************************************************************
606 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
609 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
610 if (!prevBrush
) return FALSE
;
611 retval
= PaintRgn( hdc
, hrgn
);
612 SelectObject( hdc
, prevBrush
);
616 /***********************************************************************
619 BOOL
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, int nWidth
, int nHeight
)
621 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
622 if(!REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
)) return 0;
623 FillRgn( hdc
, tmp
, hbrush
);
628 /***********************************************************************
631 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
633 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
634 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
635 BOOL retval
= PaintRgn( hdc
, hrgn
);
636 SelectObject( hdc
, prevBrush
);
637 SetROP2( hdc
, prevROP
);
642 /***********************************************************************
643 * DrawFocusRect (USER.466)
645 void DrawFocusRect( HDC hdc
, LPRECT rc
)
648 int oldDrawMode
, oldBkMode
;
649 int left
, top
, right
, bottom
;
650 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
653 left
= XLPTODP( dc
, rc
->left
);
654 top
= YLPTODP( dc
, rc
->top
);
655 right
= XLPTODP( dc
, rc
->right
);
656 bottom
= YLPTODP( dc
, rc
->bottom
);
658 hOldPen
= (HPEN
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
659 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
660 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
662 if (DC_SetupGCForPen( dc
))
663 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
664 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
665 right
-left
-1, bottom
-top
-1 );
667 SetBkMode(hdc
, oldBkMode
);
668 SetROP2(hdc
, oldDrawMode
);
669 SelectObject(hdc
, (HANDLE
)hOldPen
);
673 /**********************************************************************
676 * Short-cut function to blit a bitmap into a device.
677 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
679 BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
680 int xsrc
, int ysrc
, int width
, int height
)
685 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
686 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
688 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
689 if (bmp
->bitmap
.bmBitsPixel
== 1)
691 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
692 XSetBackground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
693 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
694 xsrc
, ysrc
, width
, height
,
695 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
698 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
700 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
701 xsrc
, ysrc
, width
, height
,
702 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
709 /**********************************************************************
710 * GRAPH_DrawReliefRect (Not a MSWin Call)
712 void GRAPH_DrawReliefRect( HDC hdc
, RECT
*rect
, int highlight_size
,
713 int shadow_size
, BOOL pressed
)
718 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
719 sysColorObjects
.hbrushBtnHighlight
);
720 for (i
= 0; i
< highlight_size
; i
++)
722 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
723 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
724 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
725 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
728 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
729 sysColorObjects
.hbrushBtnShadow
);
730 for (i
= 0; i
< shadow_size
; i
++)
732 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
733 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
734 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
735 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
738 SelectObject( hdc
, hbrushOld
);
742 /**********************************************************************
745 BOOL
Polyline (HDC hdc
, LPPOINT pt
, int count
)
748 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
751 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
752 if (!dc
) return FALSE
;
753 MF_MetaPoly(dc
, META_POLYLINE
, pt
, count
);
757 if (DC_SetupGCForPen( dc
))
758 for (i
= 0; i
< count
-1; i
++)
759 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
760 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
761 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
762 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
763 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
768 /**********************************************************************
771 BOOL
Polygon (HDC hdc
, LPPOINT pt
, int count
)
774 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
775 XPoint
*points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
+1));
779 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
780 if (!dc
) return FALSE
;
781 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
785 for (i
= 0; i
< count
; i
++)
787 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
788 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
790 points
[count
] = points
[0];
792 if (DC_SetupGCForBrush( dc
))
793 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
794 points
, count
+1, Complex
, CoordModeOrigin
);
796 if (DC_SetupGCForPen ( dc
))
797 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
798 points
, count
+1, CoordModeOrigin
);
805 /**********************************************************************
806 * PolyPolygon (GDI.450)
808 BOOL
PolyPolygon( HDC hdc
, LPPOINT pt
, LPINT counts
, WORD polygons
)
811 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
815 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
816 if (!dc
) return FALSE
;
817 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
820 /* FIXME: The points should be converted to device coords before */
821 /* creating the region. But as CreatePolyPolygonRgn is not */
822 /* really correct either, it doesn't matter much... */
823 /* At least the outline will be correct :-) */
824 hrgn
= CreatePolyPolygonRgn( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
825 PaintRgn( hdc
, hrgn
);
826 DeleteObject( hrgn
);
828 /* Draw the outline of the polygons */
830 if (DC_SetupGCForPen ( dc
))
835 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
836 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
838 for (i
= 0; i
< polygons
; i
++)
840 for (j
= 0; j
< counts
[i
]; j
++)
842 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
843 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
846 points
[j
] = points
[0];
847 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
848 points
, j
+ 1, CoordModeOrigin
);
856 /**********************************************************************
857 * GRAPH_InternalFloodFill
859 * Internal helper function for flood fill.
860 * (xorg,yorg) is the origin of the X image relative to the drawable.
861 * (x,y) is relative to the origin of the X image.
863 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
866 Pixel pixel
, WORD fillType
)
870 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
871 (XGetPixel(image,x,y) != pixel) : \
872 (XGetPixel(image,x,y) == pixel))
874 if (!TO_FLOOD(x
,y
)) return;
876 /* Find left and right boundaries */
879 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
880 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
881 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
882 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
884 /* Set the pixels of this line so we don't fill it again */
886 for (x
= left
; x
< right
; x
++)
888 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
889 else XPutPixel( image
, x
, y
, ~pixel
);
892 /* Fill the line above */
899 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
900 if (x
>= right
) break;
901 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
902 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
903 xOrg
, yOrg
, pixel
, fillType
);
907 /* Fill the line below */
909 if ((y
+= 2) < image
->height
)
914 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
915 if (x
>= right
) break;
916 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
917 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
918 xOrg
, yOrg
, pixel
, fillType
);
925 /**********************************************************************
928 * Main flood-fill routine.
930 static BOOL
GRAPH_DoFloodFill( DC
*dc
, RECT
*rect
, INT x
, INT y
,
931 COLORREF color
, WORD fillType
)
935 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
936 dc
->w
.DCOrgX
+ rect
->left
,
937 dc
->w
.DCOrgY
+ rect
->top
,
938 rect
->right
- rect
->left
,
939 rect
->bottom
- rect
->top
,
940 AllPlanes
, ZPixmap
))) return FALSE
;
942 if (DC_SetupGCForBrush( dc
))
944 /* ROP mode is always GXcopy for flood-fill */
945 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
946 GRAPH_InternalFloodFill( image
, dc
,
947 XLPTODP(dc
,x
) - rect
->left
,
948 YLPTODP(dc
,y
) - rect
->top
,
949 dc
->w
.DCOrgX
+ rect
->left
,
950 dc
->w
.DCOrgY
+ rect
->top
,
951 COLOR_ToPhysical( dc
, color
), fillType
);
954 XDestroyImage( image
);
959 /**********************************************************************
960 * ExtFloodFill (GDI.372)
962 BOOL
ExtFloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
, WORD fillType
)
967 dprintf_graphics( stddeb
, "ExtFloodFill "NPFMT
" %d,%d %06lx %d\n",
968 hdc
, x
, y
, color
, fillType
);
969 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
972 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
973 if (!dc
) return FALSE
;
974 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
979 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
980 if (GetRgnBox( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
982 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill
, 6,
983 dc
, &rect
, x
, y
, color
, fillType
);
987 /**********************************************************************
990 BOOL
FloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
)
992 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);