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"
68 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 #define RAD2DEG 57.2957795131
76 // Fudge factor (VZ: what??)
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 #if !USE_SHARED_LIBRARY
84 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
85 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
94 Drawable src
, Drawable dest
,
97 unsigned int w
, unsigned int h
,
99 bool more
, XImage
**cache
);
101 // ============================================================================
103 // ============================================================================
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 wxWindowDC::wxWindowDC()
112 m_gcBacking
= (WXGC
) 0;
114 m_backgroundPixel
= -1;
115 m_currentPenWidth
= 1;
116 m_currentPenJoin
= -1;
117 m_currentPenDashCount
= -1;
118 m_currentPenDash
= (char*) NULL
;
121 // m_currentBkMode = wxTRANSPARENT;
122 m_colour
= wxColourDisplay();
123 m_display
= (WXDisplay
*) NULL
;
124 m_currentRegion
= (WXRegion
) 0;
125 m_userRegion
= (WXRegion
) 0;
126 m_pixmap
= (WXPixmap
) 0;
128 m_oldFont
= (WXFont
) 0;
131 wxWindowDC::wxWindowDC( wxWindow
*window
)
133 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
136 m_font
= window
->GetFont();
138 m_gcBacking
= (WXGC
) 0;
139 m_backgroundPixel
= -1;
140 m_currentPenWidth
= 1;
141 m_currentPenJoin
= -1;
142 m_currentPenDashCount
= -1;
143 m_currentPenDash
= (char*) NULL
;
146 // m_currentBkMode = wxTRANSPARENT;
147 m_colour
= wxColourDisplay();
148 m_currentRegion
= (WXRegion
) 0;
149 m_userRegion
= (WXRegion
) 0;
153 m_display
= window
->GetXDisplay();
154 m_pixmap
= window
->GetXWindow();
155 Display
* display
= (Display
*) m_display
;
157 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
160 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
161 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
162 gcvalues
.graphics_exposures
= False
;
163 gcvalues
.line_width
= 1;
164 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
165 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
168 if (m_window
->GetBackingPixmap())
170 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
171 DefaultScreen (display
)),
172 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
176 m_backgroundPixel
= (int) gcvalues
.background
;
178 // Get the current Font so we can set it back later
180 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
181 m_oldFont
= (WXFont
) valReturn
.font
;
183 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
186 wxWindowDC::~wxWindowDC()
188 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
190 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
192 if (m_window
&& m_window
->GetBackingPixmap())
193 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
197 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
201 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
202 m_gcBacking
= (WXGC
) 0;
205 XDestroyRegion ((Region
) m_currentRegion
);
206 m_currentRegion
= (WXRegion
) 0;
209 XDestroyRegion ((Region
) m_userRegion
);
210 m_userRegion
= (WXRegion
) 0;
213 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
214 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
216 wxFAIL_MSG("not implemented");
219 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
221 wxFAIL_MSG("not implemented");
226 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
228 wxCHECK_RET( Ok(), "invalid dc" );
230 int x1d
, y1d
, x2d
, y2d
;
232 // FreeGetPixelCache();
242 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
244 if (m_window
&& m_window
->GetBackingPixmap())
245 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
246 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
247 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
249 CalcBoundingBox(x1
, y1
);
250 CalcBoundingBox(x2
, y2
);
253 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
255 wxCHECK_RET( Ok(), "invalid dc" );
260 int xx
= XLOG2DEV (x
);
261 int yy
= YLOG2DEV (y
);
263 wxDisplaySize (&ww
, &hh
);
264 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
266 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
269 if (m_window
&& m_window
->GetBackingPixmap())
273 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
276 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
282 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
284 wxCHECK_RET( Ok(), "invalid dc" );
286 // FreeGetPixelCache();
288 int xx1
= XLOG2DEV (x1
);
289 int yy1
= YLOG2DEV (y1
);
290 int xx2
= XLOG2DEV (x2
);
291 int yy2
= YLOG2DEV (y2
);
292 int xxc
= XLOG2DEV (xc
);
293 int yyc
= YLOG2DEV (yc
);
294 int xxc_2
= XLOG2DEV_2 (xc
);
295 int yyc_2
= YLOG2DEV_2 (yc
);
297 wxCoord dx
= xx1
- xxc
;
298 wxCoord dy
= yy1
- yyc
;
299 double radius
= sqrt (dx
* dx
+ dy
* dy
);
300 wxCoord r
= (wxCoord
) radius
;
302 double radius1
, radius2
;
304 if (xx1
== xx2
&& yy1
== yy2
)
309 else if (radius
== 0.0)
310 radius1
= radius2
= 0.0;
319 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
327 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
331 int alpha1
= (int) radius1
;
332 int alpha2
= (int) (radius2
- radius1
);
335 while (alpha2
> 360 * 64)
338 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
341 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
342 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
344 if (m_window
&& m_window
->GetBackingPixmap())
345 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
346 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
350 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
354 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
355 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
357 if (m_window
&& m_window
->GetBackingPixmap())
358 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
359 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
361 CalcBoundingBox (x1
, y1
);
362 CalcBoundingBox (x2
, y2
);
365 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
367 wxCHECK_RET( Ok(), "invalid dc" );
373 wd
= XLOG2DEVREL(width
);
374 hd
= YLOG2DEVREL(height
);
376 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
377 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
378 int start
= int(sa
*64);
379 int end
= int(ea
*64);
380 if (start
<0) start
+=360*64;
381 if (end
<0) end
+=360*64;
382 if (end
>start
) end
-=start
;
383 else end
+=360*64-start
;
385 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
387 m_autoSetting
= TRUE
; // must be reset
390 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
392 if (m_window
&& m_window
->GetBackingPixmap())
393 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
394 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
397 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
401 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
402 if (m_window
&& m_window
->GetBackingPixmap())
403 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
404 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
406 CalcBoundingBox (x
, y
);
407 CalcBoundingBox (x
+ width
, y
+ height
);
410 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
412 wxCHECK_RET( Ok(), "invalid dc" );
414 // FreeGetPixelCache();
416 if (m_pen
.Ok() && m_autoSetting
)
419 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
420 if (m_window
&& m_window
->GetBackingPixmap())
421 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
423 CalcBoundingBox (x
, y
);
426 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
428 wxCHECK_RET( Ok(), "invalid dc" );
430 // FreeGetPixelCache();
432 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
437 XPoint
*xpoints
= new XPoint
[n
];
440 for (i
= 0; i
< n
; i
++)
442 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
443 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
445 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
447 if (m_window
&& m_window
->GetBackingPixmap())
449 for (i
= 0; i
< n
; i
++)
451 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
452 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
454 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
460 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
461 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
463 wxCHECK_RET( Ok(), "invalid dc" );
465 // FreeGetPixelCache();
467 XPoint
*xpoints1
= new XPoint
[n
+ 1];
468 XPoint
*xpoints2
= new XPoint
[n
+ 1];
470 for (i
= 0; i
< n
; i
++)
472 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
473 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
474 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
475 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
476 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
479 // Close figure for XDrawLines (not needed for XFillPolygon)
480 xpoints1
[i
].x
= xpoints1
[0].x
;
481 xpoints1
[i
].y
= xpoints1
[0].y
;
482 xpoints2
[i
].x
= xpoints2
[0].x
;
483 xpoints2
[i
].y
= xpoints2
[0].y
;
485 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
488 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
489 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
490 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
491 if (m_window
&& m_window
->GetBackingPixmap())
493 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
494 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
495 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
496 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
500 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
504 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
506 if (m_window
&& m_window
->GetBackingPixmap())
507 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
514 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
516 wxCHECK_RET( Ok(), "invalid dc" );
518 // FreeGetPixelCache();
520 int xd
, yd
, wfd
, hfd
, wd
, hd
;
524 wfd
= XLOG2DEVREL(width
);
526 hfd
= YLOG2DEVREL(height
);
529 if (wfd
== 0 || hfd
== 0) return;
530 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
531 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
533 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
536 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
538 if (m_window
&& m_window
->GetBackingPixmap())
539 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
540 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
544 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
548 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
550 if (m_window
&& m_window
->GetBackingPixmap())
551 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
552 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
555 CalcBoundingBox (x
, y
);
556 CalcBoundingBox (x
+ width
, y
+ height
);
559 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
561 wxCHECK_RET( Ok(), "invalid dc" );
563 // FreeGetPixelCache();
565 // If radius is negative, it's a proportion of the smaller dimension.
567 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
569 int xd
= XLOG2DEV (x
);
570 int yd
= YLOG2DEV (y
);
571 int rd
= XLOG2DEVREL ((long) radius
);
572 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
573 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
578 // If radius is zero use DrawRectangle() instead to avoid
579 // X drawing errors with small radii
582 DrawRectangle( x
, y
, width
, height
);
586 // Draw nothing if transformed w or h is 0
587 if (wd
== 0 || hd
== 0) return;
589 // CMB: adjust size if outline is drawn otherwise the result is
590 // 1 pixel too wide and high
591 if (m_pen
.GetStyle() != wxTRANSPARENT
)
597 // CMB: ensure dd is not larger than rectangle otherwise we
598 // get an hour glass shape
599 if (rw_d
> wd
) rw_d
= wd
;
600 if (rw_d
> hd
) rw_d
= hd
;
603 // For backing pixmap
604 int xd2
= XLOG2DEV_2 (x
);
605 int yd2
= YLOG2DEV_2 (y
);
606 int rd2
= XLOG2DEVREL ((long) radius
);
607 int wd2
= XLOG2DEVREL (width
) ;
608 int hd2
= YLOG2DEVREL (height
) ;
613 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
617 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
619 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
622 // Arcs start from 3 o'clock, positive angles anticlockwise
624 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
625 rw_d
, rh_d
, 90 * 64, 90 * 64);
627 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
628 // rw_d, rh_d, 0, 90 * 64);
629 rw_d
, rh_d
, 0, 91 * 64);
631 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
633 // rw_d, rh_d, 270 * 64, 90 * 64);
634 rw_d
, rh_d
, 269 * 64, 92 * 64);
636 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
637 rw_d
, rh_d
, 180 * 64, 90 * 64);
639 if (m_window
&& m_window
->GetBackingPixmap())
641 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
642 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
643 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
644 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
646 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
647 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
648 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
649 xd2
+ wd2
- rw_d2
, yd2
,
650 // rw_d2, rh_d2, 0, 90 * 64);
651 rw_d2
, rh_d2
, 0, 91 * 64);
652 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
655 // rw_d2, rh_d2, 270 * 64, 90 * 64);
656 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
657 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
658 xd2
, yd2
+ hd2
- rh_d2
,
659 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
663 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
666 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
667 xd
+ wd
- rd
+ 1, yd
);
668 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
669 xd
+ wd
- rd
, yd
+ hd
);
671 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
673 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
674 xd
+ wd
, yd
+ hd
- rd
+ 1);
675 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
676 rw_d
, rh_d
, 90 * 64, 90 * 64);
677 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
678 // rw_d, rh_d, 0, 90 * 64);
679 rw_d
, rh_d
, 0, 91 * 64);
680 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
682 rw_d
, rh_d
, 269 * 64, 92 * 64);
683 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
684 rw_d
, rh_d
, 180 * 64, 90 * 64);
686 if (m_window
&& m_window
->GetBackingPixmap())
688 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
690 xd2
+ wd2
- rd2
+ 1, yd2
);
691 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
692 xd2
+ rd2
, yd2
+ hd2
,
693 xd2
+ wd2
- rd2
, yd2
+ hd2
);
695 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
697 xd2
, yd2
+ hd2
- rd2
);
698 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
699 xd2
+ wd2
, yd2
+ rd2
,
700 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
703 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
704 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
705 xd2
+ wd2
- rw_d2
, yd2
,
706 // rw_d2, rh_d2, 0, 90 * 64);
707 rw_d2
, rh_d2
, 0, 91 * 64);
708 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
711 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
712 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
713 xd2
, yd2
+ hd2
- rh_d2
,
714 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
717 CalcBoundingBox (x
, y
);
718 CalcBoundingBox (x
+ width
, y
+ height
);
723 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
725 wxCHECK_RET( Ok(), "invalid dc" );
727 // Check for negative width and height
740 // FreeGetPixelCache();
742 static const int angle
= 23040;
748 wd
= XLOG2DEVREL(width
) ;
749 hd
= YLOG2DEVREL(height
) ;
751 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
754 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
755 if (m_window
&& m_window
->GetBackingPixmap())
756 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
757 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
758 XLOG2DEVREL (width
) - WX_GC_CF
,
759 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
762 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
766 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
767 if (m_window
&& m_window
->GetBackingPixmap())
768 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
769 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
770 XLOG2DEVREL (width
) - WX_GC_CF
,
771 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
773 CalcBoundingBox (x
, y
);
774 CalcBoundingBox (x
+ width
, y
+ height
);
778 bool wxWindowDC::CanDrawBitmap() const
780 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
786 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
788 // FreeGetPixelCache();
790 // Be sure that foreground pixels (1) of
791 // the Icon will be painted with pen colour. [m_pen.SetColour()]
792 // Background pixels (0) will be painted with
793 // last selected background color. [::SetBackground]
794 if (m_pen
.Ok() && m_autoSetting
)
798 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
799 width
= icon
.GetWidth();
800 height
= icon
.GetHeight();
801 if (icon
.GetDisplay() == m_display
)
803 if (icon
.GetDepth() <= 1)
805 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
807 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
811 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
813 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
817 if (m_window
&& m_window
->GetBackingPixmap())
819 if (icon
.GetDepth() <= 1)
821 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
822 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
826 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
828 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
831 } else { /* Remote copy (different (Display*) m_displays) */
832 XImage
*cache
= NULL
;
833 if (m_window
&& m_window
->GetBackingPixmap())
834 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
835 (GC
) m_gcBacking
, 0, 0, width
, height
,
836 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
837 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
839 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
841 CalcBoundingBox (x
, y
);
845 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
846 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
847 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
849 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
851 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
853 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
855 // FreeGetPixelCache();
857 // Be sure that foreground pixels (1) of the Icon will be painted with pen
858 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
859 // last selected background color. [::SetBackground]
860 if (m_pen
.Ok() && m_autoSetting
)
863 // Do bitmap scaling if necessary
865 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
866 Pixmap sourcePixmap
= (Pixmap
) NULL
;
867 double scaleX
, scaleY
;
868 GetUserScale(& scaleX
, & scaleY
);
870 // Sorry, can't scale masks just yet
871 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
873 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
874 wxBitmap
& bitmap
= memDC
->GetBitmap();
876 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
878 wxImage
image(bitmap
);
881 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
885 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
886 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
888 image
= image
.Scale(scaledW
, scaledH
);
889 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
890 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
894 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
896 if (m_pixmap
&& sourcePixmap
)
899 int orig
= m_logicalFunction
;
901 SetLogicalFunction (rop
);
903 if (m_display
!= sourceDC
->m_display
)
905 XImage
*cache
= NULL
;
907 if (m_window
&& m_window
->GetBackingPixmap())
908 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
909 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
911 source
->LogicalToDeviceX (xsrc
),
912 source
->LogicalToDeviceY (ysrc
),
913 source
->LogicalToDeviceXRel(width
),
914 source
->LogicalToDeviceYRel(height
),
915 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
918 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
920 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
921 wxBitmap
& sel
= memDC
->GetBitmap();
922 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
924 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
925 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
929 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
930 source
->LogicalToDeviceX (xsrc
),
931 source
->LogicalToDeviceY (ysrc
),
932 source
->LogicalToDeviceXRel(width
),
933 source
->LogicalToDeviceYRel(height
),
934 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
939 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
940 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
945 if (m_window
&& m_window
->GetBackingPixmap())
947 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
948 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
950 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
951 source
->LogicalToDeviceX (xsrc
),
952 source
->LogicalToDeviceY (ysrc
),
953 source
->LogicalToDeviceXRel(width
),
954 source
->LogicalToDeviceYRel(height
),
955 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
959 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
960 source
->LogicalToDeviceX (xsrc
),
961 source
->LogicalToDeviceY (ysrc
),
962 source
->LogicalToDeviceXRel(width
),
963 source
->LogicalToDeviceYRel(height
),
964 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
967 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
969 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
970 wxBitmap
& sel
= memDC
->GetBitmap();
971 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
973 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
974 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
978 // Check if we're copying from a mono bitmap
979 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
980 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
982 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
983 source
->LogicalToDeviceX (xsrc
),
984 source
->LogicalToDeviceY (ysrc
),
985 source
->LogicalToDeviceXRel(width
),
986 source
->LogicalToDeviceYRel(height
),
987 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
991 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
992 source
->LogicalToDeviceX (xsrc
),
993 source
->LogicalToDeviceY (ysrc
),
994 source
->LogicalToDeviceXRel(width
),
995 source
->LogicalToDeviceYRel(height
),
996 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1001 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1002 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1005 } /* Remote/local (Display*) m_display */
1006 CalcBoundingBox (xdest
, ydest
);
1007 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1009 SetLogicalFunction(orig
);
1011 if (scaledBitmap
) delete scaledBitmap
;
1015 if (scaledBitmap
) delete scaledBitmap
;
1020 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1022 wxCHECK_RET( Ok(), "invalid dc" );
1024 // Since X draws from the baseline of the text, must add the text height
1030 slen
= strlen(text
);
1034 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1035 int direction
, descent
;
1036 XCharStruct overall_return
;
1039 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1040 &ascent
, &descent
, &overall_return
);
1043 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1044 &ascent
, &descent
, &overall_return
);
1046 cx
= overall_return
.width
;
1047 cy
= ascent
+ descent
;
1050 // First draw a rectangle representing the text background, if a text
1051 // background is specified
1052 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1054 wxColour oldPenColour
= m_currentColour
;
1055 m_currentColour
= m_textBackgroundColour
;
1056 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1057 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1058 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1059 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1061 // This separation of the big && test required for gcc2.7/HP UX 9.02
1062 // or pixel value can be corrupted!
1063 sameColour
= (sameColour
&&
1064 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1066 if (!sameColour
|| !GetOptimization())
1068 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1069 m_currentColour
= m_textBackgroundColour
;
1071 // Set the GC to the required colour
1074 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1075 if (m_window
&& m_window
->GetBackingPixmap())
1076 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1080 m_textBackgroundColour
= oldPenColour
;
1082 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1083 if (m_window
&& m_window
->GetBackingPixmap())
1084 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1085 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1088 // Now set the text foreground and draw the text
1089 if (m_textForegroundColour
.Ok ())
1091 wxColour oldPenColour
= m_currentColour
;
1092 m_currentColour
= m_textForegroundColour
;
1093 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1094 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1095 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1096 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1097 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1099 if (!sameColour
|| !GetOptimization())
1102 if (!m_colour
) // Mono display
1104 // Unless foreground is really white, draw it in black
1105 unsigned char red
= m_textForegroundColour
.Red ();
1106 unsigned char blue
= m_textForegroundColour
.Blue ();
1107 unsigned char green
= m_textForegroundColour
.Green ();
1108 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1109 && green
== (unsigned char) 255)
1111 m_currentColour
= *wxWHITE
;
1112 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1113 m_currentColour
.SetPixel(pixel
);
1114 m_textForegroundColour
.SetPixel(pixel
);
1118 m_currentColour
= *wxBLACK
;
1119 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1120 m_currentColour
.SetPixel(pixel
);
1121 m_textForegroundColour
.SetPixel(pixel
);
1126 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1127 m_currentColour
.SetPixel(pixel
);
1130 // Set the GC to the required colour
1133 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1134 if (m_window
&& m_window
->GetBackingPixmap())
1135 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1139 m_textForegroundColour
= oldPenColour
;
1142 // We need to add the ascent, not the whole height, since X draws at the
1143 // point above the descender.
1146 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1147 (XChar2b
*)(char*) (const char*) text
, slen
);
1150 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1152 if (m_window
&& m_window
->GetBackingPixmap()) {
1155 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1156 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1157 (XChar2b
*)(char*) (const char*) text
, slen
);
1160 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1161 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1165 GetTextExtent (text
, &w
, &h
);
1166 CalcBoundingBox (x
+ w
, y
+ h
);
1167 CalcBoundingBox (x
, y
);
1170 bool wxWindowDC::CanGetTextExtent() const
1175 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1176 wxCoord
*descent
, wxCoord
*externalLeading
,
1177 wxFont
*font
) const
1179 wxCHECK_RET( Ok(), "invalid dc" );
1181 wxFont
* theFont
= font
;
1183 theFont
= (wxFont
*)&m_font
; // const_cast
1187 // TODO: this should be an error log function
1188 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1190 if (width
) *width
= -1;
1191 if (height
) *height
= -1;
1195 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1197 int direction
, ascent
, descent2
;
1198 XCharStruct overall
;
1203 slen
= str16len(string
);
1206 slen
= strlen(string
);
1210 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1211 &ascent
, &descent2
, &overall
);
1214 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1215 &ascent
, &descent2
, &overall
);
1217 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1218 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1220 *descent
= descent2
;
1221 if (externalLeading
)
1222 *externalLeading
= 0;
1225 wxCoord
wxWindowDC::GetCharWidth() const
1227 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1228 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1230 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1232 int direction
, ascent
, descent
;
1233 XCharStruct overall
;
1234 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1235 &descent
, &overall
);
1236 return XDEV2LOGREL(overall
.width
);
1239 wxCoord
wxWindowDC::GetCharHeight() const
1241 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1242 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1244 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1246 int direction
, ascent
, descent
;
1247 XCharStruct overall
;
1248 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1249 &descent
, &overall
);
1250 // return XDEV2LOGREL(overall.ascent + overall.descent);
1251 return XDEV2LOGREL(ascent
+ descent
);
1254 void wxWindowDC::Clear()
1256 wxCHECK_RET( Ok(), "invalid dc" );
1261 m_window
->GetSize(&w
, &h
);
1263 if (m_window
&& m_window
->GetBackingPixmap())
1265 w
= m_window
->GetPixmapWidth();
1266 h
= m_window
->GetPixmapHeight();
1271 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1273 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1274 w
= memDC
->GetBitmap().GetWidth();
1275 h
= memDC
->GetBitmap().GetHeight();
1281 wxBrush saveBrush
= m_brush
;
1282 SetBrush (m_backgroundBrush
);
1284 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1286 if (m_window
&& m_window
->GetBackingPixmap())
1287 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1289 m_brush
= saveBrush
;
1292 void wxWindowDC::Clear(const wxRect
& rect
)
1294 wxCHECK_RET( Ok(), "invalid dc" );
1296 int x
= rect
.x
; int y
= rect
.y
;
1297 int w
= rect
.width
; int h
= rect
.height
;
1299 wxBrush saveBrush
= m_brush
;
1300 SetBrush (m_backgroundBrush
);
1302 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1304 if (m_window
&& m_window
->GetBackingPixmap())
1305 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1307 m_brush
= saveBrush
;
1310 void wxWindowDC::SetFont( const wxFont
&font
)
1312 wxCHECK_RET( Ok(), "invalid dc" );
1318 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1320 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1322 if (m_window
&& m_window
->GetBackingPixmap())
1323 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1328 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1330 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1331 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1333 if (m_window
&& m_window
->GetBackingPixmap())
1334 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1337 void wxWindowDC::SetPen( const wxPen
&pen
)
1339 wxCHECK_RET( Ok(), "invalid dc" );
1345 wxBitmap oldStipple
= m_currentStipple
;
1346 int oldStyle
= m_currentStyle
;
1347 int oldFill
= m_currentFill
;
1348 int old_pen_width
= m_currentPenWidth
;
1349 int old_pen_join
= m_currentPenJoin
;
1350 int old_pen_cap
= m_currentPenCap
;
1351 int old_pen_nb_dash
= m_currentPenDashCount
;
1352 char *old_pen_dash
= m_currentPenDash
;
1354 wxColour oldPenColour
= m_currentColour
;
1355 m_currentColour
= m_pen
.GetColour ();
1356 m_currentStyle
= m_pen
.GetStyle ();
1357 m_currentFill
= m_pen
.GetStyle (); // TODO?
1358 m_currentPenWidth
= m_pen
.GetWidth ();
1359 m_currentPenJoin
= m_pen
.GetJoin ();
1360 m_currentPenCap
= m_pen
.GetCap ();
1361 m_currentPenDashCount
= m_pen
.GetDashCount();
1362 m_currentPenDash
= m_pen
.GetDash();
1364 if (m_currentStyle
== wxSTIPPLE
)
1365 m_currentStipple
= * m_pen
.GetStipple ();
1367 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1368 oldFill
== m_currentFill
&&
1369 old_pen_join
== m_currentPenJoin
&&
1370 old_pen_cap
== m_currentPenCap
&&
1371 old_pen_nb_dash
== m_currentPenDashCount
&&
1372 old_pen_dash
== m_currentPenDash
&&
1373 old_pen_width
== m_currentPenWidth
);
1375 bool sameColour
= (oldPenColour
.Ok () &&
1376 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1377 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1378 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1379 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1381 if (!sameStyle
|| !GetOptimization())
1383 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1384 if (scaled_width
< 0)
1390 static const char dotted
[] = {2, 5};
1391 static const char short_dashed
[] = {4, 4};
1392 static const char long_dashed
[] = {4, 8};
1393 static const char dotted_dashed
[] = {6, 6, 2, 6};
1395 // We express dash pattern in pen width unit, so we are
1396 // independent of zoom factor and so on...
1398 const char *req_dash
;
1400 switch (m_pen
.GetStyle ())
1403 req_nb_dash
= m_currentPenDashCount
;
1404 req_dash
= m_currentPenDash
;
1405 style
= LineOnOffDash
;
1410 style
= LineOnOffDash
;
1414 req_dash
= short_dashed
;
1415 style
= LineOnOffDash
;
1419 req_dash
= long_dashed
;
1420 style
= LineOnOffDash
;
1424 req_dash
= dotted_dashed
;
1425 style
= LineOnOffDash
;
1436 if (req_dash
&& req_nb_dash
)
1438 char *real_req_dash
= new char[req_nb_dash
];
1441 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1442 for (int i
= 0; i
< req_nb_dash
; i
++)
1443 real_req_dash
[i
] = req_dash
[i
] * factor
;
1444 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1446 if (m_window
&& m_window
->GetBackingPixmap())
1447 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1448 delete[]real_req_dash
;
1452 // No Memory. We use non-scaled dash pattern...
1453 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1455 if (m_window
&& m_window
->GetBackingPixmap())
1456 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1460 switch (m_pen
.GetCap ())
1462 case wxCAP_PROJECTING
:
1463 cap
= CapProjecting
;
1470 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1474 switch (m_pen
.GetJoin ())
1488 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1490 if (m_window
&& m_window
->GetBackingPixmap())
1491 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1494 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1498 oldStipple
= wxNullBitmap
; // For later reset!!
1500 switch (m_currentFill
)
1502 case wxBDIAGONAL_HATCH
:
1503 if (bdiag
== (Pixmap
) 0)
1504 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1505 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1506 bdiag_bits
, bdiag_width
, bdiag_height
);
1509 case wxFDIAGONAL_HATCH
:
1510 if (fdiag
== (Pixmap
) 0)
1511 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1512 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1513 fdiag_bits
, fdiag_width
, fdiag_height
);
1517 if (cross
== (Pixmap
) 0)
1518 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1519 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1520 cross_bits
, cross_width
, cross_height
);
1523 case wxHORIZONTAL_HATCH
:
1524 if (horiz
== (Pixmap
) 0)
1525 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1526 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1527 horiz_bits
, horiz_width
, horiz_height
);
1530 case wxVERTICAL_HATCH
:
1531 if (verti
== (Pixmap
) 0)
1532 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1533 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1534 verti_bits
, verti_width
, verti_height
);
1537 case wxCROSSDIAG_HATCH
:
1539 if (cdiag
== (Pixmap
) 0)
1540 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1541 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1542 cdiag_bits
, cdiag_width
, cdiag_height
);
1546 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1548 if (m_window
&& m_window
->GetBackingPixmap())
1549 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1551 else if (m_currentStipple
.Ok()
1552 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1554 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1556 if (m_window
&& m_window
->GetBackingPixmap())
1557 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1560 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1564 if (m_currentFill
== wxSTIPPLE
)
1565 fill_style
= FillStippled
;
1566 else if (IS_HATCH (m_currentFill
))
1567 fill_style
= FillStippled
;
1569 fill_style
= FillSolid
;
1570 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1571 if (m_window
&& m_window
->GetBackingPixmap())
1572 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1575 // must test m_logicalFunction, because it involves background!
1576 if (!sameColour
|| !GetOptimization()
1577 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1580 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1581 pixel
= m_backgroundPixel
;
1584 unsigned char red
= m_pen
.GetColour ().Red ();
1585 unsigned char blue
= m_pen
.GetColour ().Blue ();
1586 unsigned char green
= m_pen
.GetColour ().Green ();
1587 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1588 && green
== (unsigned char) 255)
1590 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1591 m_currentColour
= *wxWHITE
;
1592 m_pen
.GetColour().SetPixel(pixel
);
1593 m_currentColour
.SetPixel(pixel
);
1597 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1598 m_currentColour
= *wxBLACK
;
1599 m_pen
.GetColour().SetPixel(pixel
);
1604 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1605 m_currentColour
.SetPixel(pixel
);
1608 // Finally, set the GC to the required colour
1611 if (m_logicalFunction
== wxXOR
)
1614 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1615 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1616 if (m_window
&& m_window
->GetBackingPixmap())
1617 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1621 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1622 if (m_window
&& m_window
->GetBackingPixmap())
1623 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1628 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1633 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1635 wxCHECK_RET( Ok(), "invalid dc" );
1639 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1642 int oldFill
= m_currentFill
;
1643 wxBitmap oldStipple
= m_currentStipple
;
1645 m_autoSetting
|= 0x1;
1647 m_currentFill
= m_brush
.GetStyle ();
1648 if (m_currentFill
== wxSTIPPLE
)
1649 m_currentStipple
= * m_brush
.GetStipple ();
1651 wxColour
oldBrushColour(m_currentColour
);
1652 m_currentColour
= m_brush
.GetColour ();
1654 bool sameColour
= (oldBrushColour
.Ok () &&
1655 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1656 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1657 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1658 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1660 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1662 switch (brush
.GetStyle ())
1666 case wxBDIAGONAL_HATCH
:
1667 case wxCROSSDIAG_HATCH
:
1668 case wxFDIAGONAL_HATCH
:
1670 case wxHORIZONTAL_HATCH
:
1671 case wxVERTICAL_HATCH
:
1674 // Chris Breeze 23/07/97: use background mode to determine whether
1675 // fill style should be solid or transparent
1676 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1677 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1678 if (m_window
&& m_window
->GetBackingPixmap())
1679 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1684 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1685 if (m_window
&& m_window
->GetBackingPixmap())
1686 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1690 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1694 switch (m_currentFill
)
1696 case wxBDIAGONAL_HATCH
:
1697 if (bdiag
== (Pixmap
) 0)
1698 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1699 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1700 bdiag_bits
, bdiag_width
, bdiag_height
);
1703 case wxFDIAGONAL_HATCH
:
1704 if (fdiag
== (Pixmap
) 0)
1705 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1706 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1707 fdiag_bits
, fdiag_width
, fdiag_height
);
1711 if (cross
== (Pixmap
) 0)
1712 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1713 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1714 cross_bits
, cross_width
, cross_height
);
1717 case wxHORIZONTAL_HATCH
:
1718 if (horiz
== (Pixmap
) 0)
1719 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1720 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1721 horiz_bits
, horiz_width
, horiz_height
);
1724 case wxVERTICAL_HATCH
:
1725 if (verti
== (Pixmap
) 0)
1726 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1727 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1728 verti_bits
, verti_width
, verti_height
);
1731 case wxCROSSDIAG_HATCH
:
1733 if (cdiag
== (Pixmap
) 0)
1734 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1735 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1736 cdiag_bits
, cdiag_width
, cdiag_height
);
1740 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1742 if (m_window
&& m_window
->GetBackingPixmap())
1743 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1745 // X can forget the stipple value when resizing a window (apparently)
1746 // so always set the stipple.
1747 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1749 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1750 if (m_window
&& m_window
->GetBackingPixmap())
1751 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1754 // must test m_logicalFunction, because it involves background!
1755 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1760 // Policy - on a monochrome screen, all brushes are white,
1761 // except when they're REALLY black!!!
1762 unsigned char red
= m_brush
.GetColour ().Red ();
1763 unsigned char blue
= m_brush
.GetColour ().Blue ();
1764 unsigned char green
= m_brush
.GetColour ().Green ();
1766 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1767 && green
== (unsigned char) 0)
1769 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1770 m_currentColour
= *wxBLACK
;
1771 m_brush
.GetColour().SetPixel(pixel
);
1772 m_currentColour
.SetPixel(pixel
);
1776 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1777 m_currentColour
= *wxWHITE
;
1778 m_brush
.GetColour().SetPixel(pixel
);
1779 m_currentColour
.SetPixel(pixel
);
1782 // N.B. comment out the above line and uncomment the following lines
1783 // if you want non-white colours to be black on a monochrome display.
1785 if (red == (unsigned char )255 && blue == (unsigned char)255
1786 && green == (unsigned char)255)
1787 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1789 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1792 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1794 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1795 m_currentColour
.SetPixel(pixel
);
1799 // Finally, set the GC to the required colour
1800 if (m_logicalFunction
== wxXOR
)
1803 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1804 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1805 if (m_window
&& m_window
->GetBackingPixmap())
1806 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1810 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1811 if (m_window
&& m_window
->GetBackingPixmap())
1812 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1817 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1820 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1822 wxCHECK_RET( Ok(), "invalid dc" );
1824 m_backgroundBrush
= brush
;
1826 if (!m_backgroundBrush
.Ok())
1829 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1831 // New behaviour, 10/2/99: setting the background brush of a DC
1832 // doesn't affect the window background colour.
1834 // XSetWindowBackground doesn't work for non-Window pixmaps
1835 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1836 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1839 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1840 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1841 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1842 if (m_window
&& m_window
->GetBackingPixmap())
1843 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1846 void wxWindowDC::SetLogicalFunction( int function
)
1848 wxCHECK_RET( Ok(), "invalid dc" );
1853 if (m_logicalFunction
== function
)
1859 x_function
= GXclear
;
1865 x_function
= GXinvert
;
1868 x_function
= GXorReverse
;
1871 x_function
= GXandReverse
;
1880 x_function
= GXandInverted
;
1883 x_function
= GXnoop
;
1889 x_function
= GXequiv
;
1892 x_function
= GXcopyInverted
;
1895 x_function
= GXorInverted
;
1898 x_function
= GXnand
;
1905 x_function
= GXcopy
;
1909 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1910 if (m_window
&& m_window
->GetBackingPixmap())
1911 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1913 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1914 /* MATTHEW: [9] Need to redo pen simply */
1915 m_autoSetting
|= 0x2;
1917 m_logicalFunction
= function
;
1921 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1923 wxCHECK_RET( Ok(), "invalid dc" );
1925 if (m_textForegroundColour
== col
)
1928 m_textForegroundColour
= col
;
1932 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1934 wxCHECK_RET( Ok(), "invalid dc" );
1936 if (m_textBackgroundColour
== col
)
1939 m_textBackgroundColour
= col
;
1940 if (!m_textBackgroundColour
.Ok())
1944 void wxWindowDC::SetBackgroundMode( int mode
)
1946 m_backgroundMode
= mode
;
1949 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1954 /* Use GetXColormap */
1955 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1956 (Colormap
) palette
.GetXColormap());
1958 /* Use wxGetMainColormap */
1959 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1960 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1965 void wxWindowDC::SetDCClipping()
1967 // m_userRegion is the region set by calling SetClippingRegion
1969 if (m_currentRegion
)
1970 XDestroyRegion ((Region
) m_currentRegion
);
1972 // We need to take into account
1973 // clipping imposed on a window by a repaint.
1974 // We'll combine it with the user region. But for now,
1975 // just use the currently-defined user clipping region.
1976 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1977 m_currentRegion
= (WXRegion
) XCreateRegion ();
1979 m_currentRegion
= (WXRegion
) NULL
;
1981 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1982 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1983 else if (m_userRegion
)
1984 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1985 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1986 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
1987 (Region
) m_currentRegion
);
1989 if (m_currentRegion
)
1991 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1995 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2000 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2002 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2005 XDestroyRegion ((Region
) m_userRegion
);
2006 m_userRegion
= (WXRegion
) XCreateRegion ();
2010 r
.width
= XLOG2DEVREL(width
);
2011 r
.height
= YLOG2DEVREL(height
);
2012 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2016 // Needs to work differently for Pixmap: without this,
2017 // there's a nasty (Display*) m_display bug. 8/12/94
2018 if (m_window
&& m_window
->GetBackingPixmap())
2020 XRectangle rects
[1];
2021 rects
[0].x
= XLOG2DEV_2(x
);
2022 rects
[0].y
= YLOG2DEV_2(y
);
2023 rects
[0].width
= XLOG2DEVREL(width
);
2024 rects
[0].height
= YLOG2DEVREL(height
);
2025 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2029 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2031 wxRect box
= region
.GetBox();
2033 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2036 XDestroyRegion ((Region
) m_userRegion
);
2037 m_userRegion
= (WXRegion
) XCreateRegion ();
2039 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2043 // Needs to work differently for Pixmap: without this,
2044 // there's a nasty (Display*) m_display bug. 8/12/94
2045 if (m_window
&& m_window
->GetBackingPixmap())
2047 XRectangle rects
[1];
2048 rects
[0].x
= XLOG2DEV_2(box
.x
);
2049 rects
[0].y
= YLOG2DEV_2(box
.y
);
2050 rects
[0].width
= XLOG2DEVREL(box
.width
);
2051 rects
[0].height
= YLOG2DEVREL(box
.height
);
2052 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2057 void wxWindowDC::DestroyClippingRegion()
2059 wxDC::DestroyClippingRegion();
2062 XDestroyRegion ((Region
) m_userRegion
);
2063 m_userRegion
= NULL
;
2068 gc_val
.clip_mask
= None
;
2069 if (m_window
&& m_window
->GetBackingPixmap())
2070 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2073 // Resolution in pixels per logical inch
2074 wxSize
wxWindowDC::GetPPI() const
2076 return wxSize(100, 100);
2079 int wxWindowDC::GetDepth() const
2086 // ----------------------------------- spline code ----------------------------------------
2088 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2089 double a3
, double b3
, double a4
, double b4
);
2090 void wx_clear_stack();
2091 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2092 double *y3
, double *x4
, double *y4
);
2093 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2094 double x4
, double y4
);
2095 static bool wx_spline_add_point(double x
, double y
);
2096 static void wx_spline_draw_point_array(wxDC
*dc
);
2098 wxList wx_spline_point_list
;
2100 #define half(z1, z2) ((z1+z2)/2.0)
2103 /* iterative version */
2105 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2108 register double xmid
, ymid
;
2109 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2112 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2114 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2115 xmid
= (double)half(x2
, x3
);
2116 ymid
= (double)half(y2
, y3
);
2117 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2118 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2119 wx_spline_add_point( x1
, y1
);
2120 wx_spline_add_point( xmid
, ymid
);
2122 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2123 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2124 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2125 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2130 /* utilities used by spline drawing routines */
2132 typedef struct wx_spline_stack_struct
{
2133 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2136 #define SPLINE_STACK_DEPTH 20
2137 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2138 static Stack
*wx_stack_top
;
2139 static int wx_stack_count
;
2141 void wx_clear_stack()
2143 wx_stack_top
= wx_spline_stack
;
2147 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2149 wx_stack_top
->x1
= x1
;
2150 wx_stack_top
->y1
= y1
;
2151 wx_stack_top
->x2
= x2
;
2152 wx_stack_top
->y2
= y2
;
2153 wx_stack_top
->x3
= x3
;
2154 wx_stack_top
->y3
= y3
;
2155 wx_stack_top
->x4
= x4
;
2156 wx_stack_top
->y4
= y4
;
2161 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2162 double *x3
, double *y3
, double *x4
, double *y4
)
2164 if (wx_stack_count
== 0)
2168 *x1
= wx_stack_top
->x1
;
2169 *y1
= wx_stack_top
->y1
;
2170 *x2
= wx_stack_top
->x2
;
2171 *y2
= wx_stack_top
->y2
;
2172 *x3
= wx_stack_top
->x3
;
2173 *y3
= wx_stack_top
->y3
;
2174 *x4
= wx_stack_top
->x4
;
2175 *y4
= wx_stack_top
->y4
;
2179 static bool wx_spline_add_point(double x
, double y
)
2181 wxPoint
*point
= new wxPoint
;
2184 wx_spline_point_list
.Append((wxObject
*)point
);
2188 static void wx_spline_draw_point_array(wxDC
*dc
)
2190 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2191 wxNode
*node
= wx_spline_point_list
.First();
2194 wxPoint
*point
= (wxPoint
*)node
->Data();
2197 node
= wx_spline_point_list
.First();
2201 void wxWindowDC::DoDrawSpline( wxList
*points
)
2203 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2206 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2207 double x1
, y1
, x2
, y2
;
2209 wxNode
*node
= points
->First();
2210 p
= (wxPoint
*)node
->Data();
2215 node
= node
->Next();
2216 p
= (wxPoint
*)node
->Data();
2220 cx1
= (double)((x1
+ x2
) / 2);
2221 cy1
= (double)((y1
+ y2
) / 2);
2222 cx2
= (double)((cx1
+ x2
) / 2);
2223 cy2
= (double)((cy1
+ y2
) / 2);
2225 wx_spline_add_point(x1
, y1
);
2227 while ((node
= node
->Next()) != NULL
)
2229 p
= (wxPoint
*)node
->Data();
2234 cx4
= (double)(x1
+ x2
) / 2;
2235 cy4
= (double)(y1
+ y2
) / 2;
2236 cx3
= (double)(x1
+ cx4
) / 2;
2237 cy3
= (double)(y1
+ cy4
) / 2;
2239 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2243 cx2
= (double)(cx1
+ x2
) / 2;
2244 cy2
= (double)(cy1
+ y2
) / 2;
2247 wx_spline_add_point( cx1
, cy1
);
2248 wx_spline_add_point( x2
, y2
);
2250 wx_spline_draw_point_array( this );
2253 #endif // wxUSE_SPLINE
2257 // ----------------------------------------------------------------------------
2259 // ----------------------------------------------------------------------------
2261 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2263 wxRegion
* region
= NULL
;
2265 // Combine all the update rects into a region
2266 const wxRectList
& updateRects(win
->GetUpdateRects());
2267 if ( updateRects
.GetCount() != 0 )
2269 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2271 node
= node
->GetNext() )
2273 wxRect
* rect
= node
->GetData();
2276 region
= new wxRegion(*rect
);
2278 // TODO: is this correct? In SetDCClipping above,
2279 // XIntersectRegion is used to combine paint and user
2280 // regions. XIntersectRegion appears to work in that case...
2281 region
->Union(*rect
);
2287 win
->GetClientSize(&cw
, &ch
);
2288 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2291 win
->SetUpdateRegion(*region
);
2293 wxRegion
& theRegion(win
->GetUpdateRegion());
2294 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2296 // Set the clipping region. Any user-defined region will be combined with this
2297 // one in SetDCClipping.
2298 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2303 wxPaintDC::~wxPaintDC()
2305 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2307 m_window
->ClearUpdateRegion();
2310 // ----------------------------------------------------------------------------
2311 // private functions
2312 // ----------------------------------------------------------------------------
2315 Used when copying between drawables on different (Display*) m_displays. Not
2316 very fast, but better than giving up.
2319 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2320 Drawable src
, Drawable dest
,
2323 unsigned int w
, unsigned int h
,
2324 int destx
, int desty
,
2325 bool more
, XImage
**cache
)
2327 XImage
*image
, *destimage
;
2328 Colormap destcm
, srccm
;
2329 static const int CACHE_SIZE
= 256;
2332 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2333 int k
, cache_pos
, all_cache
;
2335 if (!cache
|| !*cache
)
2336 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2340 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2342 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2343 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2348 for (i
= 0; i
< w
; i
++)
2349 for (j
= 0; j
< h
; j
++) {
2350 unsigned long pixel
;
2353 pixel
= XGetPixel(image
, i
, j
);
2354 for (k
= cache_pos
; k
--; )
2355 if (cachesrc
[k
] == pixel
) {
2356 pixel
= cachedest
[k
];
2360 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2361 if (cachesrc
[k
] == pixel
) {
2362 pixel
= cachedest
[k
];
2366 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2367 XQueryColor(src_display
, srccm
, &xcol
);
2368 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2370 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2372 if (++cache_pos
>= CACHE_SIZE
) {
2378 XPutPixel(destimage
, i
, j
, pixel
);
2381 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2382 XDestroyImage(destimage
);
2387 XDestroyImage(image
);
2392 /* Helper function for 16-bit fonts */
2393 static int str16len(const char *s
)
2397 while (s
[0] && s
[1]) {