2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
27 /***********************************************************************
30 BOOL
LineTo( HDC hdc
, short x
, short y
)
32 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
35 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
36 if (!dc
) return FALSE
;
37 MF_MetaParam2(dc
, META_LINETO
, x
, y
);
41 if (DC_SetupGCForPen( dc
))
42 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
43 dc
->w
.DCOrgX
+ XLPTODP( dc
, dc
->w
.CursPosX
),
44 dc
->w
.DCOrgY
+ YLPTODP( dc
, dc
->w
.CursPosY
),
45 dc
->w
.DCOrgX
+ XLPTODP( dc
, x
),
46 dc
->w
.DCOrgY
+ YLPTODP( dc
, y
) );
53 /***********************************************************************
56 DWORD
MoveTo( HDC hdc
, short x
, short y
)
59 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
62 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
63 if (!dc
) return FALSE
;
64 MF_MetaParam2(dc
, META_MOVETO
, x
, y
);
68 oldx
= dc
->w
.CursPosX
;
69 oldy
= dc
->w
.CursPosY
;
72 return oldx
| (oldy
<< 16);
76 /***********************************************************************
77 * MoveToEx16 (GDI.483)
79 BOOL16
MoveToEx16( HDC16 hdc
, INT16 x
, INT16 y
, LPPOINT16 pt
)
81 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
82 if (!dc
) return FALSE
;
85 pt
->x
= dc
->w
.CursPosX
;
86 pt
->y
= dc
->w
.CursPosY
;
94 /***********************************************************************
95 * MoveToEx32 (GDI32.254)
97 BOOL32
MoveToEx32( HDC32 hdc
, INT32 x
, INT32 y
, LPPOINT32 pt
)
100 if (!MoveToEx16( (HDC16
)hdc
, (INT16
)x
, (INT16
)y
, &pt16
)) return FALSE
;
101 if (pt
) CONV_POINT16TO32( &pt16
, pt
);
106 /***********************************************************************
109 * Helper functions for Arc(), Chord() and Pie().
110 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
112 static BOOL
GRAPH_DrawArc( HDC hdc
, int left
, int top
, int right
, int bottom
,
113 int xstart
, int ystart
, int xend
, int yend
, int lines
)
115 int xcenter
, ycenter
, istart_angle
, idiff_angle
, tmp
;
116 double start_angle
, end_angle
;
118 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
121 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
122 if (!dc
) return FALSE
;
126 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
127 xstart
, ystart
, xend
, yend
);
131 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
132 xstart
, ystart
, xend
, yend
);
136 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
137 xstart
, ystart
, xend
, yend
);
143 left
= XLPTODP( dc
, left
);
144 top
= YLPTODP( dc
, top
);
145 right
= XLPTODP( dc
, right
);
146 bottom
= YLPTODP( dc
, bottom
);
147 xstart
= XLPTODP( dc
, xstart
);
148 ystart
= YLPTODP( dc
, ystart
);
149 xend
= XLPTODP( dc
, xend
);
150 yend
= YLPTODP( dc
, yend
);
151 if ((left
== right
) || (top
== bottom
)) return FALSE
;
153 xcenter
= (right
+ left
) / 2;
154 ycenter
= (bottom
+ top
) / 2;
155 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
156 (double)(xstart
-xcenter
)*(bottom
-top
) );
157 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
158 (double)(xend
-xcenter
)*(bottom
-top
) );
159 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
160 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
161 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
162 if (left
> right
) { tmp
=left
; left
=right
; right
=tmp
; }
163 if (top
> bottom
) { tmp
=top
; top
=bottom
; bottom
=tmp
; }
165 /* Fill arc with brush if Chord() or Pie() */
167 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
169 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
170 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
171 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
172 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
175 /* Draw arc and lines */
177 if (!DC_SetupGCForPen( dc
)) return TRUE
;
178 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
179 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
180 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
181 if (!lines
) return TRUE
;
183 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
184 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
185 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
186 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
189 points
[2] = points
[1];
190 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
191 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
193 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
194 points
, lines
+1, CoordModeOrigin
);
199 /***********************************************************************
202 BOOL
Arc( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
203 INT xstart
, INT ystart
, INT xend
, INT yend
)
205 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
206 xstart
, ystart
, xend
, yend
, 0 );
210 /***********************************************************************
213 BOOL
Pie( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
214 INT xstart
, INT ystart
, INT xend
, INT yend
)
216 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
217 xstart
, ystart
, xend
, yend
, 2 );
221 /***********************************************************************
224 BOOL
Chord( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
225 INT xstart
, INT ystart
, INT xend
, INT yend
)
227 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
228 xstart
, ystart
, xend
, yend
, 1 );
232 /***********************************************************************
235 BOOL
Ellipse( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
237 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
240 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
241 if (!dc
) return FALSE
;
242 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
246 left
= XLPTODP( dc
, left
);
247 top
= YLPTODP( dc
, top
);
248 right
= XLPTODP( dc
, right
);
249 bottom
= YLPTODP( dc
, bottom
);
250 if ((left
== right
) || (top
== bottom
)) return FALSE
;
252 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
253 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
255 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
256 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
257 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
259 left
+= dc
->u
.x
.pen
.width
/ 2;
260 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
261 top
+= dc
->u
.x
.pen
.width
/ 2;
262 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
265 if (DC_SetupGCForBrush( dc
))
266 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
267 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
268 right
-left
-1, bottom
-top
-1, 0, 360*64 );
269 if (DC_SetupGCForPen( dc
))
270 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
271 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
272 right
-left
-1, bottom
-top
-1, 0, 360*64 );
277 /***********************************************************************
280 BOOL
Rectangle( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
282 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
285 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
286 if (!dc
) return FALSE
;
287 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
290 left
= XLPTODP( dc
, left
);
291 top
= YLPTODP( dc
, top
);
292 right
= XLPTODP( dc
, right
);
293 bottom
= YLPTODP( dc
, bottom
);
295 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
296 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
298 if ((left
== right
) || (top
== bottom
))
300 if (DC_SetupGCForPen( dc
))
301 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
304 dc
->w
.DCOrgX
+ right
,
305 dc
->w
.DCOrgY
+ bottom
);
309 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
310 (dc
->u
.x
.pen
.width
< right
-left
) &&
311 (dc
->u
.x
.pen
.width
< bottom
-top
))
313 left
+= dc
->u
.x
.pen
.width
/ 2;
314 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
315 top
+= dc
->u
.x
.pen
.width
/ 2;
316 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
319 if (DC_SetupGCForBrush( dc
))
320 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
321 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
322 right
-left
, bottom
-top
);
323 if (DC_SetupGCForPen( dc
))
324 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
325 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
326 right
-left
-1, bottom
-top
-1 );
331 /***********************************************************************
334 BOOL
RoundRect( HDC hDC
, INT left
, INT top
, INT right
, INT bottom
,
335 INT ell_width
, INT ell_height
)
337 DC
* dc
= (DC
*) GDI_GetObjPtr(hDC
, DC_MAGIC
);
340 dc
= (DC
*)GDI_GetObjPtr(hDC
, METAFILE_DC_MAGIC
);
341 if (!dc
) return FALSE
;
342 MF_MetaParam6(dc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
343 ell_width
, ell_height
);
346 dprintf_graphics(stddeb
, "RoundRect(%d %d %d %d %d %d\n",
347 left
, top
, right
, bottom
, ell_width
, ell_height
);
349 left
= XLPTODP( dc
, left
);
350 top
= YLPTODP( dc
, top
);
351 right
= XLPTODP( dc
, right
);
352 bottom
= YLPTODP( dc
, bottom
);
353 ell_width
= abs( ell_width
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
);
354 ell_height
= abs( ell_height
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
356 /* Fix the coordinates */
358 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
359 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
360 if (ell_width
> right
- left
) ell_width
= right
- left
;
361 if (ell_height
> bottom
- top
) ell_height
= bottom
- top
;
363 if (DC_SetupGCForBrush( dc
))
365 if (ell_width
&& ell_height
)
367 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
368 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
369 ell_width
, ell_height
, 90 * 64, 90 * 64 );
370 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
371 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
372 ell_width
, ell_height
, 180 * 64, 90 * 64 );
373 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
374 dc
->w
.DCOrgX
+ right
- ell_width
,
375 dc
->w
.DCOrgY
+ bottom
- ell_height
,
376 ell_width
, ell_height
, 270 * 64, 90 * 64 );
377 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
378 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
379 ell_width
, ell_height
, 0, 90 * 64 );
381 if (ell_width
< right
- left
)
383 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
384 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
386 right
- left
- ell_width
, ell_height
/ 2 );
387 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
388 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
389 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2,
390 right
- left
- ell_width
, (ell_height
+1) / 2 );
392 if (ell_height
< bottom
- top
)
394 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
396 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
397 right
- left
, bottom
- top
- ell_height
);
400 if (DC_SetupGCForPen(dc
))
402 if (ell_width
&& ell_height
)
404 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
405 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
406 ell_width
, ell_height
, 90 * 64, 90 * 64 );
407 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
408 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
409 ell_width
, ell_height
, 180 * 64, 90 * 64 );
410 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
411 dc
->w
.DCOrgX
+ right
- ell_width
,
412 dc
->w
.DCOrgY
+ bottom
- ell_height
,
413 ell_width
, ell_height
, 270 * 64, 90 * 64 );
414 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
415 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
416 ell_width
, ell_height
, 0, 90 * 64 );
418 if (ell_width
< right
- left
)
420 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
421 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
423 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
424 dc
->w
.DCOrgY
+ top
);
425 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
426 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
427 dc
->w
.DCOrgY
+ bottom
,
428 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
429 dc
->w
.DCOrgY
+ bottom
);
431 if (ell_height
< bottom
- top
)
433 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
434 dc
->w
.DCOrgX
+ right
,
435 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
436 dc
->w
.DCOrgX
+ right
,
437 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
438 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
440 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
442 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
449 /***********************************************************************
450 * FillRect16 (USER.81)
452 INT16
FillRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
456 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
457 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
458 PatBlt( hdc
, rect
->left
, rect
->top
,
459 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
460 SelectObject( hdc
, prevBrush
);
465 /***********************************************************************
466 * FillRect32 (USER32.196)
468 INT32
FillRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
472 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
473 if (!(prevBrush
= SelectObject( hdc
, (HBRUSH16
)hbrush
))) return 0;
474 PatBlt( hdc
, rect
->left
, rect
->top
,
475 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
476 SelectObject( hdc
, prevBrush
);
481 /***********************************************************************
482 * InvertRect16 (USER.82)
484 void InvertRect16( HDC16 hdc
, const RECT16
*rect
)
486 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
487 PatBlt( hdc
, rect
->left
, rect
->top
,
488 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
492 /***********************************************************************
493 * InvertRect32 (USER32.329)
495 void InvertRect32( HDC32 hdc
, const RECT32
*rect
)
497 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
498 PatBlt( hdc
, rect
->left
, rect
->top
,
499 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
503 /***********************************************************************
504 * FrameRect16 (USER.83)
506 INT16
FrameRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
509 int left
, top
, right
, bottom
;
511 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
512 if (!dc
) return FALSE
;
514 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
515 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
517 left
= XLPTODP( dc
, rect
->left
);
518 top
= YLPTODP( dc
, rect
->top
);
519 right
= XLPTODP( dc
, rect
->right
);
520 bottom
= YLPTODP( dc
, rect
->bottom
);
522 if (DC_SetupGCForBrush( dc
))
524 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
525 rect
->bottom
- rect
->top
, PATCOPY
);
526 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
527 rect
->bottom
- rect
->top
, PATCOPY
);
528 PatBlt( hdc
, rect
->left
, rect
->top
,
529 rect
->right
- rect
->left
, 1, PATCOPY
);
530 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
531 rect
->right
- rect
->left
, 1, PATCOPY
);
533 SelectObject( hdc
, prevBrush
);
538 /***********************************************************************
539 * FrameRect32 (USER32.202)
541 INT32
FrameRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
544 CONV_RECT32TO16( rect
, &rect16
);
545 return FrameRect16( (HDC16
)hdc
, &rect16
, (HBRUSH16
)hbrush
);
549 /***********************************************************************
552 COLORREF
SetPixel( HDC hdc
, short x
, short y
, COLORREF color
)
556 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
559 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
561 MF_MetaParam4(dc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
));
565 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
566 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
567 pixel
= COLOR_ToPhysical( dc
, color
);
569 XSetForeground( display
, dc
->u
.x
.gc
, pixel
);
570 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
571 XDrawPoint( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
, x
, y
);
573 /* inefficient but simple... */
575 return COLOR_ToLogical(pixel
);
579 /***********************************************************************
582 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
587 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
590 #ifdef SOLITAIRE_SPEED_HACK
594 if (!PtVisible( hdc
, x
, y
)) return 0;
596 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
597 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
598 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
,
599 1, 1, AllPlanes
, ZPixmap
);
600 pixel
= XGetPixel( image
, 0, 0 );
601 XDestroyImage( image
);
603 return COLOR_ToLogical(pixel
);
607 /***********************************************************************
610 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
613 HRGN tmpVisRgn
, prevVisRgn
;
614 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
615 if (!dc
) return FALSE
;
617 /* Modify visible region */
619 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
620 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
622 RestoreVisRgn( hdc
);
625 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
626 SelectVisRgn( hdc
, tmpVisRgn
);
627 DeleteObject( tmpVisRgn
);
629 /* Fill the region */
631 GetRgnBox16( dc
->w
.hGCClipRgn
, &box
);
632 if (DC_SetupGCForBrush( dc
))
633 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
634 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
635 box
.right
-box
.left
, box
.bottom
-box
.top
);
637 /* Restore the visible region */
639 RestoreVisRgn( hdc
);
644 /***********************************************************************
647 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
650 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
651 if (!prevBrush
) return FALSE
;
652 retval
= PaintRgn( hdc
, hrgn
);
653 SelectObject( hdc
, prevBrush
);
657 /***********************************************************************
660 BOOL
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, int nWidth
, int nHeight
)
662 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
663 if(!REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
)) return 0;
664 FillRgn( hdc
, tmp
, hbrush
);
669 /***********************************************************************
672 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
674 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
675 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
676 BOOL retval
= PaintRgn( hdc
, hrgn
);
677 SelectObject( hdc
, prevBrush
);
678 SetROP2( hdc
, prevROP
);
683 /***********************************************************************
684 * DrawFocusRect16 (USER.466)
686 void DrawFocusRect16( HDC16 hdc
, const RECT16
* rc
)
689 int oldDrawMode
, oldBkMode
;
690 int left
, top
, right
, bottom
;
691 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
694 left
= XLPTODP( dc
, rc
->left
);
695 top
= YLPTODP( dc
, rc
->top
);
696 right
= XLPTODP( dc
, rc
->right
);
697 bottom
= YLPTODP( dc
, rc
->bottom
);
699 hOldPen
= (HPEN16
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
700 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
701 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
703 /* Hack: make sure the XORPEN operation has an effect */
704 dc
->u
.x
.pen
.pixel
= (1 << screenDepth
) - 1;
706 if (DC_SetupGCForPen( dc
))
707 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
708 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
709 right
-left
-1, bottom
-top
-1 );
711 SetBkMode(hdc
, oldBkMode
);
712 SetROP2(hdc
, oldDrawMode
);
713 SelectObject(hdc
, (HANDLE
)hOldPen
);
717 /***********************************************************************
718 * DrawFocusRect32 (USER32.155)
720 void DrawFocusRect32( HDC32 hdc
, const RECT32
* rect
)
723 CONV_RECT32TO16( rect
, &rect16
);
724 return DrawFocusRect16( (HDC16
)hdc
, &rect16
);
728 /**********************************************************************
731 * Short-cut function to blit a bitmap into a device.
732 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
734 BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
735 int xsrc
, int ysrc
, int width
, int height
)
740 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
741 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
743 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
744 if (bmp
->bitmap
.bmBitsPixel
== 1)
746 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
747 XSetBackground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
748 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
749 xsrc
, ysrc
, width
, height
,
750 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
753 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
755 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
756 xsrc
, ysrc
, width
, height
,
757 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
764 /**********************************************************************
765 * GRAPH_DrawReliefRect (Not a MSWin Call)
767 void GRAPH_DrawReliefRect( HDC hdc
, RECT16
*rect
, int highlight_size
,
768 int shadow_size
, BOOL pressed
)
773 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
774 sysColorObjects
.hbrushBtnHighlight
);
775 for (i
= 0; i
< highlight_size
; i
++)
777 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
778 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
779 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
780 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
783 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
784 sysColorObjects
.hbrushBtnShadow
);
785 for (i
= 0; i
< shadow_size
; i
++)
787 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
788 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
789 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
790 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
793 SelectObject( hdc
, hbrushOld
);
797 /**********************************************************************
798 * Polyline16 (GDI.37)
800 BOOL16
Polyline16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
803 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
806 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
807 if (!dc
) return FALSE
;
808 MF_MetaPoly(dc
, META_POLYLINE
, pt
, count
);
812 if (DC_SetupGCForPen( dc
))
813 for (i
= 0; i
< count
-1; i
++)
814 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
815 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
816 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
817 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
818 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
823 /**********************************************************************
826 BOOL16
Polygon16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
829 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
830 XPoint
*points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
+1));
834 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
835 if (!dc
) return FALSE
;
836 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
840 for (i
= 0; i
< count
; i
++)
842 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
843 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
845 points
[count
] = points
[0];
847 if (DC_SetupGCForBrush( dc
))
848 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
849 points
, count
+1, Complex
, CoordModeOrigin
);
851 if (DC_SetupGCForPen ( dc
))
852 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
853 points
, count
+1, CoordModeOrigin
);
860 /**********************************************************************
861 * PolyPolygon16 (GDI.450)
863 BOOL16
PolyPolygon16( HDC16 hdc
, LPPOINT16 pt
, LPINT16 counts
, UINT16 polygons
)
866 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
870 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
871 if (!dc
) return FALSE
;
872 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
875 /* FIXME: The points should be converted to device coords before */
876 /* creating the region. But as CreatePolyPolygonRgn is not */
877 /* really correct either, it doesn't matter much... */
878 /* At least the outline will be correct :-) */
879 hrgn
= CreatePolyPolygonRgn16( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
880 PaintRgn( hdc
, hrgn
);
881 DeleteObject( hrgn
);
883 /* Draw the outline of the polygons */
885 if (DC_SetupGCForPen ( dc
))
890 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
891 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
893 for (i
= 0; i
< polygons
; i
++)
895 for (j
= 0; j
< counts
[i
]; j
++)
897 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
898 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
901 points
[j
] = points
[0];
902 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
903 points
, j
+ 1, CoordModeOrigin
);
911 /**********************************************************************
912 * GRAPH_InternalFloodFill
914 * Internal helper function for flood fill.
915 * (xorg,yorg) is the origin of the X image relative to the drawable.
916 * (x,y) is relative to the origin of the X image.
918 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
921 Pixel pixel
, WORD fillType
)
925 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
926 (XGetPixel(image,x,y) != pixel) : \
927 (XGetPixel(image,x,y) == pixel))
929 if (!TO_FLOOD(x
,y
)) return;
931 /* Find left and right boundaries */
934 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
935 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
936 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
937 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
939 /* Set the pixels of this line so we don't fill it again */
941 for (x
= left
; x
< right
; x
++)
943 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
944 else XPutPixel( image
, x
, y
, ~pixel
);
947 /* Fill the line above */
954 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
955 if (x
>= right
) break;
956 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
957 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
958 xOrg
, yOrg
, pixel
, fillType
);
962 /* Fill the line below */
964 if ((y
+= 2) < image
->height
)
969 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
970 if (x
>= right
) break;
971 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
972 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
973 xOrg
, yOrg
, pixel
, fillType
);
980 /**********************************************************************
983 * Main flood-fill routine.
985 static BOOL16
GRAPH_DoFloodFill( DC
*dc
, RECT16
*rect
, INT32 x
, INT32 y
,
986 COLORREF color
, UINT32 fillType
)
990 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
991 dc
->w
.DCOrgX
+ rect
->left
,
992 dc
->w
.DCOrgY
+ rect
->top
,
993 rect
->right
- rect
->left
,
994 rect
->bottom
- rect
->top
,
995 AllPlanes
, ZPixmap
))) return FALSE
;
997 if (DC_SetupGCForBrush( dc
))
999 /* ROP mode is always GXcopy for flood-fill */
1000 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
1001 GRAPH_InternalFloodFill( image
, dc
,
1002 XLPTODP(dc
,x
) - rect
->left
,
1003 YLPTODP(dc
,y
) - rect
->top
,
1004 dc
->w
.DCOrgX
+ rect
->left
,
1005 dc
->w
.DCOrgY
+ rect
->top
,
1006 COLOR_ToPhysical( dc
, color
), fillType
);
1009 XDestroyImage( image
);
1014 /**********************************************************************
1015 * ExtFloodFill (GDI.372) (GDI32.96)
1017 BOOL16
ExtFloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
,
1023 dprintf_graphics( stddeb
, "ExtFloodFill %04x %d,%d %06lx %d\n",
1024 hdc
, x
, y
, color
, fillType
);
1025 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
1028 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
1029 if (!dc
) return FALSE
;
1030 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
1035 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
1036 if (GetRgnBox16( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
1038 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill
, 6,
1039 dc
, &rect
, x
, y
, color
, fillType
);
1043 /**********************************************************************
1044 * FloodFill (GDI.25) (GDI32.104)
1046 BOOL16
FloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
)
1048 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
1052 /**********************************************************************
1053 * DrawEdge16 (USER.659)
1055 BOOL16
DrawEdge16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1060 CONV_RECT16TO32( rc
, &rect32
);
1061 ret
= DrawEdge32( hdc
, &rect32
, edge
, flags
);
1062 CONV_RECT32TO16( &rect32
, rc
);
1067 /**********************************************************************
1068 * DrawEdge32 (USER32.154)
1070 BOOL32
DrawEdge32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1074 if (flags
>= BF_DIAGONAL
)
1075 fprintf( stderr
, "DrawEdge: unsupported flags %04x\n", flags
);
1077 dprintf_graphics( stddeb
, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
1078 hdc
, rc
->left
, rc
->top
, rc
->right
, rc
->bottom
,
1081 /* First do all the raised edges */
1083 SelectObject( hdc
, sysColorObjects
.hbrushBtnHighlight
);
1084 if (edge
& BDR_RAISEDOUTER
)
1086 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1087 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1088 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1089 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1091 if (edge
& BDR_SUNKENOUTER
)
1093 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1094 1, rc
->bottom
- rc
->top
, PATCOPY
);
1095 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1096 rc
->right
- rc
->left
, 1, PATCOPY
);
1098 if (edge
& BDR_RAISEDINNER
)
1100 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1101 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1102 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1103 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1105 if (edge
& BDR_SUNKENINNER
)
1107 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1108 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1109 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1110 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1113 /* Then do all the sunken edges */
1115 hbrushOld
= SelectObject( hdc
, sysColorObjects
.hbrushBtnShadow
);
1116 if (edge
& BDR_SUNKENOUTER
)
1118 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1119 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1120 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1121 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1123 if (edge
& BDR_RAISEDOUTER
)
1125 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1126 1, rc
->bottom
- rc
->top
, PATCOPY
);
1127 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1128 rc
->right
- rc
->left
, 1, PATCOPY
);
1130 if (edge
& BDR_SUNKENINNER
)
1132 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1133 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1134 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1135 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1137 if (edge
& BDR_RAISEDINNER
)
1139 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1140 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1141 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1142 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1145 SelectObject( hdc
, hbrushOld
);
1150 /**********************************************************************
1151 * DrawFrameControl16 (USER.656)
1153 BOOL16
DrawFrameControl16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1155 fprintf( stdnimp
,"DrawFrameControl16(%x,%p,%d,%x), empty stub!\n",
1156 hdc
,rc
,edge
,flags
);
1161 /**********************************************************************
1162 * DrawFrameControl32 (USER32.157)
1164 BOOL32
DrawFrameControl32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1166 fprintf( stdnimp
,"DrawFrameControl32(%x,%p,%d,%x), empty stub!\n",
1167 hdc
,rc
,edge
,flags
);