1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing parameters.
16 Therefore, it is impossible to independently maintain the current pen and the
17 current brush. Also, some settings depend on the current logical function. The
18 m_currentFill, etc. instance variables remember state across the brush and
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
52 #pragma message disable nosimpint
56 #pragma message enable nosimpint
59 #include "wx/motif/private.h"
62 #include <float.h> // for M_PI
72 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 #define RAD2DEG 57.2957795131
80 // Fudge factor (VZ: what??)
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 #if !USE_SHARED_LIBRARY
88 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
89 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
90 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
98 Drawable src
, Drawable dest
,
101 unsigned int w
, unsigned int h
,
102 int destx
, int desty
,
103 bool more
, XImage
**cache
);
105 // ============================================================================
107 // ============================================================================
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
113 wxWindowDC::wxWindowDC()
116 m_gcBacking
= (WXGC
) 0;
118 m_backgroundPixel
= -1;
119 m_currentPenWidth
= 1;
120 m_currentPenJoin
= -1;
121 m_currentPenDashCount
= -1;
122 m_currentPenDash
= (char*) NULL
;
125 // m_currentBkMode = wxTRANSPARENT;
126 m_colour
= wxColourDisplay();
127 m_display
= (WXDisplay
*) NULL
;
128 m_currentRegion
= (WXRegion
) 0;
129 m_userRegion
= (WXRegion
) 0;
130 m_pixmap
= (WXPixmap
) 0;
132 m_oldFont
= (WXFont
) 0;
135 wxWindowDC::wxWindowDC( wxWindow
*window
)
137 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
140 m_font
= window
->GetFont();
142 m_gcBacking
= (WXGC
) 0;
143 m_backgroundPixel
= -1;
144 m_currentPenWidth
= 1;
145 m_currentPenJoin
= -1;
146 m_currentPenDashCount
= -1;
147 m_currentPenDash
= (char*) NULL
;
150 // m_currentBkMode = wxTRANSPARENT;
151 m_colour
= wxColourDisplay();
152 m_currentRegion
= (WXRegion
) 0;
153 m_userRegion
= (WXRegion
) 0;
157 m_display
= window
->GetXDisplay();
158 m_pixmap
= window
->GetXWindow();
159 Display
* display
= (Display
*) m_display
;
161 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
164 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
165 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
166 gcvalues
.graphics_exposures
= False
;
167 gcvalues
.line_width
= 1;
168 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
169 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
172 if (m_window
->GetBackingPixmap())
174 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
175 DefaultScreen (display
)),
176 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
180 m_backgroundPixel
= (int) gcvalues
.background
;
182 // Get the current Font so we can set it back later
184 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
185 m_oldFont
= (WXFont
) valReturn
.font
;
187 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
190 wxWindowDC::~wxWindowDC()
192 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
194 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
196 if (m_window
&& m_window
->GetBackingPixmap())
197 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
201 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
205 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
206 m_gcBacking
= (WXGC
) 0;
209 XDestroyRegion ((Region
) m_currentRegion
);
210 m_currentRegion
= (WXRegion
) 0;
213 XDestroyRegion ((Region
) m_userRegion
);
214 m_userRegion
= (WXRegion
) 0;
217 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
218 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
220 wxFAIL_MSG("not implemented");
223 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
225 wxFAIL_MSG("not implemented");
230 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
232 wxCHECK_RET( Ok(), "invalid dc" );
234 int x1d
, y1d
, x2d
, y2d
;
236 // FreeGetPixelCache();
246 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
248 if (m_window
&& m_window
->GetBackingPixmap())
249 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
250 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
251 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
253 CalcBoundingBox(x1
, y1
);
254 CalcBoundingBox(x2
, y2
);
257 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
259 wxCHECK_RET( Ok(), "invalid dc" );
264 int xx
= XLOG2DEV (x
);
265 int yy
= YLOG2DEV (y
);
267 wxDisplaySize (&ww
, &hh
);
268 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
270 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
273 if (m_window
&& m_window
->GetBackingPixmap())
277 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
280 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
286 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
288 wxCHECK_RET( Ok(), "invalid dc" );
290 // FreeGetPixelCache();
292 int xx1
= XLOG2DEV (x1
);
293 int yy1
= YLOG2DEV (y1
);
294 int xx2
= XLOG2DEV (x2
);
295 int yy2
= YLOG2DEV (y2
);
296 int xxc
= XLOG2DEV (xc
);
297 int yyc
= YLOG2DEV (yc
);
298 int xxc_2
= XLOG2DEV_2 (xc
);
299 int yyc_2
= YLOG2DEV_2 (yc
);
301 wxCoord dx
= xx1
- xxc
;
302 wxCoord dy
= yy1
- yyc
;
303 double radius
= sqrt (dx
* dx
+ dy
* dy
);
304 wxCoord r
= (wxCoord
) radius
;
306 double radius1
, radius2
;
308 if (xx1
== xx2
&& yy1
== yy2
)
313 else if (radius
== 0.0)
314 radius1
= radius2
= 0.0;
323 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
331 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
335 int alpha1
= (int) radius1
;
336 int alpha2
= (int) (radius2
- radius1
);
339 while (alpha2
> 360 * 64)
342 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
345 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
346 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
348 if (m_window
&& m_window
->GetBackingPixmap())
349 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
350 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
354 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
358 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
359 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
361 if (m_window
&& m_window
->GetBackingPixmap())
362 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
363 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
365 CalcBoundingBox (x1
, y1
);
366 CalcBoundingBox (x2
, y2
);
369 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
371 wxCHECK_RET( Ok(), "invalid dc" );
377 wd
= XLOG2DEVREL(width
);
378 hd
= YLOG2DEVREL(height
);
380 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
381 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
382 int start
= int(sa
*64);
383 int end
= int(ea
*64);
384 if (start
<0) start
+=360*64;
385 if (end
<0) end
+=360*64;
386 if (end
>start
) end
-=start
;
387 else end
+=360*64-start
;
389 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
391 m_autoSetting
= TRUE
; // must be reset
394 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
396 if (m_window
&& m_window
->GetBackingPixmap())
397 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
398 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
401 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
405 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
406 if (m_window
&& m_window
->GetBackingPixmap())
407 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
408 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
410 CalcBoundingBox (x
, y
);
411 CalcBoundingBox (x
+ width
, y
+ height
);
414 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
416 wxCHECK_RET( Ok(), "invalid dc" );
418 // FreeGetPixelCache();
420 if (m_pen
.Ok() && m_autoSetting
)
423 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
424 if (m_window
&& m_window
->GetBackingPixmap())
425 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
427 CalcBoundingBox (x
, y
);
430 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
432 wxCHECK_RET( Ok(), "invalid dc" );
434 // FreeGetPixelCache();
436 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
441 XPoint
*xpoints
= new XPoint
[n
];
444 for (i
= 0; i
< n
; i
++)
446 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
447 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
449 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
451 if (m_window
&& m_window
->GetBackingPixmap())
453 for (i
= 0; i
< n
; i
++)
455 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
456 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
458 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
464 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
465 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
467 wxCHECK_RET( Ok(), "invalid dc" );
469 // FreeGetPixelCache();
471 XPoint
*xpoints1
= new XPoint
[n
+ 1];
472 XPoint
*xpoints2
= new XPoint
[n
+ 1];
474 for (i
= 0; i
< n
; i
++)
476 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
477 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
478 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
479 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
480 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
483 // Close figure for XDrawLines (not needed for XFillPolygon)
484 xpoints1
[i
].x
= xpoints1
[0].x
;
485 xpoints1
[i
].y
= xpoints1
[0].y
;
486 xpoints2
[i
].x
= xpoints2
[0].x
;
487 xpoints2
[i
].y
= xpoints2
[0].y
;
489 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
492 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
493 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
494 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
495 if (m_window
&& m_window
->GetBackingPixmap())
497 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
498 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
499 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
500 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
504 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
508 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
510 if (m_window
&& m_window
->GetBackingPixmap())
511 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
518 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
520 wxCHECK_RET( Ok(), "invalid dc" );
522 // FreeGetPixelCache();
524 int xd
, yd
, wfd
, hfd
, wd
, hd
;
528 wfd
= XLOG2DEVREL(width
);
530 hfd
= YLOG2DEVREL(height
);
533 if (wfd
== 0 || hfd
== 0) return;
534 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
535 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
537 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
540 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
542 if (m_window
&& m_window
->GetBackingPixmap())
543 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
544 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
548 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
552 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
554 if (m_window
&& m_window
->GetBackingPixmap())
555 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
556 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
559 CalcBoundingBox (x
, y
);
560 CalcBoundingBox (x
+ width
, y
+ height
);
563 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
565 wxCHECK_RET( Ok(), "invalid dc" );
567 // FreeGetPixelCache();
569 // If radius is negative, it's a proportion of the smaller dimension.
571 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
573 int xd
= XLOG2DEV (x
);
574 int yd
= YLOG2DEV (y
);
575 int rd
= XLOG2DEVREL ((long) radius
);
576 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
577 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
582 // If radius is zero use DrawRectangle() instead to avoid
583 // X drawing errors with small radii
586 DrawRectangle( x
, y
, width
, height
);
590 // Draw nothing if transformed w or h is 0
591 if (wd
== 0 || hd
== 0) return;
593 // CMB: adjust size if outline is drawn otherwise the result is
594 // 1 pixel too wide and high
595 if (m_pen
.GetStyle() != wxTRANSPARENT
)
601 // CMB: ensure dd is not larger than rectangle otherwise we
602 // get an hour glass shape
603 if (rw_d
> wd
) rw_d
= wd
;
604 if (rw_d
> hd
) rw_d
= hd
;
607 // For backing pixmap
608 int xd2
= XLOG2DEV_2 (x
);
609 int yd2
= YLOG2DEV_2 (y
);
610 int rd2
= XLOG2DEVREL ((long) radius
);
611 int wd2
= XLOG2DEVREL (width
) ;
612 int hd2
= YLOG2DEVREL (height
) ;
617 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
621 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
623 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
626 // Arcs start from 3 o'clock, positive angles anticlockwise
628 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
629 rw_d
, rh_d
, 90 * 64, 90 * 64);
631 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
632 // rw_d, rh_d, 0, 90 * 64);
633 rw_d
, rh_d
, 0, 91 * 64);
635 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
637 // rw_d, rh_d, 270 * 64, 90 * 64);
638 rw_d
, rh_d
, 269 * 64, 92 * 64);
640 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
641 rw_d
, rh_d
, 180 * 64, 90 * 64);
643 if (m_window
&& m_window
->GetBackingPixmap())
645 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
646 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
647 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
648 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
651 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
652 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
653 xd2
+ wd2
- rw_d2
, yd2
,
654 // rw_d2, rh_d2, 0, 90 * 64);
655 rw_d2
, rh_d2
, 0, 91 * 64);
656 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
659 // rw_d2, rh_d2, 270 * 64, 90 * 64);
660 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
661 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
662 xd2
, yd2
+ hd2
- rh_d2
,
663 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
667 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
670 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
671 xd
+ wd
- rd
+ 1, yd
);
672 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
673 xd
+ wd
- rd
, yd
+ hd
);
675 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
677 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
678 xd
+ wd
, yd
+ hd
- rd
+ 1);
679 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
680 rw_d
, rh_d
, 90 * 64, 90 * 64);
681 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
682 // rw_d, rh_d, 0, 90 * 64);
683 rw_d
, rh_d
, 0, 91 * 64);
684 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
686 rw_d
, rh_d
, 269 * 64, 92 * 64);
687 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
688 rw_d
, rh_d
, 180 * 64, 90 * 64);
690 if (m_window
&& m_window
->GetBackingPixmap())
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
694 xd2
+ wd2
- rd2
+ 1, yd2
);
695 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
696 xd2
+ rd2
, yd2
+ hd2
,
697 xd2
+ wd2
- rd2
, yd2
+ hd2
);
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
701 xd2
, yd2
+ hd2
- rd2
);
702 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
703 xd2
+ wd2
, yd2
+ rd2
,
704 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
705 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
707 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
708 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
709 xd2
+ wd2
- rw_d2
, yd2
,
710 // rw_d2, rh_d2, 0, 90 * 64);
711 rw_d2
, rh_d2
, 0, 91 * 64);
712 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
715 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
716 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
717 xd2
, yd2
+ hd2
- rh_d2
,
718 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
721 CalcBoundingBox (x
, y
);
722 CalcBoundingBox (x
+ width
, y
+ height
);
727 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
729 wxCHECK_RET( Ok(), "invalid dc" );
731 // Check for negative width and height
744 // FreeGetPixelCache();
746 static const int angle
= 23040;
752 wd
= XLOG2DEVREL(width
) ;
753 hd
= YLOG2DEVREL(height
) ;
755 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
758 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
759 if (m_window
&& m_window
->GetBackingPixmap())
760 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
761 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
762 XLOG2DEVREL (width
) - WX_GC_CF
,
763 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
766 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
770 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
771 if (m_window
&& m_window
->GetBackingPixmap())
772 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
773 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
774 XLOG2DEVREL (width
) - WX_GC_CF
,
775 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
777 CalcBoundingBox (x
, y
);
778 CalcBoundingBox (x
+ width
, y
+ height
);
782 bool wxWindowDC::CanDrawBitmap() const
784 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
790 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
792 // FreeGetPixelCache();
794 // Be sure that foreground pixels (1) of
795 // the Icon will be painted with pen colour. [m_pen.SetColour()]
796 // Background pixels (0) will be painted with
797 // last selected background color. [::SetBackground]
798 if (m_pen
.Ok() && m_autoSetting
)
802 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
803 width
= icon
.GetWidth();
804 height
= icon
.GetHeight();
805 if (icon
.GetDisplay() == m_display
)
807 if (icon
.GetDepth() <= 1)
809 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
811 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
815 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
817 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
821 if (m_window
&& m_window
->GetBackingPixmap())
823 if (icon
.GetDepth() <= 1)
825 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
826 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
830 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
832 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
835 } else { /* Remote copy (different (Display*) m_displays) */
836 XImage
*cache
= NULL
;
837 if (m_window
&& m_window
->GetBackingPixmap())
838 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
839 (GC
) m_gcBacking
, 0, 0, width
, height
,
840 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
841 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
843 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
845 CalcBoundingBox (x
, y
);
849 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
850 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
851 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
853 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
855 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
857 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
859 // FreeGetPixelCache();
861 // Be sure that foreground pixels (1) of the Icon will be painted with pen
862 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
863 // last selected background color. [::SetBackground]
864 if (m_pen
.Ok() && m_autoSetting
)
867 // Do bitmap scaling if necessary
869 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
870 Pixmap sourcePixmap
= (Pixmap
) NULL
;
871 double scaleX
, scaleY
;
872 GetUserScale(& scaleX
, & scaleY
);
874 // Sorry, can't scale masks just yet
875 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
877 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
878 wxBitmap
& bitmap
= memDC
->GetBitmap();
880 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
882 wxImage
image(bitmap
);
885 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
889 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
890 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
892 image
= image
.Scale(scaledW
, scaledH
);
893 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
894 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
898 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
900 if (m_pixmap
&& sourcePixmap
)
903 int orig
= m_logicalFunction
;
905 SetLogicalFunction (rop
);
907 if (m_display
!= sourceDC
->m_display
)
909 XImage
*cache
= NULL
;
911 if (m_window
&& m_window
->GetBackingPixmap())
912 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
913 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
915 source
->LogicalToDeviceX (xsrc
),
916 source
->LogicalToDeviceY (ysrc
),
917 source
->LogicalToDeviceXRel(width
),
918 source
->LogicalToDeviceYRel(height
),
919 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
922 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
924 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
925 wxBitmap
& sel
= memDC
->GetBitmap();
926 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
928 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
929 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
933 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
934 source
->LogicalToDeviceX (xsrc
),
935 source
->LogicalToDeviceY (ysrc
),
936 source
->LogicalToDeviceXRel(width
),
937 source
->LogicalToDeviceYRel(height
),
938 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
943 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
944 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
949 if (m_window
&& m_window
->GetBackingPixmap())
951 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
952 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
954 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
955 source
->LogicalToDeviceX (xsrc
),
956 source
->LogicalToDeviceY (ysrc
),
957 source
->LogicalToDeviceXRel(width
),
958 source
->LogicalToDeviceYRel(height
),
959 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
963 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
964 source
->LogicalToDeviceX (xsrc
),
965 source
->LogicalToDeviceY (ysrc
),
966 source
->LogicalToDeviceXRel(width
),
967 source
->LogicalToDeviceYRel(height
),
968 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
971 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
973 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
974 wxBitmap
& sel
= memDC
->GetBitmap();
975 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
977 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
978 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
982 // Check if we're copying from a mono bitmap
983 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
984 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
986 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
987 source
->LogicalToDeviceX (xsrc
),
988 source
->LogicalToDeviceY (ysrc
),
989 source
->LogicalToDeviceXRel(width
),
990 source
->LogicalToDeviceYRel(height
),
991 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
995 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
996 source
->LogicalToDeviceX (xsrc
),
997 source
->LogicalToDeviceY (ysrc
),
998 source
->LogicalToDeviceXRel(width
),
999 source
->LogicalToDeviceYRel(height
),
1000 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1005 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1006 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1009 } /* Remote/local (Display*) m_display */
1010 CalcBoundingBox (xdest
, ydest
);
1011 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1013 SetLogicalFunction(orig
);
1015 if (scaledBitmap
) delete scaledBitmap
;
1019 if (scaledBitmap
) delete scaledBitmap
;
1024 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1026 wxCHECK_RET( Ok(), "invalid dc" );
1028 // Since X draws from the baseline of the text, must add the text height
1034 slen
= strlen(text
);
1038 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1039 int direction
, descent
;
1040 XCharStruct overall_return
;
1043 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1044 &ascent
, &descent
, &overall_return
);
1047 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1048 &ascent
, &descent
, &overall_return
);
1050 cx
= overall_return
.width
;
1051 cy
= ascent
+ descent
;
1054 // First draw a rectangle representing the text background, if a text
1055 // background is specified
1056 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1058 wxColour oldPenColour
= m_currentColour
;
1059 m_currentColour
= m_textBackgroundColour
;
1060 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1061 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1062 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1063 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1065 // This separation of the big && test required for gcc2.7/HP UX 9.02
1066 // or pixel value can be corrupted!
1067 sameColour
= (sameColour
&&
1068 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1070 if (!sameColour
|| !GetOptimization())
1072 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1073 m_currentColour
= m_textBackgroundColour
;
1075 // Set the GC to the required colour
1078 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1079 if (m_window
&& m_window
->GetBackingPixmap())
1080 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1084 m_textBackgroundColour
= oldPenColour
;
1086 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1087 if (m_window
&& m_window
->GetBackingPixmap())
1088 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1089 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1092 // Now set the text foreground and draw the text
1093 if (m_textForegroundColour
.Ok ())
1095 wxColour oldPenColour
= m_currentColour
;
1096 m_currentColour
= m_textForegroundColour
;
1097 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1098 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1099 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1100 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1101 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1103 if (!sameColour
|| !GetOptimization())
1106 if (!m_colour
) // Mono display
1108 // Unless foreground is really white, draw it in black
1109 unsigned char red
= m_textForegroundColour
.Red ();
1110 unsigned char blue
= m_textForegroundColour
.Blue ();
1111 unsigned char green
= m_textForegroundColour
.Green ();
1112 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1113 && green
== (unsigned char) 255)
1115 m_currentColour
= *wxWHITE
;
1116 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1117 m_currentColour
.SetPixel(pixel
);
1118 m_textForegroundColour
.SetPixel(pixel
);
1122 m_currentColour
= *wxBLACK
;
1123 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1124 m_currentColour
.SetPixel(pixel
);
1125 m_textForegroundColour
.SetPixel(pixel
);
1130 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1131 m_currentColour
.SetPixel(pixel
);
1134 // Set the GC to the required colour
1137 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1138 if (m_window
&& m_window
->GetBackingPixmap())
1139 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1143 m_textForegroundColour
= oldPenColour
;
1146 // We need to add the ascent, not the whole height, since X draws at the
1147 // point above the descender.
1150 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1151 (XChar2b
*)(char*) (const char*) text
, slen
);
1154 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1156 if (m_window
&& m_window
->GetBackingPixmap()) {
1159 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1160 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1161 (XChar2b
*)(char*) (const char*) text
, slen
);
1164 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1165 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1169 GetTextExtent (text
, &w
, &h
);
1170 CalcBoundingBox (x
+ w
, y
+ h
);
1171 CalcBoundingBox (x
, y
);
1174 bool wxWindowDC::CanGetTextExtent() const
1179 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1180 wxCoord
*descent
, wxCoord
*externalLeading
,
1181 wxFont
*font
) const
1183 wxCHECK_RET( Ok(), "invalid dc" );
1185 wxFont
* theFont
= font
;
1187 theFont
= (wxFont
*)&m_font
; // const_cast
1191 // TODO: this should be an error log function
1192 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1194 if (width
) *width
= -1;
1195 if (height
) *height
= -1;
1199 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1201 int direction
, ascent
, descent2
;
1202 XCharStruct overall
;
1207 slen
= str16len(string
);
1210 slen
= strlen(string
);
1214 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1215 &ascent
, &descent2
, &overall
);
1218 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1219 &ascent
, &descent2
, &overall
);
1221 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1222 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1224 *descent
= descent2
;
1225 if (externalLeading
)
1226 *externalLeading
= 0;
1229 wxCoord
wxWindowDC::GetCharWidth() const
1231 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1232 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1234 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1236 int direction
, ascent
, descent
;
1237 XCharStruct overall
;
1238 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1239 &descent
, &overall
);
1240 return XDEV2LOGREL(overall
.width
);
1243 wxCoord
wxWindowDC::GetCharHeight() const
1245 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1246 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1248 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1250 int direction
, ascent
, descent
;
1251 XCharStruct overall
;
1252 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1253 &descent
, &overall
);
1254 // return XDEV2LOGREL(overall.ascent + overall.descent);
1255 return XDEV2LOGREL(ascent
+ descent
);
1258 void wxWindowDC::Clear()
1260 wxCHECK_RET( Ok(), "invalid dc" );
1265 m_window
->GetSize(&w
, &h
);
1267 if (m_window
&& m_window
->GetBackingPixmap())
1269 w
= m_window
->GetPixmapWidth();
1270 h
= m_window
->GetPixmapHeight();
1275 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1277 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1278 w
= memDC
->GetBitmap().GetWidth();
1279 h
= memDC
->GetBitmap().GetHeight();
1285 wxBrush saveBrush
= m_brush
;
1286 SetBrush (m_backgroundBrush
);
1288 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1290 if (m_window
&& m_window
->GetBackingPixmap())
1291 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1293 m_brush
= saveBrush
;
1296 void wxWindowDC::Clear(const wxRect
& rect
)
1298 wxCHECK_RET( Ok(), "invalid dc" );
1300 int x
= rect
.x
; int y
= rect
.y
;
1301 int w
= rect
.width
; int h
= rect
.height
;
1303 wxBrush saveBrush
= m_brush
;
1304 SetBrush (m_backgroundBrush
);
1306 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1308 if (m_window
&& m_window
->GetBackingPixmap())
1309 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1311 m_brush
= saveBrush
;
1314 void wxWindowDC::SetFont( const wxFont
&font
)
1316 wxCHECK_RET( Ok(), "invalid dc" );
1322 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1324 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1326 if (m_window
&& m_window
->GetBackingPixmap())
1327 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1332 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1334 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1335 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1337 if (m_window
&& m_window
->GetBackingPixmap())
1338 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1341 void wxWindowDC::SetPen( const wxPen
&pen
)
1343 wxCHECK_RET( Ok(), "invalid dc" );
1349 wxBitmap oldStipple
= m_currentStipple
;
1350 int oldStyle
= m_currentStyle
;
1351 int oldFill
= m_currentFill
;
1352 int old_pen_width
= m_currentPenWidth
;
1353 int old_pen_join
= m_currentPenJoin
;
1354 int old_pen_cap
= m_currentPenCap
;
1355 int old_pen_nb_dash
= m_currentPenDashCount
;
1356 char *old_pen_dash
= m_currentPenDash
;
1358 wxColour oldPenColour
= m_currentColour
;
1359 m_currentColour
= m_pen
.GetColour ();
1360 m_currentStyle
= m_pen
.GetStyle ();
1361 m_currentFill
= m_pen
.GetStyle (); // TODO?
1362 m_currentPenWidth
= m_pen
.GetWidth ();
1363 m_currentPenJoin
= m_pen
.GetJoin ();
1364 m_currentPenCap
= m_pen
.GetCap ();
1365 m_currentPenDashCount
= m_pen
.GetDashCount();
1366 m_currentPenDash
= m_pen
.GetDash();
1368 if (m_currentStyle
== wxSTIPPLE
)
1369 m_currentStipple
= * m_pen
.GetStipple ();
1371 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1372 oldFill
== m_currentFill
&&
1373 old_pen_join
== m_currentPenJoin
&&
1374 old_pen_cap
== m_currentPenCap
&&
1375 old_pen_nb_dash
== m_currentPenDashCount
&&
1376 old_pen_dash
== m_currentPenDash
&&
1377 old_pen_width
== m_currentPenWidth
);
1379 bool sameColour
= (oldPenColour
.Ok () &&
1380 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1381 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1382 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1383 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1385 if (!sameStyle
|| !GetOptimization())
1387 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1388 if (scaled_width
< 0)
1394 static const char dotted
[] = {2, 5};
1395 static const char short_dashed
[] = {4, 4};
1396 static const char long_dashed
[] = {4, 8};
1397 static const char dotted_dashed
[] = {6, 6, 2, 6};
1399 // We express dash pattern in pen width unit, so we are
1400 // independent of zoom factor and so on...
1402 const char *req_dash
;
1404 switch (m_pen
.GetStyle ())
1407 req_nb_dash
= m_currentPenDashCount
;
1408 req_dash
= m_currentPenDash
;
1409 style
= LineOnOffDash
;
1414 style
= LineOnOffDash
;
1418 req_dash
= short_dashed
;
1419 style
= LineOnOffDash
;
1423 req_dash
= long_dashed
;
1424 style
= LineOnOffDash
;
1428 req_dash
= dotted_dashed
;
1429 style
= LineOnOffDash
;
1440 if (req_dash
&& req_nb_dash
)
1442 char *real_req_dash
= new char[req_nb_dash
];
1445 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1446 for (int i
= 0; i
< req_nb_dash
; i
++)
1447 real_req_dash
[i
] = req_dash
[i
] * factor
;
1448 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1450 if (m_window
&& m_window
->GetBackingPixmap())
1451 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1452 delete[]real_req_dash
;
1456 // No Memory. We use non-scaled dash pattern...
1457 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1459 if (m_window
&& m_window
->GetBackingPixmap())
1460 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1464 switch (m_pen
.GetCap ())
1466 case wxCAP_PROJECTING
:
1467 cap
= CapProjecting
;
1474 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1478 switch (m_pen
.GetJoin ())
1492 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1494 if (m_window
&& m_window
->GetBackingPixmap())
1495 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1498 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1502 oldStipple
= wxNullBitmap
; // For later reset!!
1504 switch (m_currentFill
)
1506 case wxBDIAGONAL_HATCH
:
1507 if (bdiag
== (Pixmap
) 0)
1508 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1509 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1510 bdiag_bits
, bdiag_width
, bdiag_height
);
1513 case wxFDIAGONAL_HATCH
:
1514 if (fdiag
== (Pixmap
) 0)
1515 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1516 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1517 fdiag_bits
, fdiag_width
, fdiag_height
);
1521 if (cross
== (Pixmap
) 0)
1522 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1523 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1524 cross_bits
, cross_width
, cross_height
);
1527 case wxHORIZONTAL_HATCH
:
1528 if (horiz
== (Pixmap
) 0)
1529 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1530 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1531 horiz_bits
, horiz_width
, horiz_height
);
1534 case wxVERTICAL_HATCH
:
1535 if (verti
== (Pixmap
) 0)
1536 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1537 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1538 verti_bits
, verti_width
, verti_height
);
1541 case wxCROSSDIAG_HATCH
:
1543 if (cdiag
== (Pixmap
) 0)
1544 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1545 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1546 cdiag_bits
, cdiag_width
, cdiag_height
);
1550 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1552 if (m_window
&& m_window
->GetBackingPixmap())
1553 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1555 else if (m_currentStipple
.Ok()
1556 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1558 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1560 if (m_window
&& m_window
->GetBackingPixmap())
1561 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1564 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1568 if (m_currentFill
== wxSTIPPLE
)
1569 fill_style
= FillStippled
;
1570 else if (IS_HATCH (m_currentFill
))
1571 fill_style
= FillStippled
;
1573 fill_style
= FillSolid
;
1574 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1575 if (m_window
&& m_window
->GetBackingPixmap())
1576 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1579 // must test m_logicalFunction, because it involves background!
1580 if (!sameColour
|| !GetOptimization()
1581 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1584 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1585 pixel
= m_backgroundPixel
;
1588 unsigned char red
= m_pen
.GetColour ().Red ();
1589 unsigned char blue
= m_pen
.GetColour ().Blue ();
1590 unsigned char green
= m_pen
.GetColour ().Green ();
1591 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1592 && green
== (unsigned char) 255)
1594 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1595 m_currentColour
= *wxWHITE
;
1596 m_pen
.GetColour().SetPixel(pixel
);
1597 m_currentColour
.SetPixel(pixel
);
1601 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1602 m_currentColour
= *wxBLACK
;
1603 m_pen
.GetColour().SetPixel(pixel
);
1608 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1609 m_currentColour
.SetPixel(pixel
);
1612 // Finally, set the GC to the required colour
1615 if (m_logicalFunction
== wxXOR
)
1618 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1619 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1620 if (m_window
&& m_window
->GetBackingPixmap())
1621 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1625 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1626 if (m_window
&& m_window
->GetBackingPixmap())
1627 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1632 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1637 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1639 wxCHECK_RET( Ok(), "invalid dc" );
1643 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1646 int oldFill
= m_currentFill
;
1647 wxBitmap oldStipple
= m_currentStipple
;
1649 m_autoSetting
|= 0x1;
1651 m_currentFill
= m_brush
.GetStyle ();
1652 if (m_currentFill
== wxSTIPPLE
)
1653 m_currentStipple
= * m_brush
.GetStipple ();
1655 wxColour
oldBrushColour(m_currentColour
);
1656 m_currentColour
= m_brush
.GetColour ();
1658 bool sameColour
= (oldBrushColour
.Ok () &&
1659 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1660 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1661 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1662 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1664 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1666 switch (brush
.GetStyle ())
1670 case wxBDIAGONAL_HATCH
:
1671 case wxCROSSDIAG_HATCH
:
1672 case wxFDIAGONAL_HATCH
:
1674 case wxHORIZONTAL_HATCH
:
1675 case wxVERTICAL_HATCH
:
1678 // Chris Breeze 23/07/97: use background mode to determine whether
1679 // fill style should be solid or transparent
1680 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1681 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1682 if (m_window
&& m_window
->GetBackingPixmap())
1683 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1688 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1689 if (m_window
&& m_window
->GetBackingPixmap())
1690 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1694 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1698 switch (m_currentFill
)
1700 case wxBDIAGONAL_HATCH
:
1701 if (bdiag
== (Pixmap
) 0)
1702 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1703 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1704 bdiag_bits
, bdiag_width
, bdiag_height
);
1707 case wxFDIAGONAL_HATCH
:
1708 if (fdiag
== (Pixmap
) 0)
1709 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1710 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1711 fdiag_bits
, fdiag_width
, fdiag_height
);
1715 if (cross
== (Pixmap
) 0)
1716 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1717 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1718 cross_bits
, cross_width
, cross_height
);
1721 case wxHORIZONTAL_HATCH
:
1722 if (horiz
== (Pixmap
) 0)
1723 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1724 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1725 horiz_bits
, horiz_width
, horiz_height
);
1728 case wxVERTICAL_HATCH
:
1729 if (verti
== (Pixmap
) 0)
1730 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1731 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1732 verti_bits
, verti_width
, verti_height
);
1735 case wxCROSSDIAG_HATCH
:
1737 if (cdiag
== (Pixmap
) 0)
1738 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1739 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1740 cdiag_bits
, cdiag_width
, cdiag_height
);
1744 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1746 if (m_window
&& m_window
->GetBackingPixmap())
1747 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1749 // X can forget the stipple value when resizing a window (apparently)
1750 // so always set the stipple.
1751 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1753 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1754 if (m_window
&& m_window
->GetBackingPixmap())
1755 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1758 // must test m_logicalFunction, because it involves background!
1759 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1764 // Policy - on a monochrome screen, all brushes are white,
1765 // except when they're REALLY black!!!
1766 unsigned char red
= m_brush
.GetColour ().Red ();
1767 unsigned char blue
= m_brush
.GetColour ().Blue ();
1768 unsigned char green
= m_brush
.GetColour ().Green ();
1770 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1771 && green
== (unsigned char) 0)
1773 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1774 m_currentColour
= *wxBLACK
;
1775 m_brush
.GetColour().SetPixel(pixel
);
1776 m_currentColour
.SetPixel(pixel
);
1780 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1781 m_currentColour
= *wxWHITE
;
1782 m_brush
.GetColour().SetPixel(pixel
);
1783 m_currentColour
.SetPixel(pixel
);
1786 // N.B. comment out the above line and uncomment the following lines
1787 // if you want non-white colours to be black on a monochrome display.
1789 if (red == (unsigned char )255 && blue == (unsigned char)255
1790 && green == (unsigned char)255)
1791 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1793 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1796 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1798 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1799 m_currentColour
.SetPixel(pixel
);
1803 // Finally, set the GC to the required colour
1804 if (m_logicalFunction
== wxXOR
)
1807 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1808 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1809 if (m_window
&& m_window
->GetBackingPixmap())
1810 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1814 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1815 if (m_window
&& m_window
->GetBackingPixmap())
1816 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1821 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1824 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1826 wxCHECK_RET( Ok(), "invalid dc" );
1828 m_backgroundBrush
= brush
;
1830 if (!m_backgroundBrush
.Ok())
1833 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1835 // New behaviour, 10/2/99: setting the background brush of a DC
1836 // doesn't affect the window background colour.
1838 // XSetWindowBackground doesn't work for non-Window pixmaps
1839 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1840 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1843 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1844 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1845 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1846 if (m_window
&& m_window
->GetBackingPixmap())
1847 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1850 void wxWindowDC::SetLogicalFunction( int function
)
1852 wxCHECK_RET( Ok(), "invalid dc" );
1857 if (m_logicalFunction
== function
)
1863 x_function
= GXclear
;
1869 x_function
= GXinvert
;
1872 x_function
= GXorReverse
;
1875 x_function
= GXandReverse
;
1884 x_function
= GXandInverted
;
1887 x_function
= GXnoop
;
1893 x_function
= GXequiv
;
1896 x_function
= GXcopyInverted
;
1899 x_function
= GXorInverted
;
1902 x_function
= GXnand
;
1909 x_function
= GXcopy
;
1913 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1914 if (m_window
&& m_window
->GetBackingPixmap())
1915 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1917 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1918 /* MATTHEW: [9] Need to redo pen simply */
1919 m_autoSetting
|= 0x2;
1921 m_logicalFunction
= function
;
1925 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1927 wxCHECK_RET( Ok(), "invalid dc" );
1929 if (m_textForegroundColour
== col
)
1932 m_textForegroundColour
= col
;
1936 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1938 wxCHECK_RET( Ok(), "invalid dc" );
1940 if (m_textBackgroundColour
== col
)
1943 m_textBackgroundColour
= col
;
1944 if (!m_textBackgroundColour
.Ok())
1948 void wxWindowDC::SetBackgroundMode( int mode
)
1950 m_backgroundMode
= mode
;
1953 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1958 /* Use GetXColormap */
1959 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1960 (Colormap
) palette
.GetXColormap());
1962 /* Use wxGetMainColormap */
1963 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1964 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1969 void wxWindowDC::SetDCClipping()
1971 // m_userRegion is the region set by calling SetClippingRegion
1973 if (m_currentRegion
)
1974 XDestroyRegion ((Region
) m_currentRegion
);
1976 // We need to take into account
1977 // clipping imposed on a window by a repaint.
1978 // We'll combine it with the user region. But for now,
1979 // just use the currently-defined user clipping region.
1980 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1981 m_currentRegion
= (WXRegion
) XCreateRegion ();
1983 m_currentRegion
= (WXRegion
) NULL
;
1985 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1986 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1987 else if (m_userRegion
)
1988 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1989 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1990 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
1991 (Region
) m_currentRegion
);
1993 if (m_currentRegion
)
1995 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1999 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2004 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2006 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2009 XDestroyRegion ((Region
) m_userRegion
);
2010 m_userRegion
= (WXRegion
) XCreateRegion ();
2014 r
.width
= XLOG2DEVREL(width
);
2015 r
.height
= YLOG2DEVREL(height
);
2016 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2020 // Needs to work differently for Pixmap: without this,
2021 // there's a nasty (Display*) m_display bug. 8/12/94
2022 if (m_window
&& m_window
->GetBackingPixmap())
2024 XRectangle rects
[1];
2025 rects
[0].x
= XLOG2DEV_2(x
);
2026 rects
[0].y
= YLOG2DEV_2(y
);
2027 rects
[0].width
= XLOG2DEVREL(width
);
2028 rects
[0].height
= YLOG2DEVREL(height
);
2029 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2033 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2035 wxRect box
= region
.GetBox();
2037 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2040 XDestroyRegion ((Region
) m_userRegion
);
2041 m_userRegion
= (WXRegion
) XCreateRegion ();
2043 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2047 // Needs to work differently for Pixmap: without this,
2048 // there's a nasty (Display*) m_display bug. 8/12/94
2049 if (m_window
&& m_window
->GetBackingPixmap())
2051 XRectangle rects
[1];
2052 rects
[0].x
= XLOG2DEV_2(box
.x
);
2053 rects
[0].y
= YLOG2DEV_2(box
.y
);
2054 rects
[0].width
= XLOG2DEVREL(box
.width
);
2055 rects
[0].height
= YLOG2DEVREL(box
.height
);
2056 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2061 void wxWindowDC::DestroyClippingRegion()
2063 wxDC::DestroyClippingRegion();
2066 XDestroyRegion ((Region
) m_userRegion
);
2067 m_userRegion
= NULL
;
2072 gc_val
.clip_mask
= None
;
2073 if (m_window
&& m_window
->GetBackingPixmap())
2074 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2077 // Resolution in pixels per logical inch
2078 wxSize
wxWindowDC::GetPPI() const
2080 return wxSize(100, 100);
2083 int wxWindowDC::GetDepth() const
2090 // ----------------------------------- spline code ----------------------------------------
2092 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2093 double a3
, double b3
, double a4
, double b4
);
2094 void wx_clear_stack();
2095 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2096 double *y3
, double *x4
, double *y4
);
2097 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2098 double x4
, double y4
);
2099 static bool wx_spline_add_point(double x
, double y
);
2100 static void wx_spline_draw_point_array(wxDC
*dc
);
2102 wxList wx_spline_point_list
;
2104 #define half(z1, z2) ((z1+z2)/2.0)
2107 /* iterative version */
2109 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2112 register double xmid
, ymid
;
2113 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2116 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2118 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2119 xmid
= (double)half(x2
, x3
);
2120 ymid
= (double)half(y2
, y3
);
2121 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2122 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2123 wx_spline_add_point( x1
, y1
);
2124 wx_spline_add_point( xmid
, ymid
);
2126 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2127 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2128 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2129 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2134 /* utilities used by spline drawing routines */
2136 typedef struct wx_spline_stack_struct
{
2137 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2140 #define SPLINE_STACK_DEPTH 20
2141 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2142 static Stack
*wx_stack_top
;
2143 static int wx_stack_count
;
2145 void wx_clear_stack()
2147 wx_stack_top
= wx_spline_stack
;
2151 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2153 wx_stack_top
->x1
= x1
;
2154 wx_stack_top
->y1
= y1
;
2155 wx_stack_top
->x2
= x2
;
2156 wx_stack_top
->y2
= y2
;
2157 wx_stack_top
->x3
= x3
;
2158 wx_stack_top
->y3
= y3
;
2159 wx_stack_top
->x4
= x4
;
2160 wx_stack_top
->y4
= y4
;
2165 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2166 double *x3
, double *y3
, double *x4
, double *y4
)
2168 if (wx_stack_count
== 0)
2172 *x1
= wx_stack_top
->x1
;
2173 *y1
= wx_stack_top
->y1
;
2174 *x2
= wx_stack_top
->x2
;
2175 *y2
= wx_stack_top
->y2
;
2176 *x3
= wx_stack_top
->x3
;
2177 *y3
= wx_stack_top
->y3
;
2178 *x4
= wx_stack_top
->x4
;
2179 *y4
= wx_stack_top
->y4
;
2183 static bool wx_spline_add_point(double x
, double y
)
2185 wxPoint
*point
= new wxPoint
;
2188 wx_spline_point_list
.Append((wxObject
*)point
);
2192 static void wx_spline_draw_point_array(wxDC
*dc
)
2194 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2195 wxNode
*node
= wx_spline_point_list
.First();
2198 wxPoint
*point
= (wxPoint
*)node
->Data();
2201 node
= wx_spline_point_list
.First();
2205 void wxWindowDC::DoDrawSpline( wxList
*points
)
2207 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2210 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2211 double x1
, y1
, x2
, y2
;
2213 wxNode
*node
= points
->First();
2214 p
= (wxPoint
*)node
->Data();
2219 node
= node
->Next();
2220 p
= (wxPoint
*)node
->Data();
2224 cx1
= (double)((x1
+ x2
) / 2);
2225 cy1
= (double)((y1
+ y2
) / 2);
2226 cx2
= (double)((cx1
+ x2
) / 2);
2227 cy2
= (double)((cy1
+ y2
) / 2);
2229 wx_spline_add_point(x1
, y1
);
2231 while ((node
= node
->Next()) != NULL
)
2233 p
= (wxPoint
*)node
->Data();
2238 cx4
= (double)(x1
+ x2
) / 2;
2239 cy4
= (double)(y1
+ y2
) / 2;
2240 cx3
= (double)(x1
+ cx4
) / 2;
2241 cy3
= (double)(y1
+ cy4
) / 2;
2243 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2247 cx2
= (double)(cx1
+ x2
) / 2;
2248 cy2
= (double)(cy1
+ y2
) / 2;
2251 wx_spline_add_point( cx1
, cy1
);
2252 wx_spline_add_point( x2
, y2
);
2254 wx_spline_draw_point_array( this );
2257 #endif // wxUSE_SPLINE
2261 // ----------------------------------------------------------------------------
2263 // ----------------------------------------------------------------------------
2265 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2267 wxRegion
* region
= NULL
;
2269 // Combine all the update rects into a region
2270 const wxRectList
& updateRects(win
->GetUpdateRects());
2271 if ( updateRects
.GetCount() != 0 )
2273 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2275 node
= node
->GetNext() )
2277 wxRect
* rect
= node
->GetData();
2280 region
= new wxRegion(*rect
);
2282 // TODO: is this correct? In SetDCClipping above,
2283 // XIntersectRegion is used to combine paint and user
2284 // regions. XIntersectRegion appears to work in that case...
2285 region
->Union(*rect
);
2291 win
->GetClientSize(&cw
, &ch
);
2292 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2295 win
->SetUpdateRegion(*region
);
2297 wxRegion
& theRegion(win
->GetUpdateRegion());
2298 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2300 // Set the clipping region. Any user-defined region will be combined with this
2301 // one in SetDCClipping.
2302 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2307 wxPaintDC::~wxPaintDC()
2309 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2311 m_window
->ClearUpdateRegion();
2314 // ----------------------------------------------------------------------------
2315 // private functions
2316 // ----------------------------------------------------------------------------
2319 Used when copying between drawables on different (Display*) m_displays. Not
2320 very fast, but better than giving up.
2323 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2324 Drawable src
, Drawable dest
,
2327 unsigned int w
, unsigned int h
,
2328 int destx
, int desty
,
2329 bool more
, XImage
**cache
)
2331 XImage
*image
, *destimage
;
2332 Colormap destcm
, srccm
;
2333 static const int CACHE_SIZE
= 256;
2336 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2337 int k
, cache_pos
, all_cache
;
2339 if (!cache
|| !*cache
)
2340 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2344 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2346 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2347 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2352 for (i
= 0; i
< w
; i
++)
2353 for (j
= 0; j
< h
; j
++) {
2354 unsigned long pixel
;
2357 pixel
= XGetPixel(image
, i
, j
);
2358 for (k
= cache_pos
; k
--; )
2359 if (cachesrc
[k
] == pixel
) {
2360 pixel
= cachedest
[k
];
2364 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2365 if (cachesrc
[k
] == pixel
) {
2366 pixel
= cachedest
[k
];
2370 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2371 XQueryColor(src_display
, srccm
, &xcol
);
2372 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2374 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2376 if (++cache_pos
>= CACHE_SIZE
) {
2382 XPutPixel(destimage
, i
, j
, pixel
);
2385 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2386 XDestroyImage(destimage
);
2391 XDestroyImage(image
);
2396 /* Helper function for 16-bit fonts */
2397 static int str16len(const char *s
)
2401 while (s
[0] && s
[1]) {