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"
53 #include "wx/motif/private.h"
62 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 #define RAD2DEG 57.2957795131
70 // Fudge factor (VZ: what??)
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 #if !USE_SHARED_LIBRARY
78 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
79 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
80 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
88 Drawable src
, Drawable dest
,
91 unsigned int w
, unsigned int h
,
93 bool more
, XImage
**cache
);
95 // ============================================================================
97 // ============================================================================
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 wxWindowDC::wxWindowDC()
106 m_gcBacking
= (WXGC
) 0;
108 m_backgroundPixel
= -1;
109 m_currentPenWidth
= 1;
110 m_currentPenJoin
= -1;
111 m_currentPenDashCount
= -1;
112 m_currentPenDash
= (char*) NULL
;
115 // m_currentBkMode = wxTRANSPARENT;
116 m_colour
= wxColourDisplay();
117 m_display
= (WXDisplay
*) NULL
;
118 m_currentRegion
= (WXRegion
) 0;
119 m_userRegion
= (WXRegion
) 0;
120 m_pixmap
= (WXPixmap
) 0;
122 m_oldFont
= (WXFont
) 0;
125 wxWindowDC::wxWindowDC( wxWindow
*window
)
127 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
130 m_font
= window
->GetFont();
132 m_gcBacking
= (WXGC
) 0;
133 m_backgroundPixel
= -1;
134 m_currentPenWidth
= 1;
135 m_currentPenJoin
= -1;
136 m_currentPenDashCount
= -1;
137 m_currentPenDash
= (char*) NULL
;
140 // m_currentBkMode = wxTRANSPARENT;
141 m_colour
= wxColourDisplay();
142 m_currentRegion
= (WXRegion
) 0;
143 m_userRegion
= (WXRegion
) 0;
147 m_display
= window
->GetXDisplay();
148 m_pixmap
= window
->GetXWindow();
149 Display
* display
= (Display
*) m_display
;
151 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
154 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
155 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
156 gcvalues
.graphics_exposures
= False
;
157 gcvalues
.line_width
= 1;
158 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
159 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
162 if (m_window
->GetBackingPixmap())
164 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
165 DefaultScreen (display
)),
166 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
170 m_backgroundPixel
= (int) gcvalues
.background
;
172 // Get the current Font so we can set it back later
174 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
175 m_oldFont
= (WXFont
) valReturn
.font
;
177 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
180 wxWindowDC::~wxWindowDC()
182 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
184 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
186 if (m_window
&& m_window
->GetBackingPixmap())
187 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
191 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
195 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
196 m_gcBacking
= (WXGC
) 0;
199 XDestroyRegion ((Region
) m_currentRegion
);
200 m_currentRegion
= (WXRegion
) 0;
203 XDestroyRegion ((Region
) m_userRegion
);
204 m_userRegion
= (WXRegion
) 0;
207 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
208 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
210 wxFAIL_MSG("not implemented");
213 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
215 wxFAIL_MSG("not implemented");
220 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
222 wxCHECK_RET( Ok(), "invalid dc" );
224 int x1d
, y1d
, x2d
, y2d
;
226 // FreeGetPixelCache();
236 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
238 if (m_window
&& m_window
->GetBackingPixmap())
239 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
240 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
241 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
243 CalcBoundingBox(x1
, y1
);
244 CalcBoundingBox(x2
, y2
);
247 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
249 wxCHECK_RET( Ok(), "invalid dc" );
254 int xx
= XLOG2DEV (x
);
255 int yy
= YLOG2DEV (y
);
257 wxDisplaySize (&ww
, &hh
);
258 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
260 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
263 if (m_window
&& m_window
->GetBackingPixmap())
267 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
270 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
276 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
278 wxCHECK_RET( Ok(), "invalid dc" );
280 // FreeGetPixelCache();
282 int xx1
= XLOG2DEV (x1
);
283 int yy1
= YLOG2DEV (y1
);
284 int xx2
= XLOG2DEV (x2
);
285 int yy2
= YLOG2DEV (y2
);
286 int xxc
= XLOG2DEV (xc
);
287 int yyc
= YLOG2DEV (yc
);
288 int xxc_2
= XLOG2DEV_2 (xc
);
289 int yyc_2
= YLOG2DEV_2 (yc
);
291 wxCoord dx
= xx1
- xxc
;
292 wxCoord dy
= yy1
- yyc
;
293 double radius
= sqrt (dx
* dx
+ dy
* dy
);
294 wxCoord r
= (wxCoord
) radius
;
296 double radius1
, radius2
;
298 if (xx1
== xx2
&& yy1
== yy2
)
303 else if (radius
== 0.0)
304 radius1
= radius2
= 0.0;
313 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
321 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
325 int alpha1
= (int) radius1
;
326 int alpha2
= (int) (radius2
- radius1
);
329 while (alpha2
> 360 * 64)
332 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
335 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
336 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
338 if (m_window
&& m_window
->GetBackingPixmap())
339 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
340 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
344 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
348 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
349 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
351 if (m_window
&& m_window
->GetBackingPixmap())
352 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
353 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
355 CalcBoundingBox (x1
, y1
);
356 CalcBoundingBox (x2
, y2
);
359 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
361 wxCHECK_RET( Ok(), "invalid dc" );
367 wd
= XLOG2DEVREL(width
);
368 hd
= YLOG2DEVREL(height
);
370 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
371 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
372 int start
= int(sa
*64);
373 int end
= int(ea
*64);
374 if (start
<0) start
+=360*64;
375 if (end
<0) end
+=360*64;
376 if (end
>start
) end
-=start
;
377 else end
+=360*64-start
;
379 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
381 m_autoSetting
= TRUE
; // must be reset
384 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
386 if (m_window
&& m_window
->GetBackingPixmap())
387 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
388 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
391 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
395 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
396 if (m_window
&& m_window
->GetBackingPixmap())
397 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
398 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
400 CalcBoundingBox (x
, y
);
401 CalcBoundingBox (x
+ width
, y
+ height
);
404 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
406 wxCHECK_RET( Ok(), "invalid dc" );
408 // FreeGetPixelCache();
410 if (m_pen
.Ok() && m_autoSetting
)
413 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
414 if (m_window
&& m_window
->GetBackingPixmap())
415 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
417 CalcBoundingBox (x
, y
);
420 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
422 wxCHECK_RET( Ok(), "invalid dc" );
424 // FreeGetPixelCache();
426 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
431 XPoint
*xpoints
= new XPoint
[n
];
434 for (i
= 0; i
< n
; i
++)
436 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
437 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
439 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
441 if (m_window
&& m_window
->GetBackingPixmap())
443 for (i
= 0; i
< n
; i
++)
445 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
446 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
448 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
454 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
455 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
457 wxCHECK_RET( Ok(), "invalid dc" );
459 // FreeGetPixelCache();
461 XPoint
*xpoints1
= new XPoint
[n
+ 1];
462 XPoint
*xpoints2
= new XPoint
[n
+ 1];
464 for (i
= 0; i
< n
; i
++)
466 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
467 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
468 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
469 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
470 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
473 // Close figure for XDrawLines (not needed for XFillPolygon)
474 xpoints1
[i
].x
= xpoints1
[0].x
;
475 xpoints1
[i
].y
= xpoints1
[0].y
;
476 xpoints2
[i
].x
= xpoints2
[0].x
;
477 xpoints2
[i
].y
= xpoints2
[0].y
;
479 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
482 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
483 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
484 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
485 if (m_window
&& m_window
->GetBackingPixmap())
487 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
488 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
489 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
490 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
494 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
498 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
500 if (m_window
&& m_window
->GetBackingPixmap())
501 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
508 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
510 wxCHECK_RET( Ok(), "invalid dc" );
512 // FreeGetPixelCache();
514 int xd
, yd
, wfd
, hfd
, wd
, hd
;
518 wfd
= XLOG2DEVREL(width
);
520 hfd
= YLOG2DEVREL(height
);
523 if (wfd
== 0 || hfd
== 0) return;
524 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
525 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
527 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
530 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
532 if (m_window
&& m_window
->GetBackingPixmap())
533 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
534 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
538 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
542 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
544 if (m_window
&& m_window
->GetBackingPixmap())
545 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
546 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
549 CalcBoundingBox (x
, y
);
550 CalcBoundingBox (x
+ width
, y
+ height
);
553 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
555 wxCHECK_RET( Ok(), "invalid dc" );
557 // FreeGetPixelCache();
559 // If radius is negative, it's a proportion of the smaller dimension.
561 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
563 int xd
= XLOG2DEV (x
);
564 int yd
= YLOG2DEV (y
);
565 int rd
= XLOG2DEVREL ((long) radius
);
566 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
567 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
572 // If radius is zero use DrawRectangle() instead to avoid
573 // X drawing errors with small radii
576 DrawRectangle( x
, y
, width
, height
);
580 // Draw nothing if transformed w or h is 0
581 if (wd
== 0 || hd
== 0) return;
583 // CMB: adjust size if outline is drawn otherwise the result is
584 // 1 pixel too wide and high
585 if (m_pen
.GetStyle() != wxTRANSPARENT
)
591 // CMB: ensure dd is not larger than rectangle otherwise we
592 // get an hour glass shape
593 if (rw_d
> wd
) rw_d
= wd
;
594 if (rw_d
> hd
) rw_d
= hd
;
597 // For backing pixmap
598 int xd2
= XLOG2DEV_2 (x
);
599 int yd2
= YLOG2DEV_2 (y
);
600 int rd2
= XLOG2DEVREL ((long) radius
);
601 int wd2
= XLOG2DEVREL (width
) ;
602 int hd2
= YLOG2DEVREL (height
) ;
607 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
611 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
613 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
616 // Arcs start from 3 o'clock, positive angles anticlockwise
618 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
619 rw_d
, rh_d
, 90 * 64, 90 * 64);
621 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
622 // rw_d, rh_d, 0, 90 * 64);
623 rw_d
, rh_d
, 0, 91 * 64);
625 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
627 // rw_d, rh_d, 270 * 64, 90 * 64);
628 rw_d
, rh_d
, 269 * 64, 92 * 64);
630 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
631 rw_d
, rh_d
, 180 * 64, 90 * 64);
633 if (m_window
&& m_window
->GetBackingPixmap())
635 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
636 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
637 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
638 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
640 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
641 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
642 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
643 xd2
+ wd2
- rw_d2
, yd2
,
644 // rw_d2, rh_d2, 0, 90 * 64);
645 rw_d2
, rh_d2
, 0, 91 * 64);
646 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
649 // rw_d2, rh_d2, 270 * 64, 90 * 64);
650 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
651 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
652 xd2
, yd2
+ hd2
- rh_d2
,
653 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
657 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
660 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
661 xd
+ wd
- rd
+ 1, yd
);
662 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
663 xd
+ wd
- rd
, yd
+ hd
);
665 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
667 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
668 xd
+ wd
, yd
+ hd
- rd
+ 1);
669 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
670 rw_d
, rh_d
, 90 * 64, 90 * 64);
671 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
672 // rw_d, rh_d, 0, 90 * 64);
673 rw_d
, rh_d
, 0, 91 * 64);
674 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
676 rw_d
, rh_d
, 269 * 64, 92 * 64);
677 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
678 rw_d
, rh_d
, 180 * 64, 90 * 64);
680 if (m_window
&& m_window
->GetBackingPixmap())
682 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
684 xd2
+ wd2
- rd2
+ 1, yd2
);
685 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
686 xd2
+ rd2
, yd2
+ hd2
,
687 xd2
+ wd2
- rd2
, yd2
+ hd2
);
689 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
691 xd2
, yd2
+ hd2
- rd2
);
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
693 xd2
+ wd2
, yd2
+ rd2
,
694 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
695 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
697 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
698 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
699 xd2
+ wd2
- rw_d2
, yd2
,
700 // rw_d2, rh_d2, 0, 90 * 64);
701 rw_d2
, rh_d2
, 0, 91 * 64);
702 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
705 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
707 xd2
, yd2
+ hd2
- rh_d2
,
708 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
711 CalcBoundingBox (x
, y
);
712 CalcBoundingBox (x
+ width
, y
+ height
);
717 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
719 wxCHECK_RET( Ok(), "invalid dc" );
721 // Check for negative width and height
734 // FreeGetPixelCache();
736 static const int angle
= 23040;
742 wd
= XLOG2DEVREL(width
) ;
743 hd
= YLOG2DEVREL(height
) ;
745 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
748 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
749 if (m_window
&& m_window
->GetBackingPixmap())
750 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
751 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
752 XLOG2DEVREL (width
) - WX_GC_CF
,
753 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
756 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
760 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
761 if (m_window
&& m_window
->GetBackingPixmap())
762 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
763 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
764 XLOG2DEVREL (width
) - WX_GC_CF
,
765 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
767 CalcBoundingBox (x
, y
);
768 CalcBoundingBox (x
+ width
, y
+ height
);
772 bool wxWindowDC::CanDrawBitmap() const
774 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
780 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
782 // FreeGetPixelCache();
784 // Be sure that foreground pixels (1) of
785 // the Icon will be painted with pen colour. [m_pen.SetColour()]
786 // Background pixels (0) will be painted with
787 // last selected background color. [::SetBackground]
788 if (m_pen
.Ok() && m_autoSetting
)
792 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
793 width
= icon
.GetWidth();
794 height
= icon
.GetHeight();
795 if (icon
.GetDisplay() == m_display
)
797 if (icon
.GetDepth() <= 1)
799 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
801 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
805 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
807 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
811 if (m_window
&& m_window
->GetBackingPixmap())
813 if (icon
.GetDepth() <= 1)
815 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
816 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
820 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
822 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
825 } else { /* Remote copy (different (Display*) m_displays) */
826 XImage
*cache
= NULL
;
827 if (m_window
&& m_window
->GetBackingPixmap())
828 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
829 (GC
) m_gcBacking
, 0, 0, width
, height
,
830 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
831 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
833 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
835 CalcBoundingBox (x
, y
);
839 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
840 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
841 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
843 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
845 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
847 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
849 // FreeGetPixelCache();
851 // Be sure that foreground pixels (1) of the Icon will be painted with pen
852 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
853 // last selected background color. [::SetBackground]
854 if (m_pen
.Ok() && m_autoSetting
)
857 // Do bitmap scaling if necessary
859 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
860 Pixmap sourcePixmap
= (Pixmap
) NULL
;
861 double scaleX
, scaleY
;
862 GetUserScale(& scaleX
, & scaleY
);
864 // Sorry, can't scale masks just yet
865 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
867 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
868 wxBitmap
& bitmap
= memDC
->GetBitmap();
870 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
872 wxImage
image(bitmap
);
875 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
879 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
880 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
882 image
= image
.Scale(scaledW
, scaledH
);
883 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
884 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
888 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
890 if (m_pixmap
&& sourcePixmap
)
893 int orig
= m_logicalFunction
;
895 SetLogicalFunction (rop
);
897 if (m_display
!= sourceDC
->m_display
)
899 XImage
*cache
= NULL
;
901 if (m_window
&& m_window
->GetBackingPixmap())
902 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
903 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
905 source
->LogicalToDeviceX (xsrc
),
906 source
->LogicalToDeviceY (ysrc
),
907 source
->LogicalToDeviceXRel(width
),
908 source
->LogicalToDeviceYRel(height
),
909 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
912 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
914 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
915 wxBitmap
& sel
= memDC
->GetBitmap();
916 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
918 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
919 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
923 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
924 source
->LogicalToDeviceX (xsrc
),
925 source
->LogicalToDeviceY (ysrc
),
926 source
->LogicalToDeviceXRel(width
),
927 source
->LogicalToDeviceYRel(height
),
928 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
933 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
934 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
939 if (m_window
&& m_window
->GetBackingPixmap())
941 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
942 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
944 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
945 source
->LogicalToDeviceX (xsrc
),
946 source
->LogicalToDeviceY (ysrc
),
947 source
->LogicalToDeviceXRel(width
),
948 source
->LogicalToDeviceYRel(height
),
949 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
953 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
954 source
->LogicalToDeviceX (xsrc
),
955 source
->LogicalToDeviceY (ysrc
),
956 source
->LogicalToDeviceXRel(width
),
957 source
->LogicalToDeviceYRel(height
),
958 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
961 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
963 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
964 wxBitmap
& sel
= memDC
->GetBitmap();
965 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
967 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
968 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
972 // Check if we're copying from a mono bitmap
973 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
974 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
976 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
977 source
->LogicalToDeviceX (xsrc
),
978 source
->LogicalToDeviceY (ysrc
),
979 source
->LogicalToDeviceXRel(width
),
980 source
->LogicalToDeviceYRel(height
),
981 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
985 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
986 source
->LogicalToDeviceX (xsrc
),
987 source
->LogicalToDeviceY (ysrc
),
988 source
->LogicalToDeviceXRel(width
),
989 source
->LogicalToDeviceYRel(height
),
990 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
995 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
996 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
999 } /* Remote/local (Display*) m_display */
1000 CalcBoundingBox (xdest
, ydest
);
1001 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1003 SetLogicalFunction(orig
);
1005 if (scaledBitmap
) delete scaledBitmap
;
1009 if (scaledBitmap
) delete scaledBitmap
;
1014 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1016 wxCHECK_RET( Ok(), "invalid dc" );
1018 // Since X draws from the baseline of the text, must add the text height
1024 slen
= strlen(text
);
1028 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1029 int direction
, descent
;
1030 XCharStruct overall_return
;
1033 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1034 &ascent
, &descent
, &overall_return
);
1037 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1038 &ascent
, &descent
, &overall_return
);
1040 cx
= overall_return
.width
;
1041 cy
= ascent
+ descent
;
1044 // First draw a rectangle representing the text background, if a text
1045 // background is specified
1046 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1048 wxColour oldPenColour
= m_currentColour
;
1049 m_currentColour
= m_textBackgroundColour
;
1050 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1051 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1052 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1053 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1055 // This separation of the big && test required for gcc2.7/HP UX 9.02
1056 // or pixel value can be corrupted!
1057 sameColour
= (sameColour
&&
1058 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1060 if (!sameColour
|| !GetOptimization())
1062 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1063 m_currentColour
= m_textBackgroundColour
;
1065 // Set the GC to the required colour
1068 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1069 if (m_window
&& m_window
->GetBackingPixmap())
1070 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1074 m_textBackgroundColour
= oldPenColour
;
1076 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1077 if (m_window
&& m_window
->GetBackingPixmap())
1078 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1079 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1082 // Now set the text foreground and draw the text
1083 if (m_textForegroundColour
.Ok ())
1085 wxColour oldPenColour
= m_currentColour
;
1086 m_currentColour
= m_textForegroundColour
;
1087 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1088 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1089 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1090 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1091 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1093 if (!sameColour
|| !GetOptimization())
1096 if (!m_colour
) // Mono display
1098 // Unless foreground is really white, draw it in black
1099 unsigned char red
= m_textForegroundColour
.Red ();
1100 unsigned char blue
= m_textForegroundColour
.Blue ();
1101 unsigned char green
= m_textForegroundColour
.Green ();
1102 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1103 && green
== (unsigned char) 255)
1105 m_currentColour
= *wxWHITE
;
1106 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1107 m_currentColour
.SetPixel(pixel
);
1108 m_textForegroundColour
.SetPixel(pixel
);
1112 m_currentColour
= *wxBLACK
;
1113 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1114 m_currentColour
.SetPixel(pixel
);
1115 m_textForegroundColour
.SetPixel(pixel
);
1120 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1121 m_currentColour
.SetPixel(pixel
);
1124 // Set the GC to the required colour
1127 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1128 if (m_window
&& m_window
->GetBackingPixmap())
1129 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1133 m_textForegroundColour
= oldPenColour
;
1136 // We need to add the ascent, not the whole height, since X draws at the
1137 // point above the descender.
1140 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1141 (XChar2b
*)(char*) (const char*) text
, slen
);
1144 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1146 if (m_window
&& m_window
->GetBackingPixmap()) {
1149 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1150 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1151 (XChar2b
*)(char*) (const char*) text
, slen
);
1154 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1155 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1159 GetTextExtent (text
, &w
, &h
);
1160 CalcBoundingBox (x
+ w
, y
+ h
);
1161 CalcBoundingBox (x
, y
);
1164 bool wxWindowDC::CanGetTextExtent() const
1169 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1170 wxCoord
*descent
, wxCoord
*externalLeading
,
1171 wxFont
*font
) const
1173 wxCHECK_RET( Ok(), "invalid dc" );
1175 wxFont
* theFont
= font
;
1177 theFont
= (wxFont
*)&m_font
; // const_cast
1181 // TODO: this should be an error log function
1182 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1184 if (width
) *width
= -1;
1185 if (height
) *height
= -1;
1189 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1191 int direction
, ascent
, descent2
;
1192 XCharStruct overall
;
1197 slen
= str16len(string
);
1200 slen
= strlen(string
);
1204 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1205 &ascent
, &descent2
, &overall
);
1208 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1209 &ascent
, &descent2
, &overall
);
1211 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1212 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1214 *descent
= descent2
;
1215 if (externalLeading
)
1216 *externalLeading
= 0;
1219 wxCoord
wxWindowDC::GetCharWidth() const
1221 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1222 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1224 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1226 int direction
, ascent
, descent
;
1227 XCharStruct overall
;
1228 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1229 &descent
, &overall
);
1230 return XDEV2LOGREL(overall
.width
);
1233 wxCoord
wxWindowDC::GetCharHeight() const
1235 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1236 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1238 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1240 int direction
, ascent
, descent
;
1241 XCharStruct overall
;
1242 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1243 &descent
, &overall
);
1244 // return XDEV2LOGREL(overall.ascent + overall.descent);
1245 return XDEV2LOGREL(ascent
+ descent
);
1248 void wxWindowDC::Clear()
1250 wxCHECK_RET( Ok(), "invalid dc" );
1255 m_window
->GetSize(&w
, &h
);
1257 if (m_window
&& m_window
->GetBackingPixmap())
1259 w
= m_window
->GetPixmapWidth();
1260 h
= m_window
->GetPixmapHeight();
1265 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1267 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1268 w
= memDC
->GetBitmap().GetWidth();
1269 h
= memDC
->GetBitmap().GetHeight();
1275 wxBrush saveBrush
= m_brush
;
1276 SetBrush (m_backgroundBrush
);
1278 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1280 if (m_window
&& m_window
->GetBackingPixmap())
1281 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1283 m_brush
= saveBrush
;
1286 void wxWindowDC::Clear(const wxRect
& rect
)
1288 wxCHECK_RET( Ok(), "invalid dc" );
1290 int x
= rect
.x
; int y
= rect
.y
;
1291 int w
= rect
.width
; int h
= rect
.height
;
1293 wxBrush saveBrush
= m_brush
;
1294 SetBrush (m_backgroundBrush
);
1296 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1298 if (m_window
&& m_window
->GetBackingPixmap())
1299 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1301 m_brush
= saveBrush
;
1304 void wxWindowDC::SetFont( const wxFont
&font
)
1306 wxCHECK_RET( Ok(), "invalid dc" );
1312 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1314 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1316 if (m_window
&& m_window
->GetBackingPixmap())
1317 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1322 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1324 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1325 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1327 if (m_window
&& m_window
->GetBackingPixmap())
1328 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1331 void wxWindowDC::SetPen( const wxPen
&pen
)
1333 wxCHECK_RET( Ok(), "invalid dc" );
1339 wxBitmap oldStipple
= m_currentStipple
;
1340 int oldStyle
= m_currentStyle
;
1341 int oldFill
= m_currentFill
;
1342 int old_pen_width
= m_currentPenWidth
;
1343 int old_pen_join
= m_currentPenJoin
;
1344 int old_pen_cap
= m_currentPenCap
;
1345 int old_pen_nb_dash
= m_currentPenDashCount
;
1346 char *old_pen_dash
= m_currentPenDash
;
1348 wxColour oldPenColour
= m_currentColour
;
1349 m_currentColour
= m_pen
.GetColour ();
1350 m_currentStyle
= m_pen
.GetStyle ();
1351 m_currentFill
= m_pen
.GetStyle (); // TODO?
1352 m_currentPenWidth
= m_pen
.GetWidth ();
1353 m_currentPenJoin
= m_pen
.GetJoin ();
1354 m_currentPenCap
= m_pen
.GetCap ();
1355 m_currentPenDashCount
= m_pen
.GetDashCount();
1356 m_currentPenDash
= m_pen
.GetDash();
1358 if (m_currentStyle
== wxSTIPPLE
)
1359 m_currentStipple
= * m_pen
.GetStipple ();
1361 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1362 oldFill
== m_currentFill
&&
1363 old_pen_join
== m_currentPenJoin
&&
1364 old_pen_cap
== m_currentPenCap
&&
1365 old_pen_nb_dash
== m_currentPenDashCount
&&
1366 old_pen_dash
== m_currentPenDash
&&
1367 old_pen_width
== m_currentPenWidth
);
1369 bool sameColour
= (oldPenColour
.Ok () &&
1370 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1371 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1372 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1373 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1375 if (!sameStyle
|| !GetOptimization())
1377 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1378 if (scaled_width
< 0)
1384 const static char dotted
[] = {2, 5};
1385 const static char short_dashed
[] = {4, 4};
1386 const static char long_dashed
[] = {4, 8};
1387 const static char dotted_dashed
[] = {6, 6, 2, 6};
1389 // We express dash pattern in pen width unit, so we are
1390 // independent of zoom factor and so on...
1392 const char *req_dash
;
1394 switch (m_pen
.GetStyle ())
1397 req_nb_dash
= m_currentPenDashCount
;
1398 req_dash
= m_currentPenDash
;
1399 style
= LineOnOffDash
;
1404 style
= LineOnOffDash
;
1408 req_dash
= short_dashed
;
1409 style
= LineOnOffDash
;
1413 req_dash
= long_dashed
;
1414 style
= LineOnOffDash
;
1418 req_dash
= dotted_dashed
;
1419 style
= LineOnOffDash
;
1430 if (req_dash
&& req_nb_dash
)
1432 char *real_req_dash
= new char[req_nb_dash
];
1435 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1436 for (int i
= 0; i
< req_nb_dash
; i
++)
1437 real_req_dash
[i
] = req_dash
[i
] * factor
;
1438 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1440 if (m_window
&& m_window
->GetBackingPixmap())
1441 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1442 delete[]real_req_dash
;
1446 // No Memory. We use non-scaled dash pattern...
1447 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1449 if (m_window
&& m_window
->GetBackingPixmap())
1450 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1454 switch (m_pen
.GetCap ())
1456 case wxCAP_PROJECTING
:
1457 cap
= CapProjecting
;
1464 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1468 switch (m_pen
.GetJoin ())
1482 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1484 if (m_window
&& m_window
->GetBackingPixmap())
1485 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1488 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1492 oldStipple
= wxNullBitmap
; // For later reset!!
1494 switch (m_currentFill
)
1496 case wxBDIAGONAL_HATCH
:
1497 if (bdiag
== (Pixmap
) 0)
1498 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1499 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1500 bdiag_bits
, bdiag_width
, bdiag_height
);
1503 case wxFDIAGONAL_HATCH
:
1504 if (fdiag
== (Pixmap
) 0)
1505 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1506 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1507 fdiag_bits
, fdiag_width
, fdiag_height
);
1511 if (cross
== (Pixmap
) 0)
1512 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1513 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1514 cross_bits
, cross_width
, cross_height
);
1517 case wxHORIZONTAL_HATCH
:
1518 if (horiz
== (Pixmap
) 0)
1519 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1520 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1521 horiz_bits
, horiz_width
, horiz_height
);
1524 case wxVERTICAL_HATCH
:
1525 if (verti
== (Pixmap
) 0)
1526 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1527 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1528 verti_bits
, verti_width
, verti_height
);
1531 case wxCROSSDIAG_HATCH
:
1533 if (cdiag
== (Pixmap
) 0)
1534 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1535 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1536 cdiag_bits
, cdiag_width
, cdiag_height
);
1540 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1542 if (m_window
&& m_window
->GetBackingPixmap())
1543 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1545 else if (m_currentStipple
.Ok()
1546 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1548 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1550 if (m_window
&& m_window
->GetBackingPixmap())
1551 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1554 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1558 if (m_currentFill
== wxSTIPPLE
)
1559 fill_style
= FillStippled
;
1560 else if (IS_HATCH (m_currentFill
))
1561 fill_style
= FillStippled
;
1563 fill_style
= FillSolid
;
1564 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1565 if (m_window
&& m_window
->GetBackingPixmap())
1566 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1569 // must test m_logicalFunction, because it involves background!
1570 if (!sameColour
|| !GetOptimization()
1571 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1574 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1575 pixel
= m_backgroundPixel
;
1578 unsigned char red
= m_pen
.GetColour ().Red ();
1579 unsigned char blue
= m_pen
.GetColour ().Blue ();
1580 unsigned char green
= m_pen
.GetColour ().Green ();
1581 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1582 && green
== (unsigned char) 255)
1584 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1585 m_currentColour
= *wxWHITE
;
1586 m_pen
.GetColour().SetPixel(pixel
);
1587 m_currentColour
.SetPixel(pixel
);
1591 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1592 m_currentColour
= *wxBLACK
;
1593 m_pen
.GetColour().SetPixel(pixel
);
1598 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1599 m_currentColour
.SetPixel(pixel
);
1602 // Finally, set the GC to the required colour
1605 if (m_logicalFunction
== wxXOR
)
1608 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1609 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1610 if (m_window
&& m_window
->GetBackingPixmap())
1611 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1615 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1616 if (m_window
&& m_window
->GetBackingPixmap())
1617 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1622 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1627 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1629 wxCHECK_RET( Ok(), "invalid dc" );
1633 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1636 int oldFill
= m_currentFill
;
1637 wxBitmap oldStipple
= m_currentStipple
;
1639 m_autoSetting
|= 0x1;
1641 m_currentFill
= m_brush
.GetStyle ();
1642 if (m_currentFill
== wxSTIPPLE
)
1643 m_currentStipple
= * m_brush
.GetStipple ();
1645 wxColour
oldBrushColour(m_currentColour
);
1646 m_currentColour
= m_brush
.GetColour ();
1648 bool sameColour
= (oldBrushColour
.Ok () &&
1649 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1650 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1651 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1652 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1654 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1656 switch (brush
.GetStyle ())
1660 case wxBDIAGONAL_HATCH
:
1661 case wxCROSSDIAG_HATCH
:
1662 case wxFDIAGONAL_HATCH
:
1664 case wxHORIZONTAL_HATCH
:
1665 case wxVERTICAL_HATCH
:
1668 // Chris Breeze 23/07/97: use background mode to determine whether
1669 // fill style should be solid or transparent
1670 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1671 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1672 if (m_window
&& m_window
->GetBackingPixmap())
1673 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1678 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1679 if (m_window
&& m_window
->GetBackingPixmap())
1680 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1684 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1688 switch (m_currentFill
)
1690 case wxBDIAGONAL_HATCH
:
1691 if (bdiag
== (Pixmap
) 0)
1692 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1693 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1694 bdiag_bits
, bdiag_width
, bdiag_height
);
1697 case wxFDIAGONAL_HATCH
:
1698 if (fdiag
== (Pixmap
) 0)
1699 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1700 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1701 fdiag_bits
, fdiag_width
, fdiag_height
);
1705 if (cross
== (Pixmap
) 0)
1706 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1707 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1708 cross_bits
, cross_width
, cross_height
);
1711 case wxHORIZONTAL_HATCH
:
1712 if (horiz
== (Pixmap
) 0)
1713 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1714 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1715 horiz_bits
, horiz_width
, horiz_height
);
1718 case wxVERTICAL_HATCH
:
1719 if (verti
== (Pixmap
) 0)
1720 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1721 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1722 verti_bits
, verti_width
, verti_height
);
1725 case wxCROSSDIAG_HATCH
:
1727 if (cdiag
== (Pixmap
) 0)
1728 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1729 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1730 cdiag_bits
, cdiag_width
, cdiag_height
);
1734 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1736 if (m_window
&& m_window
->GetBackingPixmap())
1737 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1739 // X can forget the stipple value when resizing a window (apparently)
1740 // so always set the stipple.
1741 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1743 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1744 if (m_window
&& m_window
->GetBackingPixmap())
1745 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1748 // must test m_logicalFunction, because it involves background!
1749 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1754 // Policy - on a monochrome screen, all brushes are white,
1755 // except when they're REALLY black!!!
1756 unsigned char red
= m_brush
.GetColour ().Red ();
1757 unsigned char blue
= m_brush
.GetColour ().Blue ();
1758 unsigned char green
= m_brush
.GetColour ().Green ();
1760 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1761 && green
== (unsigned char) 0)
1763 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1764 m_currentColour
= *wxBLACK
;
1765 m_brush
.GetColour().SetPixel(pixel
);
1766 m_currentColour
.SetPixel(pixel
);
1770 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1771 m_currentColour
= *wxWHITE
;
1772 m_brush
.GetColour().SetPixel(pixel
);
1773 m_currentColour
.SetPixel(pixel
);
1776 // N.B. comment out the above line and uncomment the following lines
1777 // if you want non-white colours to be black on a monochrome display.
1779 if (red == (unsigned char )255 && blue == (unsigned char)255
1780 && green == (unsigned char)255)
1781 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1783 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1786 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1788 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1789 m_currentColour
.SetPixel(pixel
);
1793 // Finally, set the GC to the required colour
1794 if (m_logicalFunction
== wxXOR
)
1797 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1798 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1799 if (m_window
&& m_window
->GetBackingPixmap())
1800 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1804 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1805 if (m_window
&& m_window
->GetBackingPixmap())
1806 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1811 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1814 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1816 wxCHECK_RET( Ok(), "invalid dc" );
1818 m_backgroundBrush
= brush
;
1820 if (!m_backgroundBrush
.Ok())
1823 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1825 // New behaviour, 10/2/99: setting the background brush of a DC
1826 // doesn't affect the window background colour.
1828 // XSetWindowBackground doesn't work for non-Window pixmaps
1829 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1830 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1833 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1834 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1835 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1836 if (m_window
&& m_window
->GetBackingPixmap())
1837 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1840 void wxWindowDC::SetLogicalFunction( int function
)
1842 wxCHECK_RET( Ok(), "invalid dc" );
1847 if (m_logicalFunction
== function
)
1853 x_function
= GXclear
;
1859 x_function
= GXinvert
;
1862 x_function
= GXorReverse
;
1865 x_function
= GXandReverse
;
1874 x_function
= GXandInverted
;
1877 x_function
= GXnoop
;
1883 x_function
= GXequiv
;
1886 x_function
= GXcopyInverted
;
1889 x_function
= GXorInverted
;
1892 x_function
= GXnand
;
1899 x_function
= GXcopy
;
1903 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1904 if (m_window
&& m_window
->GetBackingPixmap())
1905 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1907 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1908 /* MATTHEW: [9] Need to redo pen simply */
1909 m_autoSetting
|= 0x2;
1911 m_logicalFunction
= function
;
1915 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1917 wxCHECK_RET( Ok(), "invalid dc" );
1919 if (m_textForegroundColour
== col
)
1922 m_textForegroundColour
= col
;
1926 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1928 wxCHECK_RET( Ok(), "invalid dc" );
1930 if (m_textBackgroundColour
== col
)
1933 m_textBackgroundColour
= col
;
1934 if (!m_textBackgroundColour
.Ok())
1938 void wxWindowDC::SetBackgroundMode( int mode
)
1940 m_backgroundMode
= mode
;
1943 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1948 /* Use GetXColormap */
1949 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1950 (Colormap
) palette
.GetXColormap());
1952 /* Use wxGetMainColormap */
1953 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1954 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1959 void wxWindowDC::SetDCClipping()
1961 // m_userRegion is the region set by calling SetClippingRegion
1963 if (m_currentRegion
)
1964 XDestroyRegion ((Region
) m_currentRegion
);
1966 // We need to take into account
1967 // clipping imposed on a window by a repaint.
1968 // We'll combine it with the user region. But for now,
1969 // just use the currently-defined user clipping region.
1970 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1971 m_currentRegion
= (WXRegion
) XCreateRegion ();
1973 m_currentRegion
= (WXRegion
) NULL
;
1975 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1976 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1977 else if (m_userRegion
)
1978 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1979 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1980 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
1981 (Region
) m_currentRegion
);
1983 if (m_currentRegion
)
1985 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1989 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1994 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1996 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1999 XDestroyRegion ((Region
) m_userRegion
);
2000 m_userRegion
= (WXRegion
) XCreateRegion ();
2004 r
.width
= XLOG2DEVREL(width
);
2005 r
.height
= YLOG2DEVREL(height
);
2006 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2010 // Needs to work differently for Pixmap: without this,
2011 // there's a nasty (Display*) m_display bug. 8/12/94
2012 if (m_window
&& m_window
->GetBackingPixmap())
2014 XRectangle rects
[1];
2015 rects
[0].x
= XLOG2DEV_2(x
);
2016 rects
[0].y
= YLOG2DEV_2(y
);
2017 rects
[0].width
= XLOG2DEVREL(width
);
2018 rects
[0].height
= YLOG2DEVREL(height
);
2019 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2023 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2025 wxRect box
= region
.GetBox();
2027 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2030 XDestroyRegion ((Region
) m_userRegion
);
2031 m_userRegion
= (WXRegion
) XCreateRegion ();
2033 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2037 // Needs to work differently for Pixmap: without this,
2038 // there's a nasty (Display*) m_display bug. 8/12/94
2039 if (m_window
&& m_window
->GetBackingPixmap())
2041 XRectangle rects
[1];
2042 rects
[0].x
= XLOG2DEV_2(box
.x
);
2043 rects
[0].y
= YLOG2DEV_2(box
.y
);
2044 rects
[0].width
= XLOG2DEVREL(box
.width
);
2045 rects
[0].height
= YLOG2DEVREL(box
.height
);
2046 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2051 void wxWindowDC::DestroyClippingRegion()
2053 wxDC::DestroyClippingRegion();
2056 XDestroyRegion ((Region
) m_userRegion
);
2057 m_userRegion
= NULL
;
2062 gc_val
.clip_mask
= None
;
2063 if (m_window
&& m_window
->GetBackingPixmap())
2064 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2067 // Resolution in pixels per logical inch
2068 wxSize
wxWindowDC::GetPPI() const
2070 return wxSize(100, 100);
2073 int wxWindowDC::GetDepth() const
2080 // ----------------------------------- spline code ----------------------------------------
2082 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2083 double a3
, double b3
, double a4
, double b4
);
2084 void wx_clear_stack();
2085 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2086 double *y3
, double *x4
, double *y4
);
2087 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2088 double x4
, double y4
);
2089 static bool wx_spline_add_point(double x
, double y
);
2090 static void wx_spline_draw_point_array(wxDC
*dc
);
2092 wxList wx_spline_point_list
;
2094 #define half(z1, z2) ((z1+z2)/2.0)
2097 /* iterative version */
2099 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2102 register double xmid
, ymid
;
2103 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2106 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2108 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2109 xmid
= (double)half(x2
, x3
);
2110 ymid
= (double)half(y2
, y3
);
2111 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2112 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2113 wx_spline_add_point( x1
, y1
);
2114 wx_spline_add_point( xmid
, ymid
);
2116 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2117 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2118 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2119 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2124 /* utilities used by spline drawing routines */
2126 typedef struct wx_spline_stack_struct
{
2127 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2130 #define SPLINE_STACK_DEPTH 20
2131 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2132 static Stack
*wx_stack_top
;
2133 static int wx_stack_count
;
2135 void wx_clear_stack()
2137 wx_stack_top
= wx_spline_stack
;
2141 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2143 wx_stack_top
->x1
= x1
;
2144 wx_stack_top
->y1
= y1
;
2145 wx_stack_top
->x2
= x2
;
2146 wx_stack_top
->y2
= y2
;
2147 wx_stack_top
->x3
= x3
;
2148 wx_stack_top
->y3
= y3
;
2149 wx_stack_top
->x4
= x4
;
2150 wx_stack_top
->y4
= y4
;
2155 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2156 double *x3
, double *y3
, double *x4
, double *y4
)
2158 if (wx_stack_count
== 0)
2162 *x1
= wx_stack_top
->x1
;
2163 *y1
= wx_stack_top
->y1
;
2164 *x2
= wx_stack_top
->x2
;
2165 *y2
= wx_stack_top
->y2
;
2166 *x3
= wx_stack_top
->x3
;
2167 *y3
= wx_stack_top
->y3
;
2168 *x4
= wx_stack_top
->x4
;
2169 *y4
= wx_stack_top
->y4
;
2173 static bool wx_spline_add_point(double x
, double y
)
2175 wxPoint
*point
= new wxPoint
;
2178 wx_spline_point_list
.Append((wxObject
*)point
);
2182 static void wx_spline_draw_point_array(wxDC
*dc
)
2184 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2185 wxNode
*node
= wx_spline_point_list
.First();
2188 wxPoint
*point
= (wxPoint
*)node
->Data();
2191 node
= wx_spline_point_list
.First();
2195 void wxWindowDC::DoDrawSpline( wxList
*points
)
2197 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2200 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2201 double x1
, y1
, x2
, y2
;
2203 wxNode
*node
= points
->First();
2204 p
= (wxPoint
*)node
->Data();
2209 node
= node
->Next();
2210 p
= (wxPoint
*)node
->Data();
2214 cx1
= (double)((x1
+ x2
) / 2);
2215 cy1
= (double)((y1
+ y2
) / 2);
2216 cx2
= (double)((cx1
+ x2
) / 2);
2217 cy2
= (double)((cy1
+ y2
) / 2);
2219 wx_spline_add_point(x1
, y1
);
2221 while ((node
= node
->Next()) != NULL
)
2223 p
= (wxPoint
*)node
->Data();
2228 cx4
= (double)(x1
+ x2
) / 2;
2229 cy4
= (double)(y1
+ y2
) / 2;
2230 cx3
= (double)(x1
+ cx4
) / 2;
2231 cy3
= (double)(y1
+ cy4
) / 2;
2233 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2237 cx2
= (double)(cx1
+ x2
) / 2;
2238 cy2
= (double)(cy1
+ y2
) / 2;
2241 wx_spline_add_point( cx1
, cy1
);
2242 wx_spline_add_point( x2
, y2
);
2244 wx_spline_draw_point_array( this );
2247 #endif // wxUSE_SPLINE
2251 // ----------------------------------------------------------------------------
2253 // ----------------------------------------------------------------------------
2255 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2257 wxRegion
* region
= NULL
;
2259 // Combine all the update rects into a region
2260 const wxRectList
& updateRects(win
->GetUpdateRects());
2261 if ( updateRects
.GetCount() != 0 )
2263 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2265 node
= node
->GetNext() )
2267 wxRect
* rect
= node
->GetData();
2270 region
= new wxRegion(*rect
);
2272 // TODO: is this correct? In SetDCClipping above,
2273 // XIntersectRegion is used to combine paint and user
2274 // regions. XIntersectRegion appears to work in that case...
2275 region
->Union(*rect
);
2281 win
->GetClientSize(&cw
, &ch
);
2282 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2285 win
->SetUpdateRegion(*region
);
2287 // Set the clipping region. Any user-defined region will be combined with this
2288 // one in SetDCClipping.
2289 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2294 wxPaintDC::~wxPaintDC()
2296 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2298 m_window
->ClearUpdateRegion();
2301 // ----------------------------------------------------------------------------
2302 // private functions
2303 // ----------------------------------------------------------------------------
2306 Used when copying between drawables on different (Display*) m_displays. Not
2307 very fast, but better than giving up.
2310 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2311 Drawable src
, Drawable dest
,
2314 unsigned int w
, unsigned int h
,
2315 int destx
, int desty
,
2316 bool more
, XImage
**cache
)
2318 XImage
*image
, *destimage
;
2319 Colormap destcm
, srccm
;
2320 static const int CACHE_SIZE
= 256;
2323 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2324 int k
, cache_pos
, all_cache
;
2326 if (!cache
|| !*cache
)
2327 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2331 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2333 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2334 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2339 for (i
= 0; i
< w
; i
++)
2340 for (j
= 0; j
< h
; j
++) {
2341 unsigned long pixel
;
2344 pixel
= XGetPixel(image
, i
, j
);
2345 for (k
= cache_pos
; k
--; )
2346 if (cachesrc
[k
] == pixel
) {
2347 pixel
= cachedest
[k
];
2351 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2352 if (cachesrc
[k
] == pixel
) {
2353 pixel
= cachedest
[k
];
2357 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2358 XQueryColor(src_display
, srccm
, &xcol
);
2359 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2361 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2363 if (++cache_pos
>= CACHE_SIZE
) {
2369 XPutPixel(destimage
, i
, j
, pixel
);
2372 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2373 XDestroyImage(destimage
);
2378 XDestroyImage(image
);
2383 /* Helper function for 16-bit fonts */
2384 static int str16len(const char *s
)
2388 while (s
[0] && s
[1]) {