2 * GDI graphics operations
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xutil.h>
11 #include <X11/Intrinsic.h>
23 static __inline__
void swap_int(int *a
, int *b
)
32 /***********************************************************************
35 BOOL
LineTo( HDC hdc
, short x
, short y
)
37 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
40 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
41 if (!dc
) return FALSE
;
42 MF_MetaParam2(dc
, META_LINETO
, x
, y
);
46 if (DC_SetupGCForPen( dc
))
47 XDrawLine(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
48 dc
->w
.DCOrgX
+ XLPTODP( dc
, dc
->w
.CursPosX
),
49 dc
->w
.DCOrgY
+ YLPTODP( dc
, dc
->w
.CursPosY
),
50 dc
->w
.DCOrgX
+ XLPTODP( dc
, x
),
51 dc
->w
.DCOrgY
+ YLPTODP( dc
, y
) );
58 /***********************************************************************
61 DWORD
MoveTo( HDC hdc
, short x
, short y
)
64 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
67 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
68 if (!dc
) return FALSE
;
69 MF_MetaParam2(dc
, META_MOVETO
, x
, y
);
73 oldx
= dc
->w
.CursPosX
;
74 oldy
= dc
->w
.CursPosY
;
77 return oldx
| (oldy
<< 16);
81 /***********************************************************************
84 BOOL
MoveToEx( HDC hdc
, short x
, short y
, LPPOINT pt
)
86 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
87 if (!dc
) return FALSE
;
90 pt
->x
= dc
->w
.CursPosX
;
91 pt
->y
= dc
->w
.CursPosY
;
99 /***********************************************************************
102 * Helper functions for Arc(), Chord() and Pie().
103 * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
105 static BOOL
GRAPH_DrawArc( HDC hdc
, int left
, int top
, int right
, int bottom
,
106 int xstart
, int ystart
, int xend
, int yend
, int lines
)
108 int xcenter
, ycenter
, istart_angle
, idiff_angle
;
109 double start_angle
, end_angle
;
111 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
114 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
115 if (!dc
) return FALSE
;
119 MF_MetaParam8(dc
, META_ARC
, left
, top
, right
, bottom
,
120 xstart
, ystart
, xend
, yend
);
124 MF_MetaParam8(dc
, META_CHORD
, left
, top
, right
, bottom
,
125 xstart
, ystart
, xend
, yend
);
129 MF_MetaParam8(dc
, META_PIE
, left
, top
, right
, bottom
,
130 xstart
, ystart
, xend
, yend
);
136 left
= XLPTODP( dc
, left
);
137 top
= YLPTODP( dc
, top
);
138 right
= XLPTODP( dc
, right
);
139 bottom
= YLPTODP( dc
, bottom
);
140 xstart
= XLPTODP( dc
, xstart
);
141 ystart
= YLPTODP( dc
, ystart
);
142 xend
= XLPTODP( dc
, xend
);
143 yend
= YLPTODP( dc
, yend
);
144 if ((left
== right
) || (top
== bottom
)) return FALSE
;
146 xcenter
= (right
+ left
) / 2;
147 ycenter
= (bottom
+ top
) / 2;
148 start_angle
= atan2( (double)(ycenter
-ystart
)*(right
-left
),
149 (double)(xstart
-xcenter
)*(bottom
-top
) );
150 end_angle
= atan2( (double)(ycenter
-yend
)*(right
-left
),
151 (double)(xend
-xcenter
)*(bottom
-top
) );
152 istart_angle
= (int)(start_angle
* 180 * 64 / PI
);
153 idiff_angle
= (int)((end_angle
- start_angle
) * 180 * 64 / PI
);
154 if (idiff_angle
<= 0) idiff_angle
+= 360 * 64;
155 if (left
> right
) swap_int( &left
, &right
);
156 if (top
> bottom
) swap_int( &top
, &bottom
);
158 /* Fill arc with brush if Chord() or Pie() */
160 if ((lines
> 0) && DC_SetupGCForBrush( dc
))
162 XSetArcMode( display
, dc
->u
.x
.gc
, (lines
==1) ? ArcChord
: ArcPieSlice
);
163 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
164 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
165 right
-left
-1, bottom
-top
-1, istart_angle
, idiff_angle
);
168 /* Draw arc and lines */
170 if (!DC_SetupGCForPen( dc
)) return TRUE
;
171 XDrawArc( 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
);
174 if (!lines
) return TRUE
;
176 points
[0].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(start_angle
) * (right
-left
) / 2);
177 points
[0].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(start_angle
) * (bottom
-top
) / 2);
178 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
+ (int)(cos(end_angle
) * (right
-left
) / 2);
179 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
- (int)(sin(end_angle
) * (bottom
-top
) / 2);
182 points
[2] = points
[1];
183 points
[1].x
= dc
->w
.DCOrgX
+ xcenter
;
184 points
[1].y
= dc
->w
.DCOrgY
+ ycenter
;
186 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
187 points
, lines
+1, CoordModeOrigin
);
192 /***********************************************************************
195 BOOL
Arc( HDC hdc
, int left
, int top
, int right
, int bottom
,
196 int xstart
, int ystart
, int xend
, int yend
)
198 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
199 xstart
, ystart
, xend
, yend
, 0 );
203 /***********************************************************************
206 BOOL
Pie( HDC hdc
, int left
, int top
, int right
, int bottom
,
207 int xstart
, int ystart
, int xend
, int yend
)
209 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
210 xstart
, ystart
, xend
, yend
, 2 );
214 /***********************************************************************
217 BOOL
Chord( HDC hdc
, int left
, int top
, int right
, int bottom
,
218 int xstart
, int ystart
, int xend
, int yend
)
220 return GRAPH_DrawArc( hdc
, left
, top
, right
, bottom
,
221 xstart
, ystart
, xend
, yend
, 1 );
225 /***********************************************************************
228 BOOL
Ellipse( HDC hdc
, int left
, int top
, int right
, int bottom
)
230 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
233 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
234 if (!dc
) return FALSE
;
235 MF_MetaParam4(dc
, META_ELLIPSE
, left
, top
, right
, bottom
);
239 left
= XLPTODP( dc
, left
);
240 top
= YLPTODP( dc
, top
);
241 right
= XLPTODP( dc
, right
);
242 bottom
= YLPTODP( dc
, bottom
);
243 if ((left
== right
) || (top
== bottom
)) return FALSE
;
246 swap_int(&right
, &left
);
249 swap_int(&bottom
, &top
);
251 if ((dc
->u
.x
.pen
.style
== PS_INSIDEFRAME
) &&
252 (dc
->u
.x
.pen
.width
< right
-left
-1) &&
253 (dc
->u
.x
.pen
.width
< bottom
-top
-1))
255 left
+= dc
->u
.x
.pen
.width
/ 2;
256 right
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
257 top
+= dc
->u
.x
.pen
.width
/ 2;
258 bottom
-= (dc
->u
.x
.pen
.width
+ 1) / 2;
261 if (DC_SetupGCForBrush( dc
))
262 XFillArc( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
263 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
264 right
-left
-1, bottom
-top
-1, 0, 360*64 );
265 if (DC_SetupGCForPen( dc
))
266 XDrawArc( 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 );
273 /***********************************************************************
276 BOOL
Rectangle( HDC hdc
, int left
, int top
, int right
, int bottom
)
278 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
281 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
282 if (!dc
) return FALSE
;
283 MF_MetaParam4(dc
, META_RECTANGLE
, left
, top
, right
, bottom
);
286 left
= XLPTODP( dc
, left
);
287 top
= YLPTODP( dc
, top
);
288 right
= XLPTODP( dc
, right
);
289 bottom
= YLPTODP( dc
, bottom
);
292 swap_int(&right
, &left
);
295 swap_int(&bottom
, &top
);
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
, short left
, short top
, short right
, short bottom
,
334 short ell_width
, short 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
);
348 x1
= XLPTODP(dc
, left
);
349 y1
= YLPTODP(dc
, top
);
350 x2
= XLPTODP(dc
, right
- ell_width
);
351 y2
= YLPTODP(dc
, bottom
- ell_height
);
352 if (DC_SetupGCForBrush( dc
))
354 XFillArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
355 dc
->w
.DCOrgX
+ x1
, dc
->w
.DCOrgY
+ y1
,
356 ell_width
, ell_height
, 90 * 64, 90 * 64);
357 XFillArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
358 dc
->w
.DCOrgX
+ x1
, dc
->w
.DCOrgY
+ y2
,
359 ell_width
, ell_height
, 180 * 64, 90 * 64);
360 XFillArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
361 dc
->w
.DCOrgX
+ x2
, dc
->w
.DCOrgY
+ y2
,
362 ell_width
, ell_height
, 270 * 64, 90 * 64);
363 XFillArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
364 dc
->w
.DCOrgX
+ x2
, dc
->w
.DCOrgY
+ y1
,
365 ell_width
, ell_height
, 0, 90 * 64);
366 ell_width
/= 2; ell_height
/= 2;
367 XFillRectangle(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
368 dc
->w
.DCOrgX
+ left
+ ell_width
, dc
->w
.DCOrgY
+ top
,
369 right
- left
- 2 * ell_width
, bottom
- top
);
370 XFillRectangle(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
371 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
+ ell_height
,
372 ell_width
, bottom
- top
- 2 * ell_height
);
373 XFillRectangle(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
374 dc
->w
.DCOrgX
+ right
- ell_width
, dc
->w
.DCOrgY
+ top
+ ell_height
,
375 ell_width
, bottom
- top
- 2 * ell_height
);
376 ell_width
*= 2; ell_height
*= 2;
378 if (DC_SetupGCForPen(dc
)) {
379 XDrawArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
380 dc
->w
.DCOrgX
+ x1
, dc
->w
.DCOrgY
+ y1
,
381 ell_width
, ell_height
, 90 * 64, 90 * 64);
382 XDrawArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
383 dc
->w
.DCOrgX
+ x1
, dc
->w
.DCOrgY
+ y2
,
384 ell_width
, ell_height
, 180 * 64, 90 * 64);
385 XDrawArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
386 dc
->w
.DCOrgX
+ x2
, dc
->w
.DCOrgY
+ y2
,
387 ell_width
, ell_height
, 270 * 64, 90 * 64);
388 XDrawArc(display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
389 dc
->w
.DCOrgX
+ x2
, dc
->w
.DCOrgY
+ y1
,
390 ell_width
, ell_height
, 0, 90 * 64);
392 ell_width
/= 2; ell_height
/= 2;
393 MoveTo(hDC
, left
, top
+ ell_height
);
394 LineTo(hDC
, left
, bottom
- ell_height
);
395 MoveTo(hDC
, left
+ ell_width
, bottom
);
396 LineTo(hDC
, right
- ell_width
, bottom
);
397 MoveTo(hDC
, right
, bottom
- ell_height
);
398 LineTo(hDC
, right
, top
+ ell_height
);
399 MoveTo(hDC
, right
- ell_width
, top
);
400 LineTo(hDC
, left
+ ell_width
, top
);
405 /***********************************************************************
408 int FillRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
412 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
413 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
414 PatBlt( hdc
, rect
->left
, rect
->top
,
415 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, PATCOPY
);
416 SelectObject( hdc
, prevBrush
);
421 /***********************************************************************
422 * InvertRect (USER.82)
424 void InvertRect( HDC hdc
, LPRECT rect
)
426 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return;
427 PatBlt( hdc
, rect
->left
, rect
->top
,
428 rect
->right
- rect
->left
, rect
->bottom
- rect
->top
, DSTINVERT
);
432 /***********************************************************************
433 * FrameRect (USER.83)
435 int FrameRect( HDC hdc
, LPRECT rect
, HBRUSH hbrush
)
438 int left
, top
, right
, bottom
;
440 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
441 if (!dc
) return FALSE
;
443 if ((rect
->right
<= rect
->left
) || (rect
->bottom
<= rect
->top
)) return 0;
444 if (!(prevBrush
= SelectObject( hdc
, hbrush
))) return 0;
446 left
= XLPTODP( dc
, rect
->left
);
447 top
= YLPTODP( dc
, rect
->top
);
448 right
= XLPTODP( dc
, rect
->right
);
449 bottom
= YLPTODP( dc
, rect
->bottom
);
451 if (DC_SetupGCForBrush( dc
))
453 PatBlt( hdc
, rect
->left
, rect
->top
, 1,
454 rect
->bottom
- rect
->top
, PATCOPY
);
455 PatBlt( hdc
, rect
->right
- 1, rect
->top
, 1,
456 rect
->bottom
- rect
->top
, PATCOPY
);
457 PatBlt( hdc
, rect
->left
, rect
->top
,
458 rect
->right
- rect
->left
, 1, PATCOPY
);
459 PatBlt( hdc
, rect
->left
, rect
->bottom
- 1,
460 rect
->right
- rect
->left
, 1, PATCOPY
);
462 SelectObject( hdc
, prevBrush
);
467 /***********************************************************************
470 COLORREF
SetPixel( HDC hdc
, short x
, short y
, COLORREF color
)
475 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
478 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
480 MF_MetaParam4(dc
, META_SETPIXEL
, x
, y
, HIWORD(color
), LOWORD(color
));
484 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
485 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
486 pixel
= COLOR_ToPhysical( dc
, color
);
488 XSetForeground( display
, dc
->u
.x
.gc
, pixel
);
489 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
490 XDrawPoint( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
, x
, y
);
492 if (screenDepth
<= 8)
494 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
495 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
497 else return (COLORREF
)pixel
;
501 /***********************************************************************
504 COLORREF
GetPixel( HDC hdc
, short x
, short y
)
511 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
514 #ifdef SOLITAIRE_SPEED_HACK
518 if (!PtVisible( hdc
, x
, y
)) return 0;
520 x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, x
);
521 y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, y
);
522 image
= XGetImage( display
, dc
->u
.x
.drawable
, x
, y
,
523 1, 1, AllPlanes
, ZPixmap
);
524 pixel
= XGetPixel( image
, 0, 0 );
525 XDestroyImage( image
);
527 if (screenDepth
> 8) return pixel
;
528 mapping
= (WORD
*) GDI_HEAP_ADDR( dc
->u
.x
.pal
.hRevMapping
);
529 if (mapping
) pixel
= mapping
[pixel
];
530 GetPaletteEntries( dc
->w
.hPalette
, pixel
, 1, &entry
);
531 return RGB( entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
535 /***********************************************************************
538 BOOL
PaintRgn( HDC hdc
, HRGN hrgn
)
541 HRGN tmpVisRgn
, prevVisRgn
;
542 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
543 if (!dc
) return FALSE
;
545 /* FIXME: the region is supposed to be in logical coordinates */
547 /* Modify visible region */
549 if (!(prevVisRgn
= SaveVisRgn( hdc
))) return FALSE
;
550 if (!(tmpVisRgn
= CreateRectRgn( 0, 0, 0, 0 )))
552 RestoreVisRgn( hdc
);
555 CombineRgn( tmpVisRgn
, prevVisRgn
, hrgn
, RGN_AND
);
556 SelectVisRgn( hdc
, tmpVisRgn
);
557 DeleteObject( tmpVisRgn
);
559 /* Fill the region */
561 GetClipBox( hdc
, &box
);
562 if (DC_SetupGCForBrush( dc
))
563 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
564 dc
->w
.DCOrgX
+ box
.left
, dc
->w
.DCOrgY
+ box
.top
,
565 box
.right
-box
.left
, box
.bottom
-box
.top
);
567 /* Restore the visible region */
569 RestoreVisRgn( hdc
);
574 /***********************************************************************
577 BOOL
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
580 HBRUSH prevBrush
= SelectObject( hdc
, hbrush
);
581 if (!prevBrush
) return FALSE
;
582 retval
= PaintRgn( hdc
, hrgn
);
583 SelectObject( hdc
, prevBrush
);
588 /***********************************************************************
591 BOOL
InvertRgn( HDC hdc
, HRGN hrgn
)
593 HBRUSH prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
594 WORD prevROP
= SetROP2( hdc
, R2_NOT
);
595 BOOL retval
= PaintRgn( hdc
, hrgn
);
596 SelectObject( hdc
, prevBrush
);
597 SetROP2( hdc
, prevROP
);
602 /***********************************************************************
603 * DrawFocusRect (USER.466)
605 void DrawFocusRect( HDC hdc
, LPRECT rc
)
608 int oldDrawMode
, oldBkMode
;
609 int left
, top
, right
, bottom
;
610 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
613 left
= XLPTODP( dc
, rc
->left
);
614 top
= YLPTODP( dc
, rc
->top
);
615 right
= XLPTODP( dc
, rc
->right
);
616 bottom
= YLPTODP( dc
, rc
->bottom
);
618 hOldPen
= (HPEN
)SelectObject(hdc
, sysColorObjects
.hpenWindowText
);
619 oldDrawMode
= SetROP2(hdc
, R2_XORPEN
);
620 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
622 if (DC_SetupGCForPen( dc
))
623 XDrawRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
624 dc
->w
.DCOrgX
+ left
, dc
->w
.DCOrgY
+ top
,
625 right
-left
-1, bottom
-top
-1 );
627 SetBkMode(hdc
, oldBkMode
);
628 SetROP2(hdc
, oldDrawMode
);
629 SelectObject(hdc
, (HANDLE
)hOldPen
);
633 /**********************************************************************
636 * Short-cut function to blit a bitmap into a device.
637 * Faster than CreateCompatibleDC() + SelectBitmap() + BitBlt() + DeleteDC().
639 BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
640 int xsrc
, int ysrc
, int width
, int height
)
646 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return FALSE
;
647 if (!(bmp
= (BITMAPOBJ
*) GDI_GetObjPtr( hbitmap
, BITMAP_MAGIC
)))
649 val
.function
= GXcopy
;
650 val
.foreground
= dc
->w
.textPixel
;
651 val
.background
= dc
->w
.backgroundPixel
;
652 XChangeGC(display
, dc
->u
.x
.gc
, GCFunction
|GCForeground
|GCBackground
, &val
);
653 if (bmp
->bitmap
.bmBitsPixel
== 1)
655 XCopyPlane( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
656 xsrc
, ysrc
, width
, height
,
657 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
, 1 );
660 else if (bmp
->bitmap
.bmBitsPixel
== dc
->w
.bitsPerPixel
)
662 XCopyArea( display
, bmp
->pixmap
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
663 xsrc
, ysrc
, width
, height
,
664 dc
->w
.DCOrgX
+ xdest
, dc
->w
.DCOrgY
+ ydest
);
671 /**********************************************************************
672 * GRAPH_DrawReliefRect (Not a MSWin Call)
674 void GRAPH_DrawReliefRect( HDC hdc
, RECT
*rect
, int highlight_size
,
675 int shadow_size
, BOOL pressed
)
680 hbrushOld
= SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnShadow
:
681 sysColorObjects
.hbrushBtnHighlight
);
682 for (i
= 0; i
< highlight_size
; i
++)
684 PatBlt( hdc
, rect
->left
+ i
, rect
->top
,
685 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
686 PatBlt( hdc
, rect
->left
, rect
->top
+ i
,
687 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
690 SelectObject( hdc
, pressed
? sysColorObjects
.hbrushBtnHighlight
:
691 sysColorObjects
.hbrushBtnShadow
);
692 for (i
= 0; i
< shadow_size
; i
++)
694 PatBlt( hdc
, rect
->right
- i
- 1, rect
->top
+ i
,
695 1, rect
->bottom
- rect
->top
- i
, PATCOPY
);
696 PatBlt( hdc
, rect
->left
+ i
, rect
->bottom
- i
- 1,
697 rect
->right
- rect
->left
- i
, 1, PATCOPY
);
700 SelectObject( hdc
, hbrushOld
);
704 /**********************************************************************
707 BOOL
Polyline (HDC hdc
, LPPOINT pt
, int count
)
710 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
713 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
714 if (!dc
) return FALSE
;
715 MF_MetaPoly(dc
, META_POLYLINE
, pt
, count
);
719 if (DC_SetupGCForPen( dc
))
721 for (i
= 0; i
< count
-1; i
++)
722 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
723 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
].x
),
724 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
].y
),
725 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[i
+1].x
),
726 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[i
+1].y
));
727 XDrawLine (display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
728 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[count
-1].x
),
729 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[count
-1].y
),
730 dc
->w
.DCOrgX
+ XLPTODP(dc
, pt
[0].x
),
731 dc
->w
.DCOrgY
+ YLPTODP(dc
, pt
[0].y
));
738 /**********************************************************************
741 BOOL
Polygon (HDC hdc
, LPPOINT pt
, int count
)
744 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
745 XPoint
*points
= (XPoint
*) malloc (sizeof (XPoint
) * (count
+1));
749 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
750 if (!dc
) return FALSE
;
751 MF_MetaPoly(dc
, META_POLYGON
, pt
, count
);
755 for (i
= 0; i
< count
; i
++)
757 points
[i
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
[i
].x
);
758 points
[i
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
[i
].y
);
760 points
[count
] = points
[0];
762 if (DC_SetupGCForBrush( dc
))
763 XFillPolygon( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
764 points
, count
+1, Complex
, CoordModeOrigin
);
766 if (DC_SetupGCForPen ( dc
))
767 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
768 points
, count
+1, CoordModeOrigin
);
775 /**********************************************************************
776 * PolyPolygon (GDI.450)
778 BOOL
PolyPolygon( HDC hdc
, LPPOINT pt
, LPINT counts
, WORD polygons
)
781 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
785 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
786 if (!dc
) return FALSE
;
787 /* MF_MetaPoly(dc, META_POLYGON, pt, count); */
790 /* FIXME: The points should be converted to device coords before */
791 /* creating the region. But as CreatePolyPolygonRgn is not */
792 /* really correct either, it doesn't matter much... */
793 /* At least the outline will be correct :-) */
794 hrgn
= CreatePolyPolygonRgn( pt
, counts
, polygons
, dc
->w
.polyFillMode
);
795 PaintRgn( hdc
, hrgn
);
796 DeleteObject( hrgn
);
798 /* Draw the outline of the polygons */
800 if (DC_SetupGCForPen ( dc
))
805 for (i
= 0; i
< polygons
; i
++) if (counts
[i
] > max
) max
= counts
[i
];
806 points
= (XPoint
*) malloc( sizeof(XPoint
) * (max
+1) );
808 for (i
= 0; i
< polygons
; i
++)
810 for (j
= 0; j
< counts
[i
]; j
++)
812 points
[j
].x
= dc
->w
.DCOrgX
+ XLPTODP( dc
, pt
->x
);
813 points
[j
].y
= dc
->w
.DCOrgY
+ YLPTODP( dc
, pt
->y
);
816 points
[j
] = points
[0];
817 XDrawLines( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
818 points
, j
+ 1, CoordModeOrigin
);
826 /**********************************************************************
827 * GRAPH_InternalFloodFill
829 * Internal helper function for flood fill.
830 * (xorg,yorg) is the origin of the X image relative to the drawable.
831 * (x,y) is relative to the origin of the X image.
833 static void GRAPH_InternalFloodFill( XImage
*image
, DC
*dc
,
836 Pixel pixel
, WORD fillType
)
840 #define TO_FLOOD(x,y) ((fillType == FLOODFILLBORDER) ? \
841 (XGetPixel(image,x,y) != pixel) : \
842 (XGetPixel(image,x,y) == pixel))
844 if (!TO_FLOOD(x
,y
)) return;
846 /* Find left and right boundaries */
849 while ((left
> 0) && TO_FLOOD( left
-1, y
)) left
--;
850 while ((right
< image
->width
) && TO_FLOOD( right
, y
)) right
++;
851 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
852 xOrg
+ left
, yOrg
+ y
, right
-left
, 1 );
854 /* Set the pixels of this line so we don't fill it again */
856 for (x
= left
; x
< right
; x
++)
858 if (fillType
== FLOODFILLBORDER
) XPutPixel( image
, x
, y
, pixel
);
859 else XPutPixel( image
, x
, y
, ~pixel
);
862 /* Fill the line above */
869 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
870 if (x
>= right
) break;
871 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
872 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
873 xOrg
, yOrg
, pixel
, fillType
);
877 /* Fill the line below */
879 if ((y
+= 2) < image
->height
)
884 while ((x
< right
) && !TO_FLOOD(x
,y
)) x
++;
885 if (x
>= right
) break;
886 while ((x
< right
) && TO_FLOOD(x
,y
)) x
++;
887 GRAPH_InternalFloodFill( image
, dc
, x
-1, y
,
888 xOrg
, yOrg
, pixel
, fillType
);
895 /**********************************************************************
896 * ExtFloodFill (GDI.372)
898 BOOL
ExtFloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
, WORD fillType
)
905 dprintf_graphics( stddeb
, "ExtFloodFill %x %d,%d %06lx %d\n",
906 hdc
, x
, y
, color
, fillType
);
907 dc
= (DC
*) GDI_GetObjPtr(hdc
, DC_MAGIC
);
910 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
911 if (!dc
) return FALSE
;
912 MF_MetaParam4(dc
, META_FLOODFILL
, x
, y
, HIWORD(color
),
917 if (!PtVisible( hdc
, x
, y
)) return FALSE
;
918 if (GetClipBox( hdc
, &rect
) == ERROR
) return FALSE
;
919 pixel
= COLOR_ToPhysical( dc
, color
);
921 if (!(image
= XGetImage( display
, dc
->u
.x
.drawable
,
922 dc
->w
.DCOrgX
+ rect
.left
, dc
->w
.DCOrgY
+ rect
.top
,
923 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
924 AllPlanes
, ZPixmap
))) return FALSE
;
926 if (DC_SetupGCForBrush( dc
))
928 /* ROP mode is always GXcopy for flood-fill */
929 XSetFunction( display
, dc
->u
.x
.gc
, GXcopy
);
930 /* We can pass anything except 0 as a region */
931 GRAPH_InternalFloodFill( image
, dc
,
932 XLPTODP(dc
,x
) - rect
.left
,
933 YLPTODP(dc
,y
) - rect
.top
,
934 dc
->w
.DCOrgX
+ rect
.left
,
935 dc
->w
.DCOrgY
+ rect
.top
,
939 XDestroyImage( image
);
944 /**********************************************************************
947 BOOL
FloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
)
949 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);