2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
28 /***********************************************************************
31 BOOL
LineTo( HDC hdc
, short x
, short y
)
33 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
36 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
37 if (!dc
) return FALSE
;
38 MF_MetaParam2(dc
, META_LINETO
, x
, y
);
42 if (DC_SetupGCForPen( dc
))
43 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
44 dc
->w
.DCOrgX
+ XLPTODP( dc
, dc
->w
.CursPosX
),
45 dc
->w
.DCOrgY
+ YLPTODP( dc
, dc
->w
.CursPosY
),
46 dc
->w
.DCOrgX
+ XLPTODP( dc
, x
),
47 dc
->w
.DCOrgY
+ YLPTODP( dc
, y
) );
54 /***********************************************************************
57 DWORD
MoveTo( HDC hdc
, short x
, short y
)
60 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
63 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
64 if (!dc
) return FALSE
;
65 MF_MetaParam2(dc
, META_MOVETO
, x
, y
);
69 oldx
= dc
->w
.CursPosX
;
70 oldy
= dc
->w
.CursPosY
;
73 return oldx
| (oldy
<< 16);
77 /***********************************************************************
78 * MoveToEx16 (GDI.483)
80 BOOL16
MoveToEx16( HDC16 hdc
, INT16 x
, INT16 y
, LPPOINT16 pt
)
82 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
83 if (!dc
) return FALSE
;
86 pt
->x
= dc
->w
.CursPosX
;
87 pt
->y
= dc
->w
.CursPosY
;
95 /***********************************************************************
96 * MoveToEx32 (GDI32.254)
98 BOOL32
MoveToEx32( HDC32 hdc
, INT32 x
, INT32 y
, LPPOINT32 pt
)
101 if (!MoveToEx16( (HDC16
)hdc
, (INT16
)x
, (INT16
)y
, &pt16
)) return FALSE
;
102 if (pt
) CONV_POINT16TO32( &pt16
, pt
);
107 /***********************************************************************
110 * Helper functions for Arc(), Chord() and Pie().
111 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
113 static BOOL
GRAPH_DrawArc( HDC hdc
, int left
, int top
, int right
, int bottom
,
114 int xstart
, int ystart
, int xend
, int yend
, int lines
)
116 int xcenter
, ycenter
, istart_angle
, idiff_angle
, tmp
;
117 double start_angle
, end_angle
;
119 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
122 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
123 if (!dc
) return FALSE
;
127 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
128 xstart
, ystart
, xend
, yend
);
132 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
133 xstart
, ystart
, xend
, yend
);
137 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
138 xstart
, ystart
, xend
, yend
);
144 left
= XLPTODP( dc
, left
);
145 top
= YLPTODP( dc
, top
);
146 right
= XLPTODP( dc
, right
);
147 bottom
= YLPTODP( dc
, bottom
);
148 xstart
= XLPTODP( dc
, xstart
);
149 ystart
= YLPTODP( dc
, ystart
);
150 xend
= XLPTODP( dc
, xend
);
151 yend
= YLPTODP( dc
, yend
);
152 if ((left
== right
) || (top
== bottom
)) return FALSE
;
154 xcenter
= (right
+ left
) / 2;
155 ycenter
= (bottom
+ top
) / 2;
156 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
157 (double)(xstart
-xcenter
)*(bottom
-top
) );
158 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
159 (double)(xend
-xcenter
)*(bottom
-top
) );
160 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
161 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
162 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
163 if (left
> right
) { tmp
=left
; left
=right
; right
=tmp
; }
164 if (top
> bottom
) { tmp
=top
; top
=bottom
; bottom
=tmp
; }
166 /* Fill arc with brush if Chord() or Pie() */
168 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
170 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
171 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
172 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
173 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
176 /* Draw arc and lines */
178 if (!DC_SetupGCForPen( dc
)) return TRUE
;
179 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
180 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
181 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
182 if (!lines
) return TRUE
;
184 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
185 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
186 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
187 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
190 points
[2] = points
[1];
191 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
192 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
194 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
195 points
, lines
+1, CoordModeOrigin
);
200 /***********************************************************************
203 BOOL
Arc( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
204 INT xstart
, INT ystart
, INT xend
, INT yend
)
206 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
207 xstart
, ystart
, xend
, yend
, 0 );
211 /***********************************************************************
214 BOOL
Pie( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
215 INT xstart
, INT ystart
, INT xend
, INT yend
)
217 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
218 xstart
, ystart
, xend
, yend
, 2 );
222 /***********************************************************************
225 BOOL
Chord( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
,
226 INT xstart
, INT ystart
, INT xend
, INT yend
)
228 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
229 xstart
, ystart
, xend
, yend
, 1 );
233 /***********************************************************************
236 BOOL
Ellipse( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
238 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
241 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
242 if (!dc
) return FALSE
;
243 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
247 left
= XLPTODP( dc
, left
);
248 top
= YLPTODP( dc
, top
);
249 right
= XLPTODP( dc
, right
);
250 bottom
= YLPTODP( dc
, bottom
);
251 if ((left
== right
) || (top
== bottom
)) return FALSE
;
253 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
254 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
256 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
257 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
258 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
260 left
+= dc
->u
.x
.pen
.width
/ 2;
261 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
262 top
+= dc
->u
.x
.pen
.width
/ 2;
263 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
266 if (DC_SetupGCForBrush( dc
))
267 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
268 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
269 right
-left
-1, bottom
-top
-1, 0, 360*64 );
270 if (DC_SetupGCForPen( dc
))
271 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
272 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
273 right
-left
-1, bottom
-top
-1, 0, 360*64 );
278 /***********************************************************************
281 BOOL
Rectangle( HDC hdc
, INT left
, INT top
, INT right
, INT bottom
)
284 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
287 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
288 if (!dc
) return FALSE
;
289 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
292 left
= XLPTODP( dc
, left
);
293 top
= YLPTODP( dc
, top
);
294 right
= XLPTODP( dc
, right
);
295 bottom
= YLPTODP( dc
, bottom
);
297 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
298 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
300 if ((left
== right
) || (top
== bottom
))
302 if (DC_SetupGCForPen( dc
))
303 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
306 dc
->w
.DCOrgX
+ right
,
307 dc
->w
.DCOrgY
+ bottom
);
310 width
= dc
->u
.x
.pen
.width
;
311 if (!width
) width
= 1;
312 if(dc
->u
.x
.pen
.style
== PS_NULL
) width
= 0;
314 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
315 (width
< right
-left
) && (width
< bottom
-top
))
318 right
-= (width
+ 1) / 2;
320 bottom
-= (width
+ 1) / 2;
323 if (DC_SetupGCForBrush( dc
))
324 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
325 dc
->w
.DCOrgX
+ left
+ (width
+ 1) / 2,
326 dc
->w
.DCOrgY
+ top
+ (width
+ 1) / 2,
327 right
-left
-width
-1, bottom
-top
-width
-1);
328 if (DC_SetupGCForPen( dc
))
329 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
330 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
331 right
-left
-1, bottom
-top
-1 );
336 /***********************************************************************
339 BOOL
RoundRect( HDC hDC
, INT left
, INT top
, INT right
, INT bottom
,
340 INT ell_width
, INT ell_height
)
342 DC
* dc
= (DC
*) GDI_GetObjPtr(hDC
, DC_MAGIC
);
345 dc
= (DC
*)GDI_GetObjPtr(hDC
, METAFILE_DC_MAGIC
);
346 if (!dc
) return FALSE
;
347 MF_MetaParam6(dc
, META_ROUNDRECT
, left
, top
, right
, bottom
,
348 ell_width
, ell_height
);
351 dprintf_graphics(stddeb
, "RoundRect(%d %d %d %d %d %d\n",
352 left
, top
, right
, bottom
, ell_width
, ell_height
);
354 left
= XLPTODP( dc
, left
);
355 top
= YLPTODP( dc
, top
);
356 right
= XLPTODP( dc
, right
);
357 bottom
= YLPTODP( dc
, bottom
);
358 ell_width
= abs( ell_width
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
);
359 ell_height
= abs( ell_height
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
361 /* Fix the coordinates */
363 if (right
< left
) { INT tmp
= right
; right
= left
; left
= tmp
; }
364 if (bottom
< top
) { INT tmp
= bottom
; bottom
= top
; top
= tmp
; }
365 if (ell_width
> right
- left
) ell_width
= right
- left
;
366 if (ell_height
> bottom
- top
) ell_height
= bottom
- top
;
368 if (DC_SetupGCForBrush( dc
))
370 if (ell_width
&& ell_height
)
372 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
373 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
374 ell_width
, ell_height
, 90 * 64, 90 * 64 );
375 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
376 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
377 ell_width
, ell_height
, 180 * 64, 90 * 64 );
378 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
379 dc
->w
.DCOrgX
+ right
- ell_width
,
380 dc
->w
.DCOrgY
+ bottom
- ell_height
,
381 ell_width
, ell_height
, 270 * 64, 90 * 64 );
382 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
383 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
384 ell_width
, ell_height
, 0, 90 * 64 );
386 if (ell_width
< right
- left
)
388 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
389 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
391 right
- left
- ell_width
, ell_height
/ 2 );
392 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
393 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
394 dc
->w
.DCOrgY
+ bottom
- (ell_height
+1) / 2,
395 right
- left
- ell_width
, (ell_height
+1) / 2 );
397 if (ell_height
< bottom
- top
)
399 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
401 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
402 right
- left
, bottom
- top
- ell_height
);
405 if (DC_SetupGCForPen(dc
))
407 if (ell_width
&& ell_height
)
409 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
410 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
411 ell_width
, ell_height
, 90 * 64, 90 * 64 );
412 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
413 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ bottom
- ell_height
,
414 ell_width
, ell_height
, 180 * 64, 90 * 64 );
415 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
416 dc
->w
.DCOrgX
+ right
- ell_width
,
417 dc
->w
.DCOrgY
+ bottom
- ell_height
,
418 ell_width
, ell_height
, 270 * 64, 90 * 64 );
419 XDrawArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
420 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
,
421 ell_width
, ell_height
, 0, 90 * 64 );
423 if (ell_width
< right
- left
)
425 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
426 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
428 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
429 dc
->w
.DCOrgY
+ top
);
430 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
431 dc
->w
.DCOrgX
+ left
+ ell_width
/ 2,
432 dc
->w
.DCOrgY
+ bottom
,
433 dc
->w
.DCOrgX
+ right
- ell_width
/ 2,
434 dc
->w
.DCOrgY
+ bottom
);
436 if (ell_height
< bottom
- top
)
438 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
439 dc
->w
.DCOrgX
+ right
,
440 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
441 dc
->w
.DCOrgX
+ right
,
442 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
443 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
445 dc
->w
.DCOrgY
+ top
+ ell_height
/ 2,
447 dc
->w
.DCOrgY
+ bottom
- ell_height
/ 2 );
454 /***********************************************************************
455 * FillRect16 (USER.81)
457 INT16
FillRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
461 /* coordinates are logical so we cannot fast-check rectangle
462 * - do it in PatBlt() after LPtoDP().
465 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
466 PatBlt( hdc
, rect
->left
, rect
->top
,
467 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
468 SelectObject( hdc
, prevBrush
);
473 /***********************************************************************
474 * FillRect32 (USER32.196)
476 INT32
FillRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
480 if (!(prevBrush
= SelectObject( hdc
, (HBRUSH16
)hbrush
))) return 0;
481 PatBlt( hdc
, rect
->left
, rect
->top
,
482 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
483 SelectObject( hdc
, prevBrush
);
488 /***********************************************************************
489 * InvertRect16 (USER.82)
491 void InvertRect16( HDC16 hdc
, const RECT16
*rect
)
493 PatBlt( hdc
, rect
->left
, rect
->top
,
494 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
498 /***********************************************************************
499 * InvertRect32 (USER32.329)
501 void InvertRect32( HDC32 hdc
, const RECT32
*rect
)
503 PatBlt( hdc
, rect
->left
, rect
->top
,
504 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
508 /***********************************************************************
509 * FrameRect16 (USER.83)
511 INT16
FrameRect16( HDC16 hdc
, const RECT16
*rect
, HBRUSH16 hbrush
)
514 int left
, top
, right
, bottom
;
516 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
517 if (!dc
) return FALSE
;
519 left
= XLPTODP( dc
, rect
->left
);
520 top
= YLPTODP( dc
, rect
->top
);
521 right
= XLPTODP( dc
, rect
->right
);
522 bottom
= YLPTODP( dc
, rect
->bottom
);
524 if ( (right
<= left
) || (bottom
<= top
) ) return 0;
525 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
527 if (DC_SetupGCForBrush( dc
))
529 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
530 rect
->bottom
- rect
->top
, PATCOPY
);
531 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
532 rect
->bottom
- rect
->top
, PATCOPY
);
533 PatBlt( hdc
, rect
->left
, rect
->top
,
534 rect
->right
- rect
->left
, 1, PATCOPY
);
535 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
536 rect
->right
- rect
->left
, 1, PATCOPY
);
538 SelectObject( hdc
, prevBrush
);
543 /***********************************************************************
544 * FrameRect32 (USER32.202)
546 INT32
FrameRect32( HDC32 hdc
, const RECT32
*rect
, HBRUSH32 hbrush
)
549 CONV_RECT32TO16( rect
, &rect16
);
550 return FrameRect16( (HDC16
)hdc
, &rect16
, (HBRUSH16
)hbrush
);
554 /***********************************************************************
557 COLORREF
SetPixel( HDC hdc
, short x
, short y
, COLORREF color
)
561 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
564 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
566 MF_MetaParam4(dc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
));
570 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
571 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
572 pixel
= COLOR_ToPhysical( dc
, color
);
574 XSetForeground( display
, dc
->u
.x
.gc
, pixel
);
575 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
576 XDrawPoint( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
, x
, y
);
578 /* inefficient but simple... */
580 return COLOR_ToLogical(pixel
);
584 /***********************************************************************
587 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
589 static Pixmap pixmap
= 0;
593 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
596 #ifdef SOLITAIRE_SPEED_HACK
600 if (!PtVisible( hdc
, x
, y
)) return 0;
602 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
603 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
604 if (dc
->w
.flags
& DC_MEMORY
)
606 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
, 1, 1,
607 AllPlanes
, ZPixmap
);
611 /* If we are reading from the screen, use a temporary copy */
612 /* to avoid a BadMatch error */
613 if (!pixmap
) pixmap
= XCreatePixmap( display
, rootWindow
,
614 1, 1, dc
->w
.bitsPerPixel
);
615 XCopyArea( display
, dc
->u
.x
.drawable
, pixmap
, BITMAP_colorGC
,
617 image
= XGetImage( display
, pixmap
, 0, 0, 1, 1, AllPlanes
, ZPixmap
);
619 pixel
= XGetPixel( image
, 0, 0 );
620 XDestroyImage( image
);
622 return COLOR_ToLogical(pixel
);
626 /***********************************************************************
629 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
632 HRGN tmpVisRgn
, prevVisRgn
;
633 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
634 if (!dc
) return FALSE
;
636 /* Modify visible region */
638 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
639 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
641 RestoreVisRgn( hdc
);
644 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
645 SelectVisRgn( hdc
, tmpVisRgn
);
646 DeleteObject( tmpVisRgn
);
648 /* Fill the region */
650 GetRgnBox16( dc
->w
.hGCClipRgn
, &box
);
651 if (DC_SetupGCForBrush( dc
))
652 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
653 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
654 box
.right
-box
.left
, box
.bottom
-box
.top
);
656 /* Restore the visible region */
658 RestoreVisRgn( hdc
);
663 /***********************************************************************
666 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
669 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
670 if (!prevBrush
) return FALSE
;
671 retval
= PaintRgn( hdc
, hrgn
);
672 SelectObject( hdc
, prevBrush
);
676 /***********************************************************************
679 BOOL
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
, int nWidth
, int nHeight
)
681 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
682 if(!REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
)) return 0;
683 FillRgn( hdc
, tmp
, hbrush
);
688 /***********************************************************************
691 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
693 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
694 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
695 BOOL retval
= PaintRgn( hdc
, hrgn
);
696 SelectObject( hdc
, prevBrush
);
697 SetROP2( hdc
, prevROP
);
702 /***********************************************************************
703 * DrawFocusRect16 (USER.466)
705 void DrawFocusRect16( HDC16 hdc
, const RECT16
* rc
)
708 int oldDrawMode
, oldBkMode
;
709 int left
, top
, right
, bottom
;
710 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
713 left
= XLPTODP( dc
, rc
->left
);
714 top
= YLPTODP( dc
, rc
->top
);
715 right
= XLPTODP( dc
, rc
->right
);
716 bottom
= YLPTODP( dc
, rc
->bottom
);
718 hOldPen
= (HPEN16
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
719 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
720 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
722 /* Hack: make sure the XORPEN operation has an effect */
723 dc
->u
.x
.pen
.pixel
= (1 << screenDepth
) - 1;
725 if (DC_SetupGCForPen( dc
))
726 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
727 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
728 right
-left
-1, bottom
-top
-1 );
730 SetBkMode(hdc
, oldBkMode
);
731 SetROP2(hdc
, oldDrawMode
);
732 SelectObject(hdc
, (HANDLE
)hOldPen
);
736 /***********************************************************************
737 * DrawFocusRect32 (USER32.155)
739 void DrawFocusRect32( HDC32 hdc
, const RECT32
* rect
)
742 CONV_RECT32TO16( rect
, &rect16
);
743 return DrawFocusRect16( (HDC16
)hdc
, &rect16
);
747 /**********************************************************************
750 * Short-cut function to blit a bitmap into a device.
751 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
753 BOOL32
GRAPH_DrawBitmap( HDC32 hdc
, HBITMAP32 hbitmap
, int xdest
, int ydest
,
754 int xsrc
, int ysrc
, int width
, int height
)
759 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
760 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
762 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
763 if (bmp
->bitmap
.bmBitsPixel
== 1)
765 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
766 XSetBackground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
767 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
768 xsrc
, ysrc
, width
, height
,
769 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
772 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
774 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
775 xsrc
, ysrc
, width
, height
,
776 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
783 /**********************************************************************
784 * GRAPH_DrawReliefRect (Not a MSWin Call)
786 void GRAPH_DrawReliefRect( HDC32 hdc
, const RECT32
*rect
, INT32 highlight_size
,
787 INT32 shadow_size
, BOOL32 pressed
)
792 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
793 sysColorObjects
.hbrushBtnHighlight
);
794 for (i
= 0; i
< highlight_size
; i
++)
796 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
797 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
798 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
799 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
802 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
803 sysColorObjects
.hbrushBtnShadow
);
804 for (i
= 0; i
< shadow_size
; i
++)
806 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
807 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
808 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
809 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
812 SelectObject( hdc
, hbrushOld
);
816 /**********************************************************************
817 * Polyline16 (GDI.37)
819 BOOL16
Polyline16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
822 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
825 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
826 if (!dc
) return FALSE
;
827 MF_MetaPoly(dc
, META_POLYLINE
, pt
, count
);
831 if (DC_SetupGCForPen( dc
))
832 for (i
= 0; i
< count
-1; i
++)
833 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
834 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
835 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
836 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
837 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
842 /**********************************************************************
845 BOOL16
Polygon16( HDC16 hdc
, LPPOINT16 pt
, INT16 count
)
848 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
849 XPoint
*points
= (XPoint
*) xmalloc (sizeof (XPoint
) * (count
+1));
853 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
854 if (!dc
) return FALSE
;
855 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
859 for (i
= 0; i
< count
; i
++)
861 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
862 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
864 points
[count
] = points
[0];
866 if (DC_SetupGCForBrush( dc
))
867 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
868 points
, count
+1, Complex
, CoordModeOrigin
);
870 if (DC_SetupGCForPen ( dc
))
871 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
872 points
, count
+1, CoordModeOrigin
);
879 /**********************************************************************
880 * PolyPolygon16 (GDI.450)
882 BOOL16
PolyPolygon16( HDC16 hdc
, LPPOINT16 pt
, LPINT16 counts
, UINT16 polygons
)
885 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
889 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
890 if (!dc
) return FALSE
;
891 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
894 /* FIXME: The points should be converted to device coords before */
895 /* creating the region. But as CreatePolyPolygonRgn is not */
896 /* really correct either, it doesn't matter much... */
897 /* At least the outline will be correct :-) */
898 hrgn
= CreatePolyPolygonRgn16( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
899 PaintRgn( hdc
, hrgn
);
900 DeleteObject( hrgn
);
902 /* Draw the outline of the polygons */
904 if (DC_SetupGCForPen ( dc
))
909 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
910 points
= (XPoint
*) xmalloc( sizeof(XPoint
) * (max
+1) );
912 for (i
= 0; i
< polygons
; i
++)
914 for (j
= 0; j
< counts
[i
]; j
++)
916 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
917 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
920 points
[j
] = points
[0];
921 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
922 points
, j
+ 1, CoordModeOrigin
);
930 /**********************************************************************
931 * GRAPH_InternalFloodFill
933 * Internal helper function for flood fill.
934 * (xorg,yorg) is the origin of the X image relative to the drawable.
935 * (x,y) is relative to the origin of the X image.
937 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
940 Pixel pixel
, WORD fillType
)
944 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
945 (XGetPixel(image,x,y) != pixel) : \
946 (XGetPixel(image,x,y) == pixel))
948 if (!TO_FLOOD(x
,y
)) return;
950 /* Find left and right boundaries */
953 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
954 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
955 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
956 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
958 /* Set the pixels of this line so we don't fill it again */
960 for (x
= left
; x
< right
; x
++)
962 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
963 else XPutPixel( image
, x
, y
, ~pixel
);
966 /* Fill the line above */
973 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
974 if (x
>= right
) break;
975 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
976 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
977 xOrg
, yOrg
, pixel
, fillType
);
981 /* Fill the line below */
983 if ((y
+= 2) < image
->height
)
988 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
989 if (x
>= right
) break;
990 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
991 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
992 xOrg
, yOrg
, pixel
, fillType
);
999 /**********************************************************************
1002 * Main flood-fill routine.
1004 static BOOL16
GRAPH_DoFloodFill( DC
*dc
, RECT16
*rect
, INT32 x
, INT32 y
,
1005 COLORREF color
, UINT32 fillType
)
1009 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
1010 dc
->w
.DCOrgX
+ rect
->left
,
1011 dc
->w
.DCOrgY
+ rect
->top
,
1012 rect
->right
- rect
->left
,
1013 rect
->bottom
- rect
->top
,
1014 AllPlanes
, ZPixmap
))) return FALSE
;
1016 if (DC_SetupGCForBrush( dc
))
1018 /* ROP mode is always GXcopy for flood-fill */
1019 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
1020 GRAPH_InternalFloodFill( image
, dc
,
1021 XLPTODP(dc
,x
) - rect
->left
,
1022 YLPTODP(dc
,y
) - rect
->top
,
1023 dc
->w
.DCOrgX
+ rect
->left
,
1024 dc
->w
.DCOrgY
+ rect
->top
,
1025 COLOR_ToPhysical( dc
, color
), fillType
);
1028 XDestroyImage( image
);
1033 /**********************************************************************
1034 * ExtFloodFill (GDI.372) (GDI32.96)
1036 BOOL16
ExtFloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
,
1042 dprintf_graphics( stddeb
, "ExtFloodFill %04x %d,%d %06lx %d\n",
1043 hdc
, x
, y
, color
, fillType
);
1044 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
1047 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
1048 if (!dc
) return FALSE
;
1049 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
1054 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
1055 if (GetRgnBox16( dc
->w
.hGCClipRgn
, &rect
) == ERROR
) return FALSE
;
1057 return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill
, 6,
1058 dc
, &rect
, x
, y
, color
, fillType
);
1062 /**********************************************************************
1063 * FloodFill (GDI.25) (GDI32.104)
1065 BOOL16
FloodFill( HDC32 hdc
, INT32 x
, INT32 y
, COLORREF color
)
1067 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
1071 /**********************************************************************
1072 * DrawEdge16 (USER.659)
1074 BOOL16
DrawEdge16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1079 CONV_RECT16TO32( rc
, &rect32
);
1080 ret
= DrawEdge32( hdc
, &rect32
, edge
, flags
);
1081 CONV_RECT32TO16( &rect32
, rc
);
1086 /**********************************************************************
1087 * DrawEdge32 (USER32.154)
1089 BOOL32
DrawEdge32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1093 if (flags
>= BF_DIAGONAL
)
1094 fprintf( stderr
, "DrawEdge: unsupported flags %04x\n", flags
);
1096 dprintf_graphics( stddeb
, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
1097 hdc
, rc
->left
, rc
->top
, rc
->right
, rc
->bottom
,
1100 /* First do all the raised edges */
1102 SelectObject( hdc
, sysColorObjects
.hbrushBtnHighlight
);
1103 if (edge
& BDR_RAISEDOUTER
)
1105 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1106 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1107 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1108 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1110 if (edge
& BDR_SUNKENOUTER
)
1112 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1113 1, rc
->bottom
- rc
->top
, PATCOPY
);
1114 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1115 rc
->right
- rc
->left
, 1, PATCOPY
);
1117 if (edge
& BDR_RAISEDINNER
)
1119 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1120 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1121 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1122 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1124 if (edge
& BDR_SUNKENINNER
)
1126 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1127 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1128 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1129 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1132 /* Then do all the sunken edges */
1134 hbrushOld
= SelectObject( hdc
, sysColorObjects
.hbrushBtnShadow
);
1135 if (edge
& BDR_SUNKENOUTER
)
1137 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
, rc
->top
,
1138 1, rc
->bottom
- rc
->top
- 1, PATCOPY
);
1139 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
, rc
->top
,
1140 rc
->right
- rc
->left
- 1, 1, PATCOPY
);
1142 if (edge
& BDR_RAISEDOUTER
)
1144 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 1, rc
->top
,
1145 1, rc
->bottom
- rc
->top
, PATCOPY
);
1146 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
, rc
->bottom
- 1,
1147 rc
->right
- rc
->left
, 1, PATCOPY
);
1149 if (edge
& BDR_SUNKENINNER
)
1151 if (flags
& BF_LEFT
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1152 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1153 if (flags
& BF_TOP
) PatBlt( hdc
, rc
->left
+ 1, rc
->top
+ 1,
1154 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1156 if (edge
& BDR_RAISEDINNER
)
1158 if (flags
& BF_RIGHT
) PatBlt( hdc
, rc
->right
- 2, rc
->top
+ 1,
1159 1, rc
->bottom
- rc
->top
- 2, PATCOPY
);
1160 if (flags
& BF_BOTTOM
) PatBlt( hdc
, rc
->left
+ 1, rc
->bottom
- 2,
1161 rc
->right
- rc
->left
- 2, 1, PATCOPY
);
1164 SelectObject( hdc
, hbrushOld
);
1169 /**********************************************************************
1170 * DrawFrameControl16 (USER.656)
1172 BOOL16
DrawFrameControl16( HDC16 hdc
, LPRECT16 rc
, UINT16 edge
, UINT16 flags
)
1174 fprintf( stdnimp
,"DrawFrameControl16(%x,%p,%d,%x), empty stub!\n",
1175 hdc
,rc
,edge
,flags
);
1180 /**********************************************************************
1181 * DrawFrameControl32 (USER32.157)
1183 BOOL32
DrawFrameControl32( HDC32 hdc
, LPRECT32 rc
, UINT32 edge
, UINT32 flags
)
1185 fprintf( stdnimp
,"DrawFrameControl32(%x,%p,%d,%x), empty stub!\n",
1186 hdc
,rc
,edge
,flags
);