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
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend on
18 the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
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 // ----------------------------------------------------------------------------
39 // For compilers that support precompilation, includes "wx.h".
40 #include "wx/wxprec.h"
42 #include "wx/dcclient.h"
43 #include "wx/dcmemory.h"
44 #include "wx/window.h"
51 #pragma message disable nosimpint
55 #pragma message enable nosimpint
58 #include "wx/motif/private.h"
61 #include <float.h> // for M_PI
71 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 // Fudge factor (VZ: what??)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
85 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
89 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
90 // but wxMotif needs it for its internals here
91 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
94 // FIXME: left over after removal of wxDC::GetOptimization()
95 #define GET_OPTIMIZATION false
97 // ----------------------------------------------------------------------------
99 // ----------------------------------------------------------------------------
101 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
102 Drawable src
, Drawable dest
,
105 unsigned int w
, unsigned int h
,
106 int destx
, int desty
,
107 bool more
, XImage
**cache
);
109 // ============================================================================
111 // ============================================================================
114 * compare two doubles and return the larger rounded
117 static int roundmax(double a
, double b
)
119 return (int)((a
> b
? a
: b
) + 0.5);
123 * compare two doubles and return the smaller rounded
126 static int roundmin(double a
, double b
)
128 return (int)((a
< b
? a
: b
) - 0.5);
132 // ----------------------------------------------------------------------------
134 // ----------------------------------------------------------------------------
136 void wxWindowDC::Init()
139 m_gcBacking
= (WXGC
) 0;
141 m_backgroundPixel
= -1;
142 m_currentPenWidth
= 1;
143 m_currentPenJoin
= -1;
144 m_currentPenDashCount
= -1;
145 m_currentPenDash
= (wxX11Dash
*) NULL
;
148 m_colour
= wxColourDisplay();
149 m_display
= (WXDisplay
*) NULL
;
150 m_pixmap
= (WXPixmap
) 0;
152 m_oldFont
= (WXFont
) 0;
154 m_clipRegion
= (WXRegion
) 0;
157 wxWindowDC::wxWindowDC()
162 wxWindowDC::wxWindowDC( wxWindow
*window
)
164 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
169 m_font
= window
->GetFont();
172 m_display
= window
->GetXDisplay();
173 m_pixmap
= window
->GetXWindow();
174 Display
* display
= (Display
*) m_display
;
176 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
179 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
180 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
181 gcvalues
.graphics_exposures
= False
;
182 gcvalues
.subwindow_mode
= IncludeInferiors
;
183 gcvalues
.line_width
= 1;
184 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
185 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
188 if (m_window
->GetBackingPixmap())
190 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
191 DefaultScreen (display
)),
192 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
196 m_backgroundPixel
= (int) gcvalues
.background
;
198 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
201 wxWindowDC::~wxWindowDC()
204 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
208 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
209 m_gcBacking
= (WXGC
) 0;
212 XDestroyRegion ((Region
) m_clipRegion
);
213 m_clipRegion
= (WXRegion
) 0;
216 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
217 const wxColour
& col
, int style
);
219 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
220 const wxColour
& col
, int style
)
222 return wxDoFloodFill(this, x
, y
, col
, style
);
225 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
227 // Generic (and therefore rather inefficient) method.
228 // Could be improved.
230 wxBitmap
bitmap(1, 1);
231 memdc
.SelectObject(bitmap
);
232 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
233 memdc
.SelectObject(wxNullBitmap
);
234 wxImage image
= bitmap
.ConvertToImage();
235 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
239 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
241 wxCHECK_RET( Ok(), "invalid dc" );
243 int x1d
, y1d
, x2d
, y2d
;
253 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
255 if (m_window
&& m_window
->GetBackingPixmap())
256 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
257 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
258 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
260 CalcBoundingBox(x1
, y1
);
261 CalcBoundingBox(x2
, y2
);
264 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
266 wxCHECK_RET( Ok(), "invalid dc" );
271 int xx
= XLOG2DEV (x
);
272 int yy
= YLOG2DEV (y
);
274 wxDisplaySize (&ww
, &hh
);
275 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
277 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
280 if (m_window
&& m_window
->GetBackingPixmap())
284 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
287 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
293 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
295 wxCHECK_RET( Ok(), "invalid dc" );
297 int xx1
= XLOG2DEV (x1
);
298 int yy1
= YLOG2DEV (y1
);
299 int xx2
= XLOG2DEV (x2
);
300 int yy2
= YLOG2DEV (y2
);
301 int xxc
= XLOG2DEV (xc
);
302 int yyc
= YLOG2DEV (yc
);
303 int xxc_2
= XLOG2DEV_2 (xc
);
304 int yyc_2
= YLOG2DEV_2 (yc
);
306 wxCoord dx
= xx1
- xxc
;
307 wxCoord dy
= yy1
- yyc
;
308 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
309 wxCoord r
= (wxCoord
) radius
;
311 double radius1
, radius2
;
313 if (xx1
== xx2
&& yy1
== yy2
)
318 else if (radius
== 0.0)
319 radius1
= radius2
= 0.0;
328 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
336 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
340 int alpha1
= (int) radius1
;
341 int alpha2
= (int) (radius2
- radius1
);
344 while (alpha2
> 360 * 64)
347 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
350 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
351 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
353 if (m_window
&& m_window
->GetBackingPixmap())
354 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
355 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
359 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
363 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
364 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
366 if (m_window
&& m_window
->GetBackingPixmap())
367 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
368 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
370 CalcBoundingBox (x1
, y1
);
371 CalcBoundingBox (x2
, y2
);
374 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
376 wxCHECK_RET( Ok(), "invalid dc" );
382 wd
= XLOG2DEVREL(width
);
383 hd
= YLOG2DEVREL(height
);
385 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
386 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
387 int start
= int(sa
*64);
388 int end
= int(ea
*64);
389 if (start
<0) start
+=360*64;
390 if (end
<0) end
+=360*64;
391 if (end
>start
) end
-=start
;
392 else end
+=360*64-start
;
394 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
396 m_autoSetting
= true; // must be reset
399 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
401 if (m_window
&& m_window
->GetBackingPixmap())
402 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
403 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
406 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
410 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
411 if (m_window
&& m_window
->GetBackingPixmap())
412 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
413 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
415 CalcBoundingBox (x
, y
);
416 CalcBoundingBox (x
+ width
, y
+ height
);
419 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
421 wxCHECK_RET( Ok(), "invalid dc" );
423 if (m_pen
.Ok() && m_autoSetting
)
426 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
427 if (m_window
&& m_window
->GetBackingPixmap())
428 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
430 CalcBoundingBox (x
, y
);
433 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
435 wxCHECK_RET( Ok(), "invalid dc" );
437 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
442 XPoint
*xpoints
= new XPoint
[n
];
445 for (i
= 0; i
< n
; i
++)
447 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
448 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
450 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
452 if (m_window
&& m_window
->GetBackingPixmap())
454 for (i
= 0; i
< n
; i
++)
456 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
457 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
459 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
465 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
466 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
468 wxCHECK_RET( Ok(), "invalid dc" );
470 XPoint
*xpoints1
= new XPoint
[n
+ 1];
471 XPoint
*xpoints2
= new XPoint
[n
+ 1];
473 for (i
= 0; i
< n
; i
++)
475 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
476 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
477 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
478 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
479 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
482 // Close figure for XDrawLines (not needed for XFillPolygon)
483 xpoints1
[i
].x
= xpoints1
[0].x
;
484 xpoints1
[i
].y
= xpoints1
[0].y
;
485 xpoints2
[i
].x
= xpoints2
[0].x
;
486 xpoints2
[i
].y
= xpoints2
[0].y
;
488 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
491 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
492 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
493 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
494 if (m_window
&& m_window
->GetBackingPixmap())
496 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
497 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
498 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
499 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
503 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
507 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
509 if (m_window
&& m_window
->GetBackingPixmap())
510 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
517 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
519 wxCHECK_RET( Ok(), "invalid dc" );
521 int xd
, yd
, wfd
, hfd
, wd
, hd
;
525 wfd
= XLOG2DEVREL(width
);
527 hfd
= YLOG2DEVREL(height
);
530 if (wfd
== 0 || hfd
== 0) return;
531 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
532 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
534 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
537 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
539 if (m_window
&& m_window
->GetBackingPixmap())
540 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
541 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
545 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
549 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
551 if (m_window
&& m_window
->GetBackingPixmap())
552 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
553 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
556 CalcBoundingBox (x
, y
);
557 CalcBoundingBox (x
+ width
, y
+ height
);
560 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
562 wxCHECK_RET( Ok(), "invalid dc" );
564 // If radius is negative, it's a proportion of the smaller dimension.
566 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
568 int xd
= XLOG2DEV (x
);
569 int yd
= YLOG2DEV (y
);
570 int rd
= XLOG2DEVREL ((long) radius
);
571 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
572 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
577 // If radius is zero use DrawRectangle() instead to avoid
578 // X drawing errors with small radii
581 DrawRectangle( x
, y
, width
, height
);
585 // Draw nothing if transformed w or h is 0
586 if (wd
== 0 || hd
== 0) return;
588 // CMB: adjust size if outline is drawn otherwise the result is
589 // 1 pixel too wide and high
590 if (m_pen
.GetStyle() != wxTRANSPARENT
)
596 // CMB: ensure dd is not larger than rectangle otherwise we
597 // get an hour glass shape
598 if (rw_d
> wd
) rw_d
= wd
;
599 if (rw_d
> hd
) rw_d
= hd
;
602 // For backing pixmap
603 int xd2
= XLOG2DEV_2 (x
);
604 int yd2
= YLOG2DEV_2 (y
);
605 int rd2
= XLOG2DEVREL ((long) radius
);
606 int wd2
= XLOG2DEVREL (width
) ;
607 int hd2
= YLOG2DEVREL (height
) ;
612 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
616 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
618 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
621 // Arcs start from 3 o'clock, positive angles anticlockwise
623 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
624 rw_d
, rh_d
, 90 * 64, 90 * 64);
626 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
627 // rw_d, rh_d, 0, 90 * 64);
628 rw_d
, rh_d
, 0, 91 * 64);
630 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
632 // rw_d, rh_d, 270 * 64, 90 * 64);
633 rw_d
, rh_d
, 269 * 64, 92 * 64);
635 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
636 rw_d
, rh_d
, 180 * 64, 90 * 64);
638 if (m_window
&& m_window
->GetBackingPixmap())
640 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
641 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
642 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
643 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
645 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
646 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
647 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
648 xd2
+ wd2
- rw_d2
, yd2
,
649 // rw_d2, rh_d2, 0, 90 * 64);
650 rw_d2
, rh_d2
, 0, 91 * 64);
651 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
654 // rw_d2, rh_d2, 270 * 64, 90 * 64);
655 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
656 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
657 xd2
, yd2
+ hd2
- rh_d2
,
658 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
662 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
665 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
666 xd
+ wd
- rd
+ 1, yd
);
667 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
668 xd
+ wd
- rd
, yd
+ hd
);
670 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
672 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
673 xd
+ wd
, yd
+ hd
- rd
+ 1);
674 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
675 rw_d
, rh_d
, 90 * 64, 90 * 64);
676 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
677 // rw_d, rh_d, 0, 90 * 64);
678 rw_d
, rh_d
, 0, 91 * 64);
679 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
681 rw_d
, rh_d
, 269 * 64, 92 * 64);
682 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
683 rw_d
, rh_d
, 180 * 64, 90 * 64);
685 if (m_window
&& m_window
->GetBackingPixmap())
687 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
689 xd2
+ wd2
- rd2
+ 1, yd2
);
690 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
691 xd2
+ rd2
, yd2
+ hd2
,
692 xd2
+ wd2
- rd2
, yd2
+ hd2
);
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
696 xd2
, yd2
+ hd2
- rd2
);
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
698 xd2
+ wd2
, yd2
+ rd2
,
699 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
700 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
702 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
703 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
704 xd2
+ wd2
- rw_d2
, yd2
,
705 // rw_d2, rh_d2, 0, 90 * 64);
706 rw_d2
, rh_d2
, 0, 91 * 64);
707 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
710 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
712 xd2
, yd2
+ hd2
- rh_d2
,
713 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
716 CalcBoundingBox (x
, y
);
717 CalcBoundingBox (x
+ width
, y
+ height
);
720 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
722 wxCHECK_RET( Ok(), "invalid dc" );
724 // Check for negative width and height
737 static const int angle
= 23040;
743 wd
= XLOG2DEVREL(width
) ;
744 hd
= YLOG2DEVREL(height
) ;
746 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
749 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
750 if (m_window
&& m_window
->GetBackingPixmap())
751 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
752 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
753 XLOG2DEVREL (width
) - WX_GC_CF
,
754 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
757 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
761 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
762 if (m_window
&& m_window
->GetBackingPixmap())
763 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
764 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
765 XLOG2DEVREL (width
) - WX_GC_CF
,
766 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
768 CalcBoundingBox (x
, y
);
769 CalcBoundingBox (x
+ width
, y
+ height
);
773 bool wxWindowDC::CanDrawBitmap() const
775 wxCHECK_MSG( Ok(), false, "invalid dc" );
780 // TODO: use scaled Blit e.g. as per John Price's implementation
781 // in Contrib/Utilities
782 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
783 wxCoord width
, wxCoord height
,
784 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
785 int rop
, bool useMask
,
786 wxCoord xsrcMask
, wxCoord ysrcMask
)
788 wxCHECK_MSG( Ok(), false, "invalid dc" );
790 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
792 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
794 // Be sure that foreground pixels (1) of the Icon will be painted with
795 // foreground colour. [m_textForegroundColour] Background pixels (0)
796 // will be painted with backgound colour (m_textBackgroundColour)
797 // Using ::SetPen is horribly slow, so avoid doing it
798 int oldBackgroundPixel
= -1;
799 int oldForegroundPixel
= -1;
801 if (m_textBackgroundColour
.Ok())
803 oldBackgroundPixel
= m_backgroundPixel
;
804 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
806 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
807 if (m_window
&& m_window
->GetBackingPixmap())
808 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
811 if (m_textForegroundColour
.Ok())
813 oldForegroundPixel
= m_currentColour
.GetPixel();
815 if( m_textForegroundColour
.GetPixel() <= -1 )
816 CalculatePixel( m_textForegroundColour
,
817 m_textForegroundColour
, true);
819 int pixel
= m_textForegroundColour
.GetPixel();
821 SetForegroundPixelWithLogicalFunction(pixel
);
824 // Do bitmap scaling if necessary
826 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
827 Pixmap sourcePixmap
= (Pixmap
) NULL
;
828 double scaleX
, scaleY
;
829 GetUserScale(& scaleX
, & scaleY
);
832 /* TODO: use the mask origin when drawing transparently */
833 if (xsrcMask
== -1 && ysrcMask
== -1)
835 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
838 // Sorry, can't scale masks just yet
839 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
841 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
842 wxBitmap
& bitmap
= memDC
->GetBitmap();
844 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
846 wxImage image
= bitmap
.ConvertToImage();
849 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
853 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
854 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
856 image
= image
.Scale(scaledW
, scaledH
);
857 scaledBitmap
= new wxBitmap(image
);
858 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
862 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
864 if (m_pixmap
&& sourcePixmap
)
867 int orig
= m_logicalFunction
;
869 SetLogicalFunction (rop
);
871 if (m_display
!= sourceDC
->m_display
)
873 XImage
*cache
= NULL
;
875 if (m_window
&& m_window
->GetBackingPixmap())
876 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
877 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
879 source
->LogicalToDeviceX (xsrc
),
880 source
->LogicalToDeviceY (ysrc
),
881 source
->LogicalToDeviceXRel(width
),
882 source
->LogicalToDeviceYRel(height
),
883 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
886 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
888 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
889 wxBitmap
& sel
= memDC
->GetBitmap();
890 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
892 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
893 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
897 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
898 source
->LogicalToDeviceX (xsrc
),
899 source
->LogicalToDeviceY (ysrc
),
900 source
->LogicalToDeviceXRel(width
),
901 source
->LogicalToDeviceYRel(height
),
902 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
908 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
909 (Region
) m_clipRegion
);
911 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
913 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
917 { //XGCValues values;
918 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
920 if (m_window
&& m_window
->GetBackingPixmap())
922 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
923 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
925 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
926 source
->LogicalToDeviceX (xsrc
),
927 source
->LogicalToDeviceY (ysrc
),
928 source
->LogicalToDeviceXRel(width
),
929 source
->LogicalToDeviceYRel(height
),
930 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
934 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
935 source
->LogicalToDeviceX (xsrc
),
936 source
->LogicalToDeviceY (ysrc
),
937 source
->LogicalToDeviceXRel(width
),
938 source
->LogicalToDeviceYRel(height
),
939 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
942 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
944 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
945 wxBitmap
& sel
= memDC
->GetBitmap();
946 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
948 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
949 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
953 // Check if we're copying from a mono bitmap
954 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
955 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
957 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
958 source
->LogicalToDeviceX (xsrc
),
959 source
->LogicalToDeviceY (ysrc
),
960 source
->LogicalToDeviceXRel(width
),
961 source
->LogicalToDeviceYRel(height
),
962 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
966 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
967 source
->LogicalToDeviceX (xsrc
),
968 source
->LogicalToDeviceY (ysrc
),
969 source
->LogicalToDeviceXRel(width
),
970 source
->LogicalToDeviceYRel(height
),
971 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
977 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
978 (Region
) m_clipRegion
);
980 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
982 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
985 } /* Remote/local (Display*) m_display */
986 CalcBoundingBox (xdest
, ydest
);
987 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
989 SetLogicalFunction(orig
);
993 if (scaledBitmap
) delete scaledBitmap
;
995 if (oldBackgroundPixel
> -1)
997 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
998 if (m_window
&& m_window
->GetBackingPixmap())
999 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1000 oldBackgroundPixel
);
1002 if (oldForegroundPixel
> -1)
1004 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1005 if (m_window
&& m_window
->GetBackingPixmap())
1006 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1007 oldForegroundPixel
);
1013 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1015 wxCHECK_RET( Ok(), "invalid dc" );
1017 // Since X draws from the baseline of the text, must add the text height
1021 int slen
= text
.length();
1023 // Set FillStyle, otherwise X will use current stipple!
1024 XGCValues gcV
, gcBackingV
;
1026 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1027 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1028 if (m_window
&& m_window
->GetBackingPixmap())
1030 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1032 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1036 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1037 text
, &cx
, &cy
, &ascent
, NULL
);
1039 // First draw a rectangle representing the text background, if a text
1040 // background is specified
1041 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1043 wxColour oldPenColour
= m_currentColour
;
1044 m_currentColour
= m_textBackgroundColour
;
1045 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1046 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1047 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1048 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1050 // This separation of the big && test required for gcc2.7/HP UX 9.02
1051 // or pixel value can be corrupted!
1052 sameColour
= (sameColour
&&
1053 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1055 if (!sameColour
|| !GET_OPTIMIZATION
)
1057 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1058 m_currentColour
= m_textBackgroundColour
;
1060 // Set the GC to the required colour
1063 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1064 if (m_window
&& m_window
->GetBackingPixmap())
1065 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1069 m_textBackgroundColour
= oldPenColour
;
1071 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1072 if (m_window
&& m_window
->GetBackingPixmap())
1073 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1074 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1077 // Now set the text foreground and draw the text
1078 if (m_textForegroundColour
.Ok ())
1080 wxColour oldPenColour
= m_currentColour
;
1081 m_currentColour
= m_textForegroundColour
;
1082 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1083 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1084 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1085 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1086 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1088 if (!sameColour
|| !GET_OPTIMIZATION
)
1090 int pixel
= CalculatePixel(m_textForegroundColour
,
1091 m_currentColour
, false);
1093 // Set the GC to the required colour
1096 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1097 if (m_window
&& m_window
->GetBackingPixmap())
1098 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1102 m_textForegroundColour
= oldPenColour
;
1105 // We need to add the ascent, not the whole height, since X draws at the
1106 // point above the descender.
1109 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1110 (XChar2b
*)(char*) (const char*) text
, slen
);
1113 #if wxMOTIF_NEW_FONT_HANDLING
1114 XFontSet fset
= (XFontSet
) m_font
.GetFontSet (m_userScaleY
* m_logicalScaleY
, m_display
);
1115 XmbDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, fset
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1117 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1120 if (m_window
&& m_window
->GetBackingPixmap()) {
1123 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1124 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1125 (XChar2b
*)(char*) (const char*) text
, slen
);
1128 #if wxMOTIF_NEW_FONT_HANDLING
1129 XmbDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), fset
, (GC
) m_gcBacking
,
1130 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1131 wxConstCast(text
.c_str(), char), slen
);
1133 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1134 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1135 wxConstCast(text
.c_str(), char), slen
);
1139 // restore fill style
1140 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1141 if (m_window
&& m_window
->GetBackingPixmap())
1142 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1143 gcBackingV
.fill_style
);
1146 GetTextExtent (text
, &w
, &h
);
1147 CalcBoundingBox (x
+ w
, y
+ h
);
1148 CalcBoundingBox (x
, y
);
1151 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1156 DrawText(text
, x
, y
);
1160 wxCHECK_RET( Ok(), "invalid dc" );
1162 int oldBackgroundPixel
= -1;
1163 int oldForegroundPixel
= -1;
1164 int foregroundPixel
= -1;
1165 int backgroundPixel
= -1;
1167 if (m_textBackgroundColour
.Ok())
1169 oldBackgroundPixel
= m_backgroundPixel
;
1170 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1172 if (m_textForegroundColour
.Ok())
1174 oldForegroundPixel
= m_currentColour
.GetPixel();
1176 if( m_textForegroundColour
.GetPixel() <= -1 )
1177 CalculatePixel( m_textForegroundColour
,
1178 m_textForegroundColour
, true);
1180 foregroundPixel
= m_textForegroundColour
.GetPixel();
1183 // Since X draws from the baseline of the text, must add the text height
1189 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1190 text
, &cx
, &cy
, &ascent
, NULL
);
1192 wxBitmap
src(cx
, cy
);
1194 dc
.SelectObject(src
);
1195 dc
.SetFont(GetFont());
1196 dc
.SetBackground(*wxWHITE_BRUSH
);
1197 dc
.SetBrush(*wxBLACK_BRUSH
);
1199 dc
.DrawText(text
, 0, 0);
1200 dc
.SetFont(wxNullFont
);
1202 // Calculate the size of the rotated bounding box.
1203 double dx
= cos(angle
/ 180.0 * M_PI
);
1204 double dy
= sin(angle
/ 180.0 * M_PI
);
1205 double x4
= cy
* dy
;
1206 double y4
= cy
* dx
;
1207 double x3
= cx
* dx
;
1208 double y3
= -cx
* dy
;
1209 double x2
= x3
+ x4
;
1210 double y2
= y3
+ y4
;
1214 // Create image from the source bitmap after writing the text into it.
1215 wxImage image
= src
.ConvertToImage();
1217 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1218 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1219 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1220 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1222 bool lastFore
= false, lastBack
= false;
1224 // This rotates counterclockwise around the top left corner.
1225 for (int rx
= minx
; rx
< maxx
; rx
++)
1227 for (int ry
= miny
; ry
< maxy
; ry
++)
1229 // transform dest coords to source coords
1230 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1231 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1232 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1234 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1236 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1239 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1240 oy
= (wxCoord
) (y1
+ ry
);
1241 // draw black pixels, ignore white ones (i.e. transparent b/g)
1242 if (textPixel
&& !lastFore
)
1244 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1249 else if (!textPixel
&& !lastBack
)
1251 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1257 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1258 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1259 if (m_window
&& m_window
->GetBackingPixmap())
1260 XDrawPoint ((Display
*) m_display
,
1261 (Pixmap
) m_window
->GetBackingPixmap(),
1263 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1268 if (oldBackgroundPixel
> -1)
1270 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1271 if (m_window
&& m_window
->GetBackingPixmap())
1272 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1273 oldBackgroundPixel
);
1275 if (oldForegroundPixel
> -1)
1277 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1278 if (m_window
&& m_window
->GetBackingPixmap())
1279 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1280 oldForegroundPixel
);
1283 CalcBoundingBox (minx
, miny
);
1284 CalcBoundingBox (maxx
, maxy
);
1287 bool wxWindowDC::CanGetTextExtent() const
1292 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1293 wxCoord
*descent
, wxCoord
*externalLeading
,
1294 wxFont
*font
) const
1296 wxCHECK_RET( Ok(), "invalid dc" );
1298 const wxFont
* theFont
= font
? font
: &m_font
;
1302 // TODO: this should be an error log function
1303 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1305 if (width
) *width
= -1;
1306 if (height
) *height
= -1;
1310 wxGetTextExtent(m_display
, *theFont
, m_userScaleY
* m_logicalScaleY
,
1311 string
, width
, height
, NULL
, descent
);
1313 if (width
) *width
= XDEV2LOGREL (*width
);
1314 if (height
) *height
= YDEV2LOGREL (*height
);
1315 if (externalLeading
)
1316 *externalLeading
= 0;
1319 wxCoord
wxWindowDC::GetCharWidth() const
1321 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1322 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1326 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1327 "x", &width
, NULL
, NULL
, NULL
);
1329 return XDEV2LOGREL(width
);
1332 wxCoord
wxWindowDC::GetCharHeight() const
1334 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1335 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1339 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1340 "x", NULL
, &height
, NULL
, NULL
);
1342 return XDEV2LOGREL(height
);
1345 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1351 if( m_window
->GetBackingPixmap() )
1353 w
= m_window
->GetPixmapWidth();
1354 h
= m_window
->GetPixmapHeight();
1357 m_window
->GetSize( &w
, &h
);
1360 if( width
) *width
= w
;
1361 if( height
) *height
= h
;
1364 void wxWindowDC::Clear()
1366 wxCHECK_RET( Ok(), "invalid dc" );
1368 wxRect
rect( GetSize() );
1372 void wxWindowDC::Clear(const wxRect
& rect
)
1374 wxCHECK_RET( Ok(), "invalid dc" );
1376 int x
= rect
.x
; int y
= rect
.y
;
1377 int w
= rect
.width
; int h
= rect
.height
;
1379 wxBrush saveBrush
= m_brush
;
1380 SetBrush (m_backgroundBrush
);
1382 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1385 if (m_window
&& m_window
->GetBackingPixmap())
1386 XFillRectangle ((Display
*) m_display
,
1387 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1390 m_brush
= saveBrush
;
1393 void wxWindowDC::SetFont( const wxFont
&font
)
1395 wxCHECK_RET( Ok(), "invalid dc" );
1404 #if !wxMOTIF_NEW_FONT_HANDLING
1405 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1407 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1408 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1410 if (m_window
&& m_window
->GetBackingPixmap())
1411 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1415 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1417 if (m_logicalFunction
== wxXOR
)
1420 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1421 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1422 pixel
^ values
.background
);
1423 if (m_window
&& m_window
->GetBackingPixmap())
1424 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1425 pixel
^ values
.background
);
1429 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1430 if (m_window
&& m_window
->GetBackingPixmap())
1431 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1435 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1436 bool roundToWhite
) const
1438 const unsigned char wp
= (unsigned char)255;
1441 if(!m_colour
) // Mono display
1443 unsigned char red
= colour
.Red ();
1444 unsigned char blue
= colour
.Blue ();
1445 unsigned char green
= colour
.Green ();
1447 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1448 // not black and roundToWhite was specified
1449 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1452 pixel
= (int)WhitePixel((Display
*) m_display
,
1453 DefaultScreen((Display
*) m_display
));
1454 curCol
.SetPixel(pixel
);
1455 colour
.SetPixel(pixel
);
1460 pixel
= (int)BlackPixel((Display
*) m_display
,
1461 DefaultScreen((Display
*) m_display
));
1462 curCol
.SetPixel(pixel
);
1463 colour
.SetPixel(pixel
);
1469 pixel
= colour
.AllocColour((Display
*) m_display
);
1470 curCol
.SetPixel(pixel
);
1476 void wxWindowDC::SetPen( const wxPen
&pen
)
1478 wxCHECK_RET( Ok(), "invalid dc" );
1484 wxBitmap oldStipple
= m_currentStipple
;
1485 int oldStyle
= m_currentStyle
;
1486 int oldFill
= m_currentFill
;
1487 int old_pen_width
= m_currentPenWidth
;
1488 int old_pen_join
= m_currentPenJoin
;
1489 int old_pen_cap
= m_currentPenCap
;
1490 int old_pen_nb_dash
= m_currentPenDashCount
;
1491 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1493 wxColour oldPenColour
= m_currentColour
;
1494 m_currentColour
= m_pen
.GetColour ();
1495 m_currentStyle
= m_pen
.GetStyle ();
1496 m_currentFill
= m_pen
.GetStyle (); // TODO?
1497 m_currentPenWidth
= m_pen
.GetWidth ();
1498 m_currentPenJoin
= m_pen
.GetJoin ();
1499 m_currentPenCap
= m_pen
.GetCap ();
1500 m_currentPenDashCount
= m_pen
.GetDashCount();
1501 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1503 if (m_currentStyle
== wxSTIPPLE
)
1504 m_currentStipple
= * m_pen
.GetStipple ();
1506 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1507 oldFill
== m_currentFill
&&
1508 old_pen_join
== m_currentPenJoin
&&
1509 old_pen_cap
== m_currentPenCap
&&
1510 old_pen_nb_dash
== m_currentPenDashCount
&&
1511 old_pen_dash
== m_currentPenDash
&&
1512 old_pen_width
== m_currentPenWidth
);
1514 bool sameColour
= (oldPenColour
.Ok () &&
1515 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1516 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1517 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1518 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1520 if (!sameStyle
|| !GET_OPTIMIZATION
)
1522 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1523 if (scaled_width
< 0)
1529 static const wxX11Dash dotted
[] = {2, 5};
1530 static const wxX11Dash short_dashed
[] = {4, 4};
1531 static const wxX11Dash long_dashed
[] = {4, 8};
1532 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1534 // We express dash pattern in pen width unit, so we are
1535 // independent of zoom factor and so on...
1537 const wxX11Dash
*req_dash
;
1539 switch (m_pen
.GetStyle ())
1542 req_nb_dash
= m_currentPenDashCount
;
1543 req_dash
= m_currentPenDash
;
1544 style
= LineOnOffDash
;
1549 style
= LineOnOffDash
;
1553 req_dash
= short_dashed
;
1554 style
= LineOnOffDash
;
1558 req_dash
= long_dashed
;
1559 style
= LineOnOffDash
;
1563 req_dash
= dotted_dashed
;
1564 style
= LineOnOffDash
;
1571 req_dash
= (wxX11Dash
*)NULL
;
1575 if (req_dash
&& req_nb_dash
)
1577 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1580 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1581 for (int i
= 0; i
< req_nb_dash
; i
++)
1582 real_req_dash
[i
] = req_dash
[i
] * factor
;
1583 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1585 if (m_window
&& m_window
->GetBackingPixmap())
1586 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1587 delete[]real_req_dash
;
1591 // No Memory. We use non-scaled dash pattern...
1592 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1594 if (m_window
&& m_window
->GetBackingPixmap())
1595 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1599 switch (m_pen
.GetCap ())
1601 case wxCAP_PROJECTING
:
1602 cap
= CapProjecting
;
1609 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1613 switch (m_pen
.GetJoin ())
1627 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1629 if (m_window
&& m_window
->GetBackingPixmap())
1630 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1633 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1637 oldStipple
= wxNullBitmap
; // For later reset!!
1639 switch (m_currentFill
)
1641 case wxBDIAGONAL_HATCH
:
1642 if (bdiag
== (Pixmap
) 0)
1643 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1644 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1645 bdiag_bits
, bdiag_width
, bdiag_height
);
1648 case wxFDIAGONAL_HATCH
:
1649 if (fdiag
== (Pixmap
) 0)
1650 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1651 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1652 fdiag_bits
, fdiag_width
, fdiag_height
);
1656 if (cross
== (Pixmap
) 0)
1657 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1658 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1659 cross_bits
, cross_width
, cross_height
);
1662 case wxHORIZONTAL_HATCH
:
1663 if (horiz
== (Pixmap
) 0)
1664 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1665 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1666 horiz_bits
, horiz_width
, horiz_height
);
1669 case wxVERTICAL_HATCH
:
1670 if (verti
== (Pixmap
) 0)
1671 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1672 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1673 verti_bits
, verti_width
, verti_height
);
1676 case wxCROSSDIAG_HATCH
:
1678 if (cdiag
== (Pixmap
) 0)
1679 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1680 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1681 cdiag_bits
, cdiag_width
, cdiag_height
);
1685 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1687 if (m_window
&& m_window
->GetBackingPixmap())
1688 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1690 else if (m_currentStipple
.Ok()
1691 && ((m_currentStipple
!= oldStipple
) || !GET_OPTIMIZATION
))
1693 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1695 if (m_window
&& m_window
->GetBackingPixmap())
1696 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1699 if ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
)
1703 if (m_currentFill
== wxSTIPPLE
)
1704 fill_style
= FillStippled
;
1705 else if (IS_HATCH (m_currentFill
))
1706 fill_style
= FillStippled
;
1708 fill_style
= FillSolid
;
1709 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1710 if (m_window
&& m_window
->GetBackingPixmap())
1711 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1714 // must test m_logicalFunction, because it involves background!
1715 if (!sameColour
|| !GET_OPTIMIZATION
1716 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1719 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1720 pixel
= m_backgroundPixel
;
1723 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, false);
1726 // Finally, set the GC to the required colour
1728 SetForegroundPixelWithLogicalFunction(pixel
);
1731 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1736 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1738 wxCHECK_RET( Ok(), "invalid dc" );
1742 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1745 int oldFill
= m_currentFill
;
1746 wxBitmap oldStipple
= m_currentStipple
;
1748 m_autoSetting
|= 0x1;
1750 m_currentFill
= m_brush
.GetStyle ();
1751 if (m_currentFill
== wxSTIPPLE
)
1752 m_currentStipple
= * m_brush
.GetStipple ();
1754 wxColour
oldBrushColour(m_currentColour
);
1755 m_currentColour
= m_brush
.GetColour ();
1757 bool sameColour
= (oldBrushColour
.Ok () &&
1758 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1759 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1760 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1761 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1763 int stippleDepth
= -1;
1765 if ((oldFill
!= m_brush
.GetStyle ()) || !GET_OPTIMIZATION
)
1767 switch (brush
.GetStyle ())
1772 stippleDepth
= m_currentStipple
.GetDepth();
1774 case wxBDIAGONAL_HATCH
:
1775 case wxCROSSDIAG_HATCH
:
1776 case wxFDIAGONAL_HATCH
:
1778 case wxHORIZONTAL_HATCH
:
1779 case wxVERTICAL_HATCH
:
1781 if (stippleDepth
== -1) stippleDepth
= 1;
1783 // Chris Breeze 23/07/97: use background mode to
1784 // determine whether fill style should be solid or
1786 int style
= stippleDepth
== 1 ?
1787 (m_backgroundMode
== wxSOLID
?
1788 FillOpaqueStippled
: FillStippled
) :
1790 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1791 if (m_window
&& m_window
->GetBackingPixmap())
1792 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1797 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1798 if (m_window
&& m_window
->GetBackingPixmap())
1799 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1804 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1808 switch (m_currentFill
)
1810 case wxBDIAGONAL_HATCH
:
1811 if (bdiag
== (Pixmap
) 0)
1812 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1813 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1814 bdiag_bits
, bdiag_width
, bdiag_height
);
1817 case wxFDIAGONAL_HATCH
:
1818 if (fdiag
== (Pixmap
) 0)
1819 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1820 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1821 fdiag_bits
, fdiag_width
, fdiag_height
);
1825 if (cross
== (Pixmap
) 0)
1826 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1827 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1828 cross_bits
, cross_width
, cross_height
);
1831 case wxHORIZONTAL_HATCH
:
1832 if (horiz
== (Pixmap
) 0)
1833 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1834 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1835 horiz_bits
, horiz_width
, horiz_height
);
1838 case wxVERTICAL_HATCH
:
1839 if (verti
== (Pixmap
) 0)
1840 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1841 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1842 verti_bits
, verti_width
, verti_height
);
1845 case wxCROSSDIAG_HATCH
:
1847 if (cdiag
== (Pixmap
) 0)
1848 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1849 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1850 cdiag_bits
, cdiag_width
, cdiag_height
);
1854 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1856 if (m_window
&& m_window
->GetBackingPixmap())
1857 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1859 // X can forget the stipple value when resizing a window (apparently)
1860 // so always set the stipple.
1861 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1862 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1864 if (m_currentStipple
.GetDepth() == 1)
1866 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1867 (Pixmap
) m_currentStipple
.GetDrawable());
1868 if (m_window
&& m_window
->GetBackingPixmap())
1869 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1870 (Pixmap
) m_currentStipple
.GetDrawable());
1874 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1875 (Pixmap
) m_currentStipple
.GetDrawable());
1876 if (m_window
&& m_window
->GetBackingPixmap())
1877 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1878 (Pixmap
) m_currentStipple
.GetDrawable());
1882 // must test m_logicalFunction, because it involves background!
1883 if (!sameColour
|| !GET_OPTIMIZATION
|| m_logicalFunction
== wxXOR
)
1885 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, true);
1888 SetForegroundPixelWithLogicalFunction(pixel
);
1891 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1894 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1896 wxCHECK_RET( Ok(), "invalid dc" );
1898 m_backgroundBrush
= brush
;
1900 if (!m_backgroundBrush
.Ok())
1903 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1905 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1906 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1907 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1908 if (m_window
&& m_window
->GetBackingPixmap())
1909 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1913 void wxWindowDC::SetLogicalFunction( int function
)
1915 wxCHECK_RET( Ok(), "invalid dc" );
1920 if (m_logicalFunction
== function
)
1926 x_function
= GXclear
;
1932 x_function
= GXinvert
;
1935 x_function
= GXorReverse
;
1938 x_function
= GXandReverse
;
1947 x_function
= GXandInverted
;
1950 x_function
= GXnoop
;
1956 x_function
= GXequiv
;
1959 x_function
= GXcopyInverted
;
1962 x_function
= GXorInverted
;
1965 x_function
= GXnand
;
1972 x_function
= GXcopy
;
1976 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1977 if (m_window
&& m_window
->GetBackingPixmap())
1978 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1980 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1981 /* MATTHEW: [9] Need to redo pen simply */
1982 m_autoSetting
|= 0x2;
1984 m_logicalFunction
= function
;
1988 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1990 wxCHECK_RET( Ok(), "invalid dc" );
1992 m_textForegroundColour
= col
;
1995 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1997 wxCHECK_RET( Ok(), "invalid dc" );
1999 m_textBackgroundColour
= col
;
2002 void wxWindowDC::SetBackgroundMode( int mode
)
2004 m_backgroundMode
= mode
;
2007 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2012 /* Use GetXColormap */
2013 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2014 (Colormap
) palette
.GetXColormap());
2016 /* Use wxGetMainColormap */
2017 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2018 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2022 static void wxCopyRegion( WXRegion src
, WXRegion
& dst
)
2025 dst
= XCreateRegion();
2026 XUnionRegion( (Region
)src
, (Region
)src
, (Region
)dst
);
2029 // Helper function; userRegion is the region set by calling SetClippingRegion
2030 void wxWindowDC::SetDCClipping( WXRegion userRegion
)
2032 bool hasUpdateRegion
= m_window
&& m_window
->GetUpdateRegion().Ok();
2033 // this means that we should start the clip region from scratch,
2034 // or from the update region, if any
2038 XDestroyRegion( (Region
)m_clipRegion
);
2039 m_clipRegion
= (WXRegion
)NULL
;
2041 if( hasUpdateRegion
)
2042 wxCopyRegion( m_window
->GetUpdateRegion().GetX11Region(),
2045 // intersect the user region, if any, with the
2046 // exisiting clip region
2047 else // if( userRegion )
2050 wxCopyRegion( userRegion
, m_clipRegion
);
2052 XIntersectRegion( (Region
)m_clipRegion
,
2053 (Region
)userRegion
, (Region
)m_clipRegion
);
2057 XSetRegion( (Display
*)m_display
, (GC
)m_gc
, (Region
)m_clipRegion
);
2059 XSetClipMask( (Display
*)m_display
, (GC
)m_gc
, None
);
2062 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
,
2063 wxCoord width
, wxCoord height
)
2065 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2067 wxRegion
temp(x
, y
, width
, height
);
2069 SetDCClipping(temp
.GetX11Region());
2071 // Needs to work differently for Pixmap: without this,
2072 // there's a nasty (Display*) m_display bug. 8/12/94
2073 if (m_window
&& m_window
->GetBackingPixmap())
2075 XRectangle rects
[1];
2076 rects
[0].x
= XLOG2DEV_2(x
);
2077 rects
[0].y
= YLOG2DEV_2(y
);
2078 rects
[0].width
= XLOG2DEVREL(width
);
2079 rects
[0].height
= YLOG2DEVREL(height
);
2080 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2081 0, 0, rects
, 1, Unsorted
);
2085 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2087 wxRect box
= region
.GetBox();
2089 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2091 SetDCClipping(region
.GetX11Region());
2093 // Needs to work differently for Pixmap: without this,
2094 // there's a nasty (Display*) m_display bug. 8/12/94
2095 if (m_window
&& m_window
->GetBackingPixmap())
2097 XRectangle rects
[1];
2098 rects
[0].x
= XLOG2DEV_2(box
.x
);
2099 rects
[0].y
= YLOG2DEV_2(box
.y
);
2100 rects
[0].width
= XLOG2DEVREL(box
.width
);
2101 rects
[0].height
= YLOG2DEVREL(box
.height
);
2102 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2103 0, 0, rects
, 1, Unsorted
);
2108 void wxWindowDC::DestroyClippingRegion()
2110 wxDC::DestroyClippingRegion();
2112 SetDCClipping(NULL
);
2114 if (m_window
&& m_window
->GetBackingPixmap())
2115 XSetClipMask ((Display
*) m_display
, (GC
) m_gcBacking
, None
);
2118 // Resolution in pixels per logical inch
2119 wxSize
wxWindowDC::GetPPI() const
2122 return wxSize(100, 100);
2125 int wxWindowDC::GetDepth() const
2134 // ----------------------------------------------------------------------------
2136 // ----------------------------------------------------------------------------
2138 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2140 // Set the clipping region.to the update region
2141 SetDCClipping((WXRegion
)NULL
);
2144 wxPaintDC::~wxPaintDC()
2147 m_window
->ClearUpdateRegion();
2148 SetDCClipping((WXRegion
)NULL
);
2151 // ----------------------------------------------------------------------------
2152 // private functions
2153 // ----------------------------------------------------------------------------
2156 Used when copying between drawables on different (Display*) m_displays. Not
2157 very fast, but better than giving up.
2160 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2161 Drawable src
, Drawable dest
,
2164 unsigned int w
, unsigned int h
,
2165 int destx
, int desty
,
2166 bool more
, XImage
**cache
)
2168 XImage
*image
, *destimage
;
2169 Colormap destcm
, srccm
;
2170 static const int CACHE_SIZE
= 256;
2173 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2174 int k
, cache_pos
, all_cache
;
2176 if (!cache
|| !*cache
)
2177 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2181 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2183 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2184 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2189 for (i
= 0; i
< w
; i
++)
2190 for (j
= 0; j
< h
; j
++) {
2191 unsigned long pixel
;
2194 pixel
= XGetPixel(image
, i
, j
);
2195 for (k
= cache_pos
; k
--; )
2196 if (cachesrc
[k
] == pixel
) {
2197 pixel
= cachedest
[k
];
2201 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2202 if (cachesrc
[k
] == pixel
) {
2203 pixel
= cachedest
[k
];
2207 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2208 XQueryColor(src_display
, srccm
, &xcol
);
2209 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2211 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2213 if (++cache_pos
>= CACHE_SIZE
) {
2219 XPutPixel(destimage
, i
, j
, pixel
);
2222 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2223 XDestroyImage(destimage
);
2228 XDestroyImage(image
);
2233 /* Helper function for 16-bit fonts */
2234 static int str16len(const char *s
)
2238 while (s
[0] && s
[1]) {