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 /***********************************************************************
76 * MoveToEx16 (GDI.483)
78 BOOL16
MoveToEx16( HDC16 hdc
, INT16 x
, INT16 y
, LPPOINT16 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 /***********************************************************************
94 * MoveToEx32 (GDI32.254)
96 BOOL32
MoveToEx32( HDC32 hdc
, INT32 x
, INT32 y
, LPPOINT32 pt
)
99 if (!MoveToEx16( (HDC16
)hdc
, (INT16
)x
, (INT16
)y
, &pt16
)) return FALSE
;
100 if (pt
) CONV_POINT16TO32( &pt16
, pt
);
105 /***********************************************************************
108 * Helper functions for Arc(), Chord() and Pie().
109 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
111 static BOOL
GRAPH_DrawArc( HDC hdc
, int left
, int top
, int right
, int bottom
,
112 int xstart
, int ystart
, int xend
, int yend
, int lines
)
114 int xcenter
, ycenter
, istart_angle
, idiff_angle
, tmp
;
115 double start_angle
, end_angle
;
117 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
120 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
121 if (!dc
) return FALSE
;
125 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
126 xstart
, ystart
, xend
, yend
);
130 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
131 xstart
, ystart
, xend
, yend
);
135 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
136 xstart
, ystart
, xend
, yend
);
142 left
= XLPTODP( dc
, left
);
143 top
= YLPTODP( dc
, top
);
144 right
= XLPTODP( dc
, right
);
145 bottom
= YLPTODP( dc
, bottom
);
146 xstart
= XLPTODP( dc
, xstart
);
147 ystart
= YLPTODP( dc
, ystart
);
148 xend
= XLPTODP( dc
, xend
);
149 yend
= YLPTODP( dc
, yend
);
150 if ((left
== right
) || (top
== bottom
)) return FALSE
;
152 xcenter
= (right
+ left
) / 2;
153 ycenter
= (bottom
+ top
) / 2;
154 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
155 (double)(xstart
-xcenter
)*(bottom
-top
) );
156 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
157 (double)(xend
-xcenter
)*(bottom
-top
) );
158 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
159 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
160 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
161 if (left
> right
) { tmp
=left
; left
=right
; right
=tmp
; }
162 if (top
> bottom
) { tmp
=top
; top
=bottom
; bottom
=tmp
; }
164 /* Fill arc with brush if Chord() or Pie() */
166 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
168 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
169 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
170 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
171 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
174 /* Draw arc and lines */
176 if (!DC_SetupGCForPen( dc
)) return TRUE
;
177 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
178 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
179 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
180 if (!lines
) return TRUE
;
182 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
183 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
184 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
185 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
188 points
[2] = points
[1];
189 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
190 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
192 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
193 points
, lines
+1, CoordModeOrigin
);
198 /***********************************************************************
201 BOOL
Arc( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
202 INT xstart
, INT ystart
, INT xend
, INT yend
)
204 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
205 xstart
, ystart
, xend
, yend
, 0 );
209 /***********************************************************************
212 BOOL
Pie( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
213 INT xstart
, INT ystart
, INT xend
, INT yend
)
215 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
216 xstart
, ystart
, xend
, yend
, 2 );
220 /***********************************************************************
223 BOOL
Chord( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
224 INT xstart
, INT ystart
, INT xend
, INT yend
)
226 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
227 xstart
, ystart
, xend
, yend
, 1 );
231 /***********************************************************************
234 BOOL
Ellipse( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
236 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
239 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
240 if (!dc
) return FALSE
;
241 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
245 left
= XLPTODP( dc
, left
);
246 top
= YLPTODP( dc
, top
);
247 right
= XLPTODP( dc
, right
);
248 bottom
= YLPTODP( dc
, bottom
);
249 if ((left
== right
) || (top
== bottom
)) return FALSE
;
251 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
252 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
254 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
255 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
256 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
258 left
+= dc
->u
.x
.pen
.width
/ 2;
259 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
260 top
+= dc
->u
.x
.pen
.width
/ 2;
261 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
264 if (DC_SetupGCForBrush( dc
))
265 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
266 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
267 right
-left
-1, bottom
-top
-1, 0, 360*64 );
268 if (DC_SetupGCForPen( dc
))
269 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
270 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
271 right
-left
-1, bottom
-top
-1, 0, 360*64 );
276 /***********************************************************************
279 BOOL
Rectangle( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
281 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
284 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
285 if (!dc
) return FALSE
;
286 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
289 left
= XLPTODP( dc
, left
);
290 top
= YLPTODP( dc
, top
);
291 right
= XLPTODP( dc
, right
);
292 bottom
= YLPTODP( dc
, bottom
);
294 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
295 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
297 if ((left
== right
) || (top
== bottom
))
299 if (DC_SetupGCForPen( dc
))
300 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
303 dc
->w
.DCOrgX
+ right
,
304 dc
->w
.DCOrgY
+ bottom
);
308 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
309 (dc
->u
.x
.pen
.width
< right
-left
) &&
310 (dc
->u
.x
.pen
.width
< bottom
-top
))
312 left
+= dc
->u
.x
.pen
.width
/ 2;
313 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
314 top
+= dc
->u
.x
.pen
.width
/ 2;
315 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
318 if (DC_SetupGCForBrush( dc
))
319 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
320 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
321 right
-left
, bottom
-top
);
322 if (DC_SetupGCForPen( dc
))
323 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
324 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
325 right
-left
-1, bottom
-top
-1 );
330 /***********************************************************************
333 BOOL
RoundRect( HDC hDC
, INT left
, INT top
, INT right
, INT bottom
,
334 INT ell_width
, INT ell_height
)
336 DC
* dc
= (DC
*) GDI_GetObjPtr(hDC
, DC_MAGIC
);
339 dc
= (DC
*)GDI_GetObjPtr(hDC
, METAFILE_DC_MAGIC
);
340 if (!dc
) return FALSE
;
341 MF_MetaParam6(dc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
342 ell_width
, ell_height
);
345 dprintf_graphics(stddeb
, "RoundRect(%d %d %d %d %d %d\n",
346 left
, top
, right
, bottom
, ell_width
, ell_height
);
348 left
= XLPTODP( dc
, left
);
349 top
= YLPTODP( dc
, top
);
350 right
= XLPTODP( dc
, right
);
351 bottom
= YLPTODP( dc
, bottom
);
352 ell_width
= abs( ell_width
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
);
353 ell_height
= abs( ell_height
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
355 /* Fix the coordinates */
357 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
358 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
359 if (ell_width
> right
- left
) ell_width
= right
- left
;
360 if (ell_height
> bottom
- top
) ell_height
= bottom
- top
;
362 if (DC_SetupGCForBrush( dc
))
364 if (ell_width
&& ell_height
)
366 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
367 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
368 ell_width
, ell_height
, 90 * 64, 90 * 64 );
369 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
370 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
371 ell_width
, ell_height
, 180 * 64, 90 * 64 );
372 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
373 dc
->w
.DCOrgX
+ right
- ell_width
,
374 dc
->w
.DCOrgY
+ bottom
- ell_height
,
375 ell_width
, ell_height
, 270 * 64, 90 * 64 );
376 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
377 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
378 ell_width
, ell_height
, 0, 90 * 64 );
380 if (ell_width
< right
- left
)
382 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
383 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
385 right
- left
- ell_width
, ell_height
/ 2 );
386 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
387 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
388 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2,
389 right
- left
- ell_width
, (ell_height
+1) / 2 );
391 if (ell_height
< bottom
- top
)
393 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
395 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
396 right
- left
, bottom
- top
- ell_height
);
399 if (DC_SetupGCForPen(dc
))
401 if (ell_width
&& ell_height
)
403 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
404 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
405 ell_width
, ell_height
, 90 * 64, 90 * 64 );
406 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
407 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
408 ell_width
, ell_height
, 180 * 64, 90 * 64 );
409 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
410 dc
->w
.DCOrgX
+ right
- ell_width
,
411 dc
->w
.DCOrgY
+ bottom
- ell_height
,
412 ell_width
, ell_height
, 270 * 64, 90 * 64 );
413 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
414 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
415 ell_width
, ell_height
, 0, 90 * 64 );
417 if (ell_width
< right
- left
)
419 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
420 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
422 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
423 dc
->w
.DCOrgY
+ top
);
424 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
425 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
426 dc
->w
.DCOrgY
+ bottom
,
427 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
428 dc
->w
.DCOrgY
+ bottom
);
430 if (ell_height
< bottom
- top
)
432 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
433 dc
->w
.DCOrgX
+ right
,
434 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
435 dc
->w
.DCOrgX
+ right
,
436 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
437 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
439 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
441 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
448 /***********************************************************************
449 * FillRect16 (USER.81)
451 INT16
FillRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
455 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
456 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
457 PatBlt( hdc
, rect
->left
, rect
->top
,
458 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
459 SelectObject( hdc
, prevBrush
);
464 /***********************************************************************
465 * FillRect32 (USER32.196)
467 INT32
FillRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
471 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
472 if (!(prevBrush
= SelectObject( hdc
, (HBRUSH16
)hbrush
))) return 0;
473 PatBlt( hdc
, rect
->left
, rect
->top
,
474 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
475 SelectObject( hdc
, prevBrush
);
480 /***********************************************************************
481 * InvertRect16 (USER.82)
483 void InvertRect16( HDC16 hdc
, const RECT16
*rect
)
485 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
486 PatBlt( hdc
, rect
->left
, rect
->top
,
487 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
491 /***********************************************************************
492 * InvertRect32 (USER32.329)
494 void InvertRect32( HDC32 hdc
, const RECT32
*rect
)
496 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
497 PatBlt( hdc
, rect
->left
, rect
->top
,
498 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
502 /***********************************************************************
503 * FrameRect16 (USER.83)
505 INT16
FrameRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
508 int left
, top
, right
, bottom
;
510 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
511 if (!dc
) return FALSE
;
513 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
514 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
516 left
= XLPTODP( dc
, rect
->left
);
517 top
= YLPTODP( dc
, rect
->top
);
518 right
= XLPTODP( dc
, rect
->right
);
519 bottom
= YLPTODP( dc
, rect
->bottom
);
521 if (DC_SetupGCForBrush( dc
))
523 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
524 rect
->bottom
- rect
->top
, PATCOPY
);
525 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
526 rect
->bottom
- rect
->top
, PATCOPY
);
527 PatBlt( hdc
, rect
->left
, rect
->top
,
528 rect
->right
- rect
->left
, 1, PATCOPY
);
529 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
530 rect
->right
- rect
->left
, 1, PATCOPY
);
532 SelectObject( hdc
, prevBrush
);
537 /***********************************************************************
538 * FrameRect32 (USER32.202)
540 INT32
FrameRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
543 CONV_RECT32TO16( rect
, &rect16
);
544 return FrameRect16( (HDC16
)hdc
, &rect16
, (HBRUSH16
)hbrush
);
548 /***********************************************************************
551 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 if (screenDepth
<= 8)
575 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
576 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
578 else return (COLORREF
)pixel
;
582 /***********************************************************************
585 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
592 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
595 #ifdef SOLITAIRE_SPEED_HACK
599 if (!PtVisible( hdc
, x
, y
)) return 0;
601 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
602 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
603 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
,
604 1, 1, AllPlanes
, ZPixmap
);
605 pixel
= XGetPixel( image
, 0, 0 );
606 XDestroyImage( image
);
608 if (screenDepth
> 8) return pixel
;
609 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hRevMapping
);
610 if (mapping
) pixel
= mapping
[pixel
];
611 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
612 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
616 /***********************************************************************
619 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
622 HRGN tmpVisRgn
, prevVisRgn
;
623 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
624 if (!dc
) return FALSE
;
626 /* Modify visible region */
628 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
629 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
631 RestoreVisRgn( hdc
);
634 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
635 SelectVisRgn( hdc
, tmpVisRgn
);
636 DeleteObject( tmpVisRgn
);
638 /* Fill the region */
640 GetRgnBox16( dc
->w
.hGCClipRgn
, &box
);
641 if (DC_SetupGCForBrush( dc
))
642 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
643 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
644 box
.right
-box
.left
, box
.bottom
-box
.top
);
646 /* Restore the visible region */
648 RestoreVisRgn( hdc
);
653 /***********************************************************************
656 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
659 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
660 if (!prevBrush
) return FALSE
;
661 retval
= PaintRgn( hdc
, hrgn
);
662 SelectObject( hdc
, prevBrush
);
666 /***********************************************************************
669 BOOL
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, int nWidth
, int nHeight
)
671 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
672 if(!REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
)) return 0;
673 FillRgn( hdc
, tmp
, hbrush
);
678 /***********************************************************************
681 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
683 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
684 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
685 BOOL retval
= PaintRgn( hdc
, hrgn
);
686 SelectObject( hdc
, prevBrush
);
687 SetROP2( hdc
, prevROP
);
692 /***********************************************************************
693 * DrawFocusRect16 (USER.466)
695 void DrawFocusRect16( HDC16 hdc
, const RECT16
* rc
)
698 int oldDrawMode
, oldBkMode
;
699 int left
, top
, right
, bottom
;
700 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
703 left
= XLPTODP( dc
, rc
->left
);
704 top
= YLPTODP( dc
, rc
->top
);
705 right
= XLPTODP( dc
, rc
->right
);
706 bottom
= YLPTODP( dc
, rc
->bottom
);
708 hOldPen
= (HPEN16
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
709 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
710 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
712 /* Hack: make sure the XORPEN operation has an effect */
713 dc
->u
.x
.pen
.pixel
= (1 << screenDepth
) - 1;
715 if (DC_SetupGCForPen( dc
))
716 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
717 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
718 right
-left
-1, bottom
-top
-1 );
720 SetBkMode(hdc
, oldBkMode
);
721 SetROP2(hdc
, oldDrawMode
);
722 SelectObject(hdc
, (HANDLE
)hOldPen
);
726 /***********************************************************************
727 * DrawFocusRect32 (USER32.155)
729 void DrawFocusRect32( HDC32 hdc
, const RECT32
* rect
)
732 CONV_RECT32TO16( rect
, &rect16
);
733 return DrawFocusRect16( (HDC16
)hdc
, &rect16
);
737 /**********************************************************************
740 * Short-cut function to blit a bitmap into a device.
741 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
743 BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
744 int xsrc
, int ysrc
, int width
, int height
)
749 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
750 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
752 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
753 if (bmp
->bitmap
.bmBitsPixel
== 1)
755 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
756 XSetBackground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
757 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
758 xsrc
, ysrc
, width
, height
,
759 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
762 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
764 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
765 xsrc
, ysrc
, width
, height
,
766 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
773 /**********************************************************************
774 * GRAPH_DrawReliefRect (Not a MSWin Call)
776 void GRAPH_DrawReliefRect( HDC hdc
, RECT16
*rect
, int highlight_size
,
777 int shadow_size
, BOOL pressed
)
782 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
783 sysColorObjects
.hbrushBtnHighlight
);
784 for (i
= 0; i
< highlight_size
; i
++)
786 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
787 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
788 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
789 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
792 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
793 sysColorObjects
.hbrushBtnShadow
);
794 for (i
= 0; i
< shadow_size
; i
++)
796 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
797 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
798 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
799 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
802 SelectObject( hdc
, hbrushOld
);
806 /**********************************************************************
807 * Polyline16 (GDI.37)
809 BOOL16
Polyline16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
812 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_POLYLINE
, pt
, count
);
821 if (DC_SetupGCForPen( dc
))
822 for (i
= 0; i
< count
-1; i
++)
823 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
824 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
825 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
826 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
827 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
832 /**********************************************************************
835 BOOL16
Polygon16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
838 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
839 XPoint
*points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
+1));
843 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
844 if (!dc
) return FALSE
;
845 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
849 for (i
= 0; i
< count
; i
++)
851 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
852 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
854 points
[count
] = points
[0];
856 if (DC_SetupGCForBrush( dc
))
857 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
858 points
, count
+1, Complex
, CoordModeOrigin
);
860 if (DC_SetupGCForPen ( dc
))
861 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
862 points
, count
+1, CoordModeOrigin
);
869 /**********************************************************************
870 * PolyPolygon16 (GDI.450)
872 BOOL16
PolyPolygon16( HDC16 hdc
, LPPOINT16 pt
, LPINT16 counts
, UINT16 polygons
)
875 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
879 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
880 if (!dc
) return FALSE
;
881 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
884 /* FIXME: The points should be converted to device coords before */
885 /* creating the region. But as CreatePolyPolygonRgn is not */
886 /* really correct either, it doesn't matter much... */
887 /* At least the outline will be correct :-) */
888 hrgn
= CreatePolyPolygonRgn16( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
889 PaintRgn( hdc
, hrgn
);
890 DeleteObject( hrgn
);
892 /* Draw the outline of the polygons */
894 if (DC_SetupGCForPen ( dc
))
899 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
900 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
902 for (i
= 0; i
< polygons
; i
++)
904 for (j
= 0; j
< counts
[i
]; j
++)
906 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
907 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
910 points
[j
] = points
[0];
911 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
912 points
, j
+ 1, CoordModeOrigin
);
920 /**********************************************************************
921 * GRAPH_InternalFloodFill
923 * Internal helper function for flood fill.
924 * (xorg,yorg) is the origin of the X image relative to the drawable.
925 * (x,y) is relative to the origin of the X image.
927 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
930 Pixel pixel
, WORD fillType
)
934 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
935 (XGetPixel(image,x,y) != pixel) : \
936 (XGetPixel(image,x,y) == pixel))
938 if (!TO_FLOOD(x
,y
)) return;
940 /* Find left and right boundaries */
943 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
944 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
945 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
946 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
948 /* Set the pixels of this line so we don't fill it again */
950 for (x
= left
; x
< right
; x
++)
952 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
953 else XPutPixel( image
, x
, y
, ~pixel
);
956 /* Fill the line above */
963 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
964 if (x
>= right
) break;
965 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
966 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
967 xOrg
, yOrg
, pixel
, fillType
);
971 /* Fill the line below */
973 if ((y
+= 2) < image
->height
)
978 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
979 if (x
>= right
) break;
980 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
981 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
982 xOrg
, yOrg
, pixel
, fillType
);
989 /**********************************************************************
992 * Main flood-fill routine.
994 static BOOL16
GRAPH_DoFloodFill( DC
*dc
, RECT16
*rect
, INT32 x
, INT32 y
,
995 COLORREF color
, UINT32 fillType
)
999 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
1000 dc
->w
.DCOrgX
+ rect
->left
,
1001 dc
->w
.DCOrgY
+ rect
->top
,
1002 rect
->right
- rect
->left
,
1003 rect
->bottom
- rect
->top
,
1004 AllPlanes
, ZPixmap
))) return FALSE
;
1006 if (DC_SetupGCForBrush( dc
))
1008 /* ROP mode is always GXcopy for flood-fill */
1009 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
1010 GRAPH_InternalFloodFill( image
, dc
,
1011 XLPTODP(dc
,x
) - rect
->left
,
1012 YLPTODP(dc
,y
) - rect
->top
,
1013 dc
->w
.DCOrgX
+ rect
->left
,
1014 dc
->w
.DCOrgY
+ rect
->top
,
1015 COLOR_ToPhysical( dc
, color
), fillType
);
1018 XDestroyImage( image
);
1023 /**********************************************************************
1024 * ExtFloodFill (GDI.372) (GDI32.96)
1026 BOOL16
ExtFloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
,
1032 dprintf_graphics( stddeb
, "ExtFloodFill %04x %d,%d %06lx %d\n",
1033 hdc
, x
, y
, color
, fillType
);
1034 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
1037 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
1038 if (!dc
) return FALSE
;
1039 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
1044 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
1045 if (GetRgnBox16( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
1047 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill
, 6,
1048 dc
, &rect
, x
, y
, color
, fillType
);
1052 /**********************************************************************
1053 * FloodFill (GDI.25) (GDI32.104)
1055 BOOL16
FloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
)
1057 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
1061 /**********************************************************************
1062 * DrawEdge16 (USER.659)
1064 BOOL16
DrawEdge16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1069 CONV_RECT16TO32( rc
, &rect32
);
1070 ret
= DrawEdge32( hdc
, &rect32
, edge
, flags
);
1071 CONV_RECT32TO16( &rect32
, rc
);
1076 /**********************************************************************
1077 * DrawEdge32 (USER32.154)
1079 BOOL32
DrawEdge32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1083 if (flags
>= BF_DIAGONAL
)
1084 fprintf( stderr
, "DrawEdge: unsupported flags %04x\n", flags
);
1086 dprintf_graphics( stddeb
, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
1087 hdc
, rc
->left
, rc
->top
, rc
->right
, rc
->bottom
,
1090 /* First do all the raised edges */
1092 SelectObject( hdc
, sysColorObjects
.hbrushBtnHighlight
);
1093 if (edge
& BDR_RAISEDOUTER
)
1095 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1096 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1097 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1098 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1100 if (edge
& BDR_SUNKENOUTER
)
1102 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1103 1, rc
->bottom
- rc
->top
, PATCOPY
);
1104 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1105 rc
->right
- rc
->left
, 1, PATCOPY
);
1107 if (edge
& BDR_RAISEDINNER
)
1109 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1110 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1111 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1112 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1114 if (edge
& BDR_SUNKENINNER
)
1116 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1117 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1118 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1119 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1122 /* Then do all the sunken edges */
1124 hbrushOld
= SelectObject( hdc
, sysColorObjects
.hbrushBtnShadow
);
1125 if (edge
& BDR_SUNKENOUTER
)
1127 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1128 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1129 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1130 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1132 if (edge
& BDR_RAISEDOUTER
)
1134 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1135 1, rc
->bottom
- rc
->top
, PATCOPY
);
1136 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1137 rc
->right
- rc
->left
, 1, PATCOPY
);
1139 if (edge
& BDR_SUNKENINNER
)
1141 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1142 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1143 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1144 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1146 if (edge
& BDR_RAISEDINNER
)
1148 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1149 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1150 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1151 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1154 SelectObject( hdc
, hbrushOld
);
1159 /**********************************************************************
1160 * DrawFrameControl16 (USER.656)
1162 BOOL16
DrawFrameControl16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1164 fprintf( stdnimp
,"DrawFrameControl16(%x,%p,%d,%x), empty stub!\n",
1165 hdc
,rc
,edge
,flags
);
1170 /**********************************************************************
1171 * DrawFrameControl32 (USER32.157)
1173 BOOL32
DrawFrameControl32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1175 fprintf( stdnimp
,"DrawFrameControl32(%x,%p,%d,%x), empty stub!\n",
1176 hdc
,rc
,edge
,flags
);